From 7717bf81cbd3cc2938a6a2c0a340711c54aea5e6 Mon Sep 17 00:00:00 2001 From: max143672 Date: Sun, 27 Nov 2022 11:12:33 +0400 Subject: [PATCH 001/239] add actix-web example --- actix-web/hello-world/Cargo.toml | 10 ++++++++++ actix-web/hello-world/Shuttle.toml | 1 + actix-web/hello-world/src/lib.rs | 14 ++++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 actix-web/hello-world/Cargo.toml create mode 100644 actix-web/hello-world/Shuttle.toml create mode 100644 actix-web/hello-world/src/lib.rs diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml new file mode 100644 index 00000000..b4308725 --- /dev/null +++ b/actix-web/hello-world/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "hello-world" +version = "0.1.0" +edition = "2021" + +[dependencies] +actix-web = "4.2.1" +actix-service = "2.0.2" +shuttle-service = { version = '0.7.2', path = '../../../service', features = ["web-actix-web"] } + diff --git a/actix-web/hello-world/Shuttle.toml b/actix-web/hello-world/Shuttle.toml new file mode 100644 index 00000000..df9da3fe --- /dev/null +++ b/actix-web/hello-world/Shuttle.toml @@ -0,0 +1 @@ +name = "hello-world-actix-web-app" \ No newline at end of file diff --git a/actix-web/hello-world/src/lib.rs b/actix-web/hello-world/src/lib.rs new file mode 100644 index 00000000..1abb12c9 --- /dev/null +++ b/actix-web/hello-world/src/lib.rs @@ -0,0 +1,14 @@ +use actix_web::web::{resource, ServiceConfig}; +use shuttle_service::{ShuttleActixWeb}; + +async fn hello_world() -> &'static str { + "Hello World!" +} + +#[shuttle_service::main] +async fn actix_web() -> ShuttleActixWeb { + let h = hello_world; + Ok(move |cfg: &mut ServiceConfig| { + cfg.service(resource("/").to(h)); + }) +} From 2a90ae3004116d05f0592ad37dad8918b4804eda Mon Sep 17 00:00:00 2001 From: maksim Date: Mon, 28 Nov 2022 17:24:41 +0400 Subject: [PATCH 002/239] use git dependency instead of path --- actix-web/hello-world/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index b4308725..9adece97 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" [dependencies] actix-web = "4.2.1" actix-service = "2.0.2" -shuttle-service = { version = '0.7.2', path = '../../../service', features = ["web-actix-web"] } +shuttle-service = { version = '0.7.2', git = "ssh://git@github.com/biryukovmaxim/shuttle.git", branch = "feature/support-actix-web", features = ["web-actix-web"] } From 8078fed4cb51e975d31002d24b786c5c9ed899c5 Mon Sep 17 00:00:00 2001 From: oddgrd <29732646+oddgrd@users.noreply.github.com> Date: Mon, 28 Nov 2022 19:24:46 +0100 Subject: [PATCH 003/239] feat: bump example deps --- axum/hello-world/Cargo.toml | 4 ++-- axum/websocket/Cargo.toml | 18 +++++++++--------- poem/hello-world/Cargo.toml | 2 +- poem/mongodb/Cargo.toml | 8 ++++---- poem/postgres/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 8 ++++---- rocket/persist/Cargo.toml | 4 ++-- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 8 ++++---- salvo/hello-world/Cargo.toml | 2 +- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 8 ++++---- thruster/postgres/Cargo.toml | 8 ++++---- tide/postgres/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 2 +- 17 files changed, 50 insertions(+), 50 deletions(-) diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 1f551d11..442605ae 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [lib] [dependencies] -axum = "0.5" +axum = "0.6.0" shuttle-service = { version = "0.7.2", features = ["web-axum"] } -sync_wrapper = "0.1" +sync_wrapper = "0.1.1" diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 5a708fa5..7d889db1 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -6,13 +6,13 @@ edition = "2021" [lib] [dependencies] -axum = { version = "0.5", features = ["ws"] } -chrono = { version = "0.4", features = ["serde"] } -futures = "0.3" -hyper = { version = "0.14", features = ["client", "http2"] } -hyper-tls = "0.5" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" +axum = { version = "0.6.0", features = ["ws"] } +chrono = { version = "0.4.23", features = ["serde"] } +futures = "0.3.25" +hyper = { version = "0.14.23", features = ["client", "http2"] } +hyper-tls = "0.5.0" +serde = { version = "1.0.148", features = ["derive"] } +serde_json = "1.0.89" shuttle-service = { version = "0.7.2", features = ["web-axum"] } -sync_wrapper = "0.1" -tokio = { version = "1", features = ["full"] } +sync_wrapper = "0.1.1" +tokio = { version = "1.22.0", features = ["full"] } diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index a5cc529b..b4ebed08 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" [lib] [dependencies] -poem = "1.3.35" +poem = "1.3.49" shuttle-service = { version = "0.7.2", features = ["web-poem"] } diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index ec284f2e..fe760856 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -4,9 +4,9 @@ version = "0.1.0" edition = "2021" [dependencies] -mongodb = "2.3.0" -poem = "1.3.35" -serde = { version = "1", features = ["derive"] } -serde_json = "1" +mongodb = "2.3.1" +poem = "1.3.49" +serde = { version = "1.0.148", features = ["derive"] } +serde_json = "1.0.89" shuttle-service = { version = "0.7.2", features = ["web-poem"] } shuttle-shared-db = { version = "0.7.2", features = ["mongodb"] } diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index c8223d3e..3cc822e9 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [lib] [dependencies] -poem = "1.3.35" -serde = "1.0" +poem = "1.3.49" +serde = "1.0.148" shuttle-service = { version = "0.7.2", features = ["web-poem"] } shuttle-shared-db = { version = "0.7.2", features = ["postgres"] } -sqlx = { version = "0.6", features = ["runtime-tokio-native-tls", "postgres"] } +sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index 318e3622..37282f7b 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [lib] [dependencies] -chrono = "0.4" -jsonwebtoken = { version = "8", default-features = false } -lazy_static = "1.4" +chrono = "0.4.23" +jsonwebtoken = { version = "8.1.1", default-features = false } +lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -serde = { version = "1.0", features = ["derive"] } +serde = { version = "1.0.148", features = ["derive"] } shuttle-service = { version = "0.7.2", features = ["web-rocket"] } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 39e779f5..48527a56 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [lib] [dependencies] -rocket = { version = "0.5.0-rc.1", features = ["json"] } -serde = { version = "1.0", features = ["derive"] } +rocket = { version = "0.5.0-rc.2", features = ["json"] } +serde = { version = "1.0.148", features = ["derive"] } shuttle-persist = "0.7.2" shuttle-service = { version = "0.7.2", features = ["web-rocket"] } diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 31d64bf8..c120c8fc 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [lib] [dependencies] -rocket = { version = "0.5.0-rc.1", features = ["json"] } -serde = "1.0" +rocket = { version = "0.5.0-rc.2", features = ["json"] } +serde = "1.0.148" shuttle-service = { version = "0.7.2", features = ["web-rocket"] } shuttle-shared-db = { version = "0.7.2", features = ["postgres"] } -sqlx = { version = "0.6", features = ["runtime-tokio-native-tls", "postgres"] } +sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index dda655d0..3207ef81 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [lib] [dependencies] -anyhow = "1.0.62" -rocket = { version = "0.5.0-rc.1", features = ["json"] } +anyhow = "1.0.66" +rocket = { version = "0.5.0-rc.2", features = ["json"] } shuttle-secrets = "0.7.2" shuttle-service = { version = "0.7.2", features = ["web-rocket"] } diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index adcb3229..ed5245f8 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [lib] [dependencies] -nanoid = "0.4" +nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -serde = "1.0" +serde = "1.0.148" shuttle-service = { version = "0.7.2", features = ["web-rocket"] } shuttle-shared-db = { version = "0.7.2", features = ["postgres"] } -sqlx = { version = "0.6", features = ["runtime-tokio-native-tls", "postgres"] } -url = "2.2" +sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } +url = "2.3.1" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 98f6619b..9165c116 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" [lib] [dependencies] -salvo = "0.34.3" +salvo = "0.37.5" shuttle-service = { version = "0.7.2", features = ["web-salvo"] } diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 469a8031..ad844287 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [lib] [dependencies] -anyhow = "1.0.62" +anyhow = "1.0.66" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } shuttle-secrets = "0.7.2" shuttle-service = { version = "0.7.2", features = ["bot-serenity"] } -tracing = "0.1.35" +tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index ee84698b..4799078d 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -6,11 +6,11 @@ edition = "2021" [lib] [dependencies] -anyhow = "1.0.62" -serde = "1.0" +anyhow = "1.0.66" +serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } shuttle-secrets = "0.7.2" shuttle-service = { version = "0.7.2", features = ["bot-serenity"] } shuttle-shared-db = { version = "0.7.2", features = ["postgres"] } -sqlx = { version = "0.6", features = ["runtime-tokio-native-tls", "postgres"] } -tracing = "0.1.35" +sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } +tracing = "0.1.37" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index c9242c32..aaeae35c 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -8,10 +8,10 @@ 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" } +hyper = "0.14.23" +serde = { version = "1.0.148", features = ["derive"] } +serde_json = "1.0.89" shuttle-aws-rds = { version = "0.7.2", features = ["postgres"] } shuttle-service = { version = "0.7.2", features = ["web-thruster"] } -sqlx = { version = "0.6", features = ["runtime-tokio-native-tls", "postgres"] } +sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index eaa99a61..ef4ebfb6 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -8,8 +8,8 @@ crate-type = ["cdylib"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -serde = { version = "1.0", features = ["derive"] } +serde = { version = "1.0.148", features = ["derive"] } shuttle-aws-rds = { version = "0.7.2", features = ["postgres"] } shuttle-service = { version = "0.7.2", features = ["web-tide"] } -sqlx = { version = "0.6", features = ["runtime-tokio-native-tls", "postgres"] } +sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 678b43b6..1d150c5a 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [lib] [dependencies] -hyper = { version = "0.14", features = ["full"] } +hyper = { version = "0.14.23", features = ["full"] } shuttle-service = { version = "0.7.2", features = ["web-tower"] } -tower = { version = "0.4", features = ["full"] } +tower = { version = "0.4.13", features = ["full"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index a86ecd3b..012f75c1 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] shuttle-service = { version = "0.7.2", features = ["web-warp"] } -warp = "0.3.2" +warp = "0.3.3" From f89bae05313463a8bb5a9b48735d7bd4a36f0552 Mon Sep 17 00:00:00 2001 From: max143672 Date: Mon, 28 Nov 2022 22:27:43 +0400 Subject: [PATCH 004/239] fmt + sort --- actix-web/hello-world/Cargo.toml | 2 +- actix-web/hello-world/src/lib.rs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 9adece97..d4d99aa2 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -actix-web = "4.2.1" actix-service = "2.0.2" +actix-web = "4.2.1" shuttle-service = { version = '0.7.2', git = "ssh://git@github.com/biryukovmaxim/shuttle.git", branch = "feature/support-actix-web", features = ["web-actix-web"] } diff --git a/actix-web/hello-world/src/lib.rs b/actix-web/hello-world/src/lib.rs index 1abb12c9..0675ee56 100644 --- a/actix-web/hello-world/src/lib.rs +++ b/actix-web/hello-world/src/lib.rs @@ -1,12 +1,13 @@ use actix_web::web::{resource, ServiceConfig}; -use shuttle_service::{ShuttleActixWeb}; +use shuttle_service::ShuttleActixWeb; async fn hello_world() -> &'static str { "Hello World!" } #[shuttle_service::main] -async fn actix_web() -> ShuttleActixWeb { +async fn actix_web( +) -> ShuttleActixWeb { let h = hello_world; Ok(move |cfg: &mut ServiceConfig| { cfg.service(resource("/").to(h)); From a3ef4e1a915855d59f10b1fcec8795bb09978169 Mon Sep 17 00:00:00 2001 From: maksim Date: Tue, 29 Nov 2022 09:43:03 +0400 Subject: [PATCH 005/239] /hello endpoint --- actix-web/hello-world/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-web/hello-world/src/lib.rs b/actix-web/hello-world/src/lib.rs index 0675ee56..a6ded2fe 100644 --- a/actix-web/hello-world/src/lib.rs +++ b/actix-web/hello-world/src/lib.rs @@ -10,6 +10,6 @@ async fn actix_web( ) -> ShuttleActixWeb { let h = hello_world; Ok(move |cfg: &mut ServiceConfig| { - cfg.service(resource("/").to(h)); + cfg.service(resource("/hello").to(h)); }) } From 5f26625d3ed7e2ceeb054d6d9a94249f12f7bd61 Mon Sep 17 00:00:00 2001 From: maksim Date: Tue, 29 Nov 2022 11:07:39 +0400 Subject: [PATCH 006/239] simplify example --- actix-web/hello-world/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/actix-web/hello-world/src/lib.rs b/actix-web/hello-world/src/lib.rs index a6ded2fe..528f4b37 100644 --- a/actix-web/hello-world/src/lib.rs +++ b/actix-web/hello-world/src/lib.rs @@ -8,8 +8,7 @@ async fn hello_world() -> &'static str { #[shuttle_service::main] async fn actix_web( ) -> ShuttleActixWeb { - let h = hello_world; Ok(move |cfg: &mut ServiceConfig| { - cfg.service(resource("/hello").to(h)); + cfg.service(resource("/hello").to(hello_world)); }) } From ea85d6bff5c2ef84de6073f5cf7dee1ec9f672ad Mon Sep 17 00:00:00 2001 From: Maxim <59533214+biryukovmaxim@users.noreply.github.com> Date: Tue, 29 Nov 2022 16:31:44 +0400 Subject: [PATCH 007/239] Update actix-web/hello-world/Cargo.toml; set default shuttle-service dep MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Oddbjørn Grødem <29732646+oddgrd@users.noreply.github.com> --- actix-web/hello-world/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index d4d99aa2..671135fc 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" [dependencies] actix-service = "2.0.2" actix-web = "4.2.1" -shuttle-service = { version = '0.7.2', git = "ssh://git@github.com/biryukovmaxim/shuttle.git", branch = "feature/support-actix-web", features = ["web-actix-web"] } +shuttle-service = { version = '0.7.2', features = ["web-actix-web"] } From 2a05b9a5e7a8a70b04b66daeee1601674bda9c15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Fri, 9 Dec 2022 16:52:34 +0100 Subject: [PATCH 008/239] feat: add axum static files example (#6) --- axum/static-files/Cargo.toml | 12 ++++++++++++ axum/static-files/README.md | 5 +++++ axum/static-files/assets/index.html | 9 +++++++++ axum/static-files/assets/script.js | 1 + axum/static-files/src/lib.rs | 24 ++++++++++++++++++++++++ 5 files changed, 51 insertions(+) create mode 100644 axum/static-files/Cargo.toml create mode 100644 axum/static-files/README.md create mode 100644 axum/static-files/assets/index.html create mode 100644 axum/static-files/assets/script.js create mode 100644 axum/static-files/src/lib.rs diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml new file mode 100644 index 00000000..ee41800e --- /dev/null +++ b/axum/static-files/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "static-files" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +axum = "0.6.1" +axum-extra = { version = "0.4.2", features = ["spa"] } +shuttle-service = { version = "0.8.0", features = ["web-axum"] } +shuttle-static-folder = "0.8.0" +sync_wrapper = "0.1.1" diff --git a/axum/static-files/README.md b/axum/static-files/README.md new file mode 100644 index 00000000..dda9f655 --- /dev/null +++ b/axum/static-files/README.md @@ -0,0 +1,5 @@ +# Serving Static Assets with Axum + +This example shows how to serve static assets using [axum](https://github.com/tokio-rs/axum) and shuttle. + +This example is inspired by the static-file-server example from the axum repo, to see more ways to do this check out the [original](https://github.com/tokio-rs/axum/blob/main/examples/static-file-server/src/main.rs). diff --git a/axum/static-files/assets/index.html b/axum/static-files/assets/index.html new file mode 100644 index 00000000..dce375e7 --- /dev/null +++ b/axum/static-files/assets/index.html @@ -0,0 +1,9 @@ + + + + Static Files + + +

This is an example of serving static files with axum and shuttle.

+ + diff --git a/axum/static-files/assets/script.js b/axum/static-files/assets/script.js new file mode 100644 index 00000000..eb065f93 --- /dev/null +++ b/axum/static-files/assets/script.js @@ -0,0 +1 @@ +console.log('Hello, World!'); diff --git a/axum/static-files/src/lib.rs b/axum/static-files/src/lib.rs new file mode 100644 index 00000000..e48a15ed --- /dev/null +++ b/axum/static-files/src/lib.rs @@ -0,0 +1,24 @@ +use std::path::PathBuf; + +use axum::{routing::get, Router}; +use axum_extra::routing::SpaRouter; +use sync_wrapper::SyncWrapper; + +async fn hello_world() -> &'static str { + "Hello, world!" +} + +#[shuttle_service::main] +async fn axum( + // Name your static assets folder by passing `folder = ` to `StaticFolder` + // If you don't pass a name, it will default to `static`. + #[shuttle_static_folder::StaticFolder(folder = "assets")] static_folder: PathBuf, +) -> shuttle_service::ShuttleAxum { + let router = Router::new() + .route("/hello", get(hello_world)) + .merge(SpaRouter::new("/assets", static_folder).index_file("index.html")); + + let sync_wrapper = SyncWrapper::new(router); + + Ok(sync_wrapper) +} From 112b4071eee6a7b626a136dd30338584543e00a9 Mon Sep 17 00:00:00 2001 From: chesedo Date: Wed, 30 Nov 2022 10:33:57 +0200 Subject: [PATCH 009/239] refactor: use static-folder resource --- axum/websocket/Cargo.toml | 2 ++ axum/websocket/src/lib.rs | 22 +++++++++++++--------- axum/websocket/{ => static}/index.html | 0 3 files changed, 15 insertions(+), 9 deletions(-) rename axum/websocket/{ => static}/index.html (100%) diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 7d889db1..c3025a94 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -14,5 +14,7 @@ hyper-tls = "0.5.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" shuttle-service = { version = "0.7.2", features = ["web-axum"] } +shuttle-static-folder = "0.7.3" sync_wrapper = "0.1.1" tokio = { version = "1.22.0", features = ["full"] } +tower-http = { version = "0.3.0", features = ["fs"] } diff --git a/axum/websocket/src/lib.rs b/axum/websocket/src/lib.rs index 2d7ad4a5..f1065b1d 100644 --- a/axum/websocket/src/lib.rs +++ b/axum/websocket/src/lib.rs @@ -1,12 +1,13 @@ -use std::{sync::Arc, time::Duration}; +use std::{path::PathBuf, sync::Arc, time::Duration}; use axum::{ extract::{ ws::{Message, WebSocket}, WebSocketUpgrade, }, - response::{Html, IntoResponse}, - routing::get, + http::StatusCode, + response::IntoResponse, + routing::{get, get_service}, Extension, Router, }; use chrono::{DateTime, Utc}; @@ -20,6 +21,7 @@ use tokio::{ sync::{watch, Mutex}, time::sleep, }; +use tower_http::services::ServeDir; struct State { clients_count: usize, @@ -37,7 +39,7 @@ struct Response { } #[shuttle_service::main] -async fn main() -> ShuttleAxum { +async fn main(#[shuttle_static_folder::StaticFolder] static_folder: PathBuf) -> ShuttleAxum { let (tx, rx) = watch::channel(Message::Text("{}".to_string())); let state = Arc::new(Mutex::new(State { @@ -72,9 +74,11 @@ async fn main() -> ShuttleAxum { } }); + let serve_dir = get_service(ServeDir::new(static_folder)).handle_error(handle_error); + let router = Router::new() - .route("/", get(index)) .route("/websocket", get(websocket_handler)) + .fallback(serve_dir) .layer(Extension(state)); let sync_wrapper = SyncWrapper::new(router); @@ -82,6 +86,10 @@ async fn main() -> ShuttleAxum { Ok(sync_wrapper) } +async fn handle_error(_err: std::io::Error) -> impl IntoResponse { + (StatusCode::INTERNAL_SERVER_ERROR, "Something went wrong...") +} + async fn websocket_handler( ws: WebSocketUpgrade, Extension(state): Extension>>, @@ -126,7 +134,3 @@ async fn websocket(stream: WebSocket, state: Arc>) { // This client disconnected state.lock().await.clients_count -= 1; } - -async fn index() -> Html<&'static str> { - Html(include_str!("../index.html")) -} diff --git a/axum/websocket/index.html b/axum/websocket/static/index.html similarity index 100% rename from axum/websocket/index.html rename to axum/websocket/static/index.html From 1c158c5aabfe4ed40fcc89072b7a5de5faed1882 Mon Sep 17 00:00:00 2001 From: Damien Broka Date: Fri, 9 Dec 2022 16:15:17 +0000 Subject: [PATCH 010/239] bump shuttle-static-folder --- axum/websocket/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index c3025a94..1a513ed1 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -14,7 +14,7 @@ hyper-tls = "0.5.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" shuttle-service = { version = "0.7.2", features = ["web-axum"] } -shuttle-static-folder = "0.7.3" +shuttle-static-folder = "0.8.0" sync_wrapper = "0.1.1" tokio = { version = "1.22.0", features = ["full"] } tower-http = { version = "0.3.0", features = ["fs"] } From 21d05fc3336f876197ca7eacf3c661555a65ef23 Mon Sep 17 00:00:00 2001 From: Damien Broka Date: Fri, 9 Dec 2022 16:45:53 +0000 Subject: [PATCH 011/239] chore: bump v0.8.0 --- actix-web/hello-world/Cargo.toml | 2 +- axum/hello-world/Cargo.toml | 2 +- axum/websocket/Cargo.toml | 2 +- poem/hello-world/Cargo.toml | 2 +- poem/mongodb/Cargo.toml | 4 ++-- poem/postgres/Cargo.toml | 4 ++-- rocket/authentication/Cargo.toml | 2 +- rocket/hello-world/Cargo.toml | 2 +- rocket/persist/Cargo.toml | 4 ++-- rocket/postgres/Cargo.toml | 4 ++-- rocket/secrets/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 2 +- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 6 +++--- thruster/hello-world/Cargo.toml | 2 +- thruster/postgres/Cargo.toml | 4 ++-- tide/hello-world/Cargo.toml | 2 +- tide/postgres/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 2 +- warp/hello-world/Cargo.toml | 2 +- 21 files changed, 32 insertions(+), 32 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 671135fc..b7c812f8 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" [dependencies] actix-service = "2.0.2" actix-web = "4.2.1" -shuttle-service = { version = '0.7.2', features = ["web-actix-web"] } +shuttle-service = { version = '0.8.0', features = ["web-actix-web"] } diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 442605ae..56cab8a9 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -7,5 +7,5 @@ edition = "2021" [dependencies] axum = "0.6.0" -shuttle-service = { version = "0.7.2", features = ["web-axum"] } +shuttle-service = { version = "0.8.0", features = ["web-axum"] } sync_wrapper = "0.1.1" diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 7d889db1..aba91251 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -13,6 +13,6 @@ hyper = { version = "0.14.23", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-service = { version = "0.7.2", features = ["web-axum"] } +shuttle-service = { version = "0.8.0", features = ["web-axum"] } sync_wrapper = "0.1.1" tokio = { version = "1.22.0", features = ["full"] } diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index b4ebed08..0e09a290 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] poem = "1.3.49" -shuttle-service = { version = "0.7.2", features = ["web-poem"] } +shuttle-service = { version = "0.8.0", features = ["web-poem"] } diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index fe760856..ad03ceb0 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -8,5 +8,5 @@ mongodb = "2.3.1" poem = "1.3.49" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-service = { version = "0.7.2", features = ["web-poem"] } -shuttle-shared-db = { version = "0.7.2", features = ["mongodb"] } +shuttle-service = { version = "0.8.0", features = ["web-poem"] } +shuttle-shared-db = { version = "0.8.0", features = ["mongodb"] } diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 3cc822e9..ab77a629 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -8,6 +8,6 @@ edition = "2021" [dependencies] poem = "1.3.49" serde = "1.0.148" -shuttle-service = { version = "0.7.2", features = ["web-poem"] } -shuttle-shared-db = { version = "0.7.2", features = ["postgres"] } +shuttle-service = { version = "0.8.0", features = ["web-poem"] } +shuttle-shared-db = { version = "0.8.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index 37282f7b..3051f7b7 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -11,4 +11,4 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-service = { version = "0.7.2", features = ["web-rocket"] } +shuttle-service = { version = "0.8.0", features = ["web-rocket"] } diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index d1b2877b..3cdecd5d 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-service = { version = "0.7.2", features = ["web-rocket"] } +shuttle-service = { version = "0.8.0", features = ["web-rocket"] } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 48527a56..638a4990 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -8,5 +8,5 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.7.2" -shuttle-service = { version = "0.7.2", features = ["web-rocket"] } +shuttle-persist = "0.8.0" +shuttle-service = { version = "0.8.0", features = ["web-rocket"] } diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index c120c8fc..94a22e08 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -8,6 +8,6 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-service = { version = "0.7.2", features = ["web-rocket"] } -shuttle-shared-db = { version = "0.7.2", features = ["postgres"] } +shuttle-service = { version = "0.8.0", features = ["web-rocket"] } +shuttle-shared-db = { version = "0.8.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 3207ef81..6f7a1219 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -8,5 +8,5 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-secrets = "0.7.2" -shuttle-service = { version = "0.7.2", features = ["web-rocket"] } +shuttle-secrets = "0.8.0" +shuttle-service = { version = "0.8.0", features = ["web-rocket"] } diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index ed5245f8..0c829665 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-service = { version = "0.7.2", features = ["web-rocket"] } -shuttle-shared-db = { version = "0.7.2", features = ["postgres"] } +shuttle-service = { version = "0.8.0", features = ["web-rocket"] } +shuttle-shared-db = { version = "0.8.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } url = "2.3.1" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 9165c116..6532e2b0 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] salvo = "0.37.5" -shuttle-service = { version = "0.7.2", features = ["web-salvo"] } +shuttle-service = { version = "0.8.0", features = ["web-salvo"] } diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index ad844287..8ea7ff51 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -8,6 +8,6 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.7.2" -shuttle-service = { version = "0.7.2", features = ["bot-serenity"] } +shuttle-secrets = "0.8.0" +shuttle-service = { version = "0.8.0", features = ["bot-serenity"] } tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 4799078d..e97b71a6 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -9,8 +9,8 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.7.2" -shuttle-service = { version = "0.7.2", features = ["bot-serenity"] } -shuttle-shared-db = { version = "0.7.2", features = ["postgres"] } +shuttle-secrets = "0.8.0" +shuttle-service = { version = "0.8.0", features = ["bot-serenity"] } +shuttle-shared-db = { version = "0.8.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index fb313eb6..7d2db0ba 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" [lib] [dependencies] -shuttle-service = { version = "0.7.2", features = ["web-thruster"] } +shuttle-service = { version = "0.8.0", features = ["web-thruster"] } thruster = { version = "1.3.0", features = ["hyper_server"] } diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index aaeae35c..34f87fcc 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -11,7 +11,7 @@ crate-type = ["cdylib"] hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.7.2", features = ["postgres"] } -shuttle-service = { version = "0.7.2", features = ["web-thruster"] } +shuttle-aws-rds = { version = "0.8.0", features = ["postgres"] } +shuttle-service = { version = "0.8.0", features = ["web-thruster"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index beec2364..328c3cc0 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" [lib] [dependencies] -shuttle-service = { version = "0.7.2", features = ["web-tide"] } +shuttle-service = { version = "0.8.0", features = ["web-tide"] } tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index ef4ebfb6..8d9ac2ac 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["cdylib"] [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.7.2", features = ["postgres"] } -shuttle-service = { version = "0.7.2", features = ["web-tide"] } +shuttle-aws-rds = { version = "0.8.0", features = ["postgres"] } +shuttle-service = { version = "0.8.0", features = ["web-tide"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 1d150c5a..a26cc0b9 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -7,5 +7,5 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-service = { version = "0.7.2", features = ["web-tower"] } +shuttle-service = { version = "0.8.0", features = ["web-tower"] } tower = { version = "0.4.13", features = ["full"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 012f75c1..94df2a8f 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" [lib] [dependencies] -shuttle-service = { version = "0.7.2", features = ["web-warp"] } +shuttle-service = { version = "0.8.0", features = ["web-warp"] } warp = "0.3.3" From 893bc39babf64aedeafa5dbba5d11806b163d57a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Mon, 12 Dec 2022 11:14:33 +0100 Subject: [PATCH 012/239] feat: add actix postgres example (#8) --- actix-web/README.md | 5 +++ actix-web/hello-world/Cargo.toml | 2 - actix-web/hello-world/src/lib.rs | 7 ++-- actix-web/postgres/Cargo.toml | 13 ++++++ actix-web/postgres/schema.sql | 6 +++ actix-web/postgres/src/lib.rs | 68 ++++++++++++++++++++++++++++++++ 6 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 actix-web/README.md create mode 100644 actix-web/postgres/Cargo.toml create mode 100644 actix-web/postgres/schema.sql create mode 100644 actix-web/postgres/src/lib.rs diff --git a/actix-web/README.md b/actix-web/README.md new file mode 100644 index 00000000..0c2802ba --- /dev/null +++ b/actix-web/README.md @@ -0,0 +1,5 @@ +# Actix Web with shuttle + +Normally one would configure an application with [Actix Web](https://docs.rs/actix-web/latest/actix_web/index.html) using the [App](https://docs.rs/actix-web/latest/actix_web/struct.App.html) struct. However, shuttle needs to move the users configuration across threads to start the server on our backend, and the `App` struct is `!Send` and `!Sync`. + +That means that for shuttle to support Actix Web, we need to use the [ServiceConfig](https://docs.rs/actix-web/latest/actix_web/web/struct.ServiceConfig.html) struct. You should be able to configure your application like you normally would, but some steps may be a bit different. If you do you find something that you would expect to be possible not working, please reach out and let us know. diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index b7c812f8..8bdddcb3 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -4,7 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] -actix-service = "2.0.2" actix-web = "4.2.1" shuttle-service = { version = '0.8.0', features = ["web-actix-web"] } - diff --git a/actix-web/hello-world/src/lib.rs b/actix-web/hello-world/src/lib.rs index 528f4b37..a78719db 100644 --- a/actix-web/hello-world/src/lib.rs +++ b/actix-web/hello-world/src/lib.rs @@ -1,14 +1,15 @@ -use actix_web::web::{resource, ServiceConfig}; +use actix_web::{get, web::ServiceConfig}; use shuttle_service::ShuttleActixWeb; +#[get("/hello")] async fn hello_world() -> &'static str { "Hello World!" } #[shuttle_service::main] async fn actix_web( -) -> ShuttleActixWeb { +) -> ShuttleActixWeb { Ok(move |cfg: &mut ServiceConfig| { - cfg.service(resource("/hello").to(hello_world)); + cfg.service(hello_world); }) } diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml new file mode 100644 index 00000000..27aa3d3a --- /dev/null +++ b/actix-web/postgres/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "postgres" +version = "0.1.0" +edition = "2021" + +[lib] + +[dependencies] +actix-web = "4.2.1" +serde = "1.0.148" +shuttle-service = { version = "0.8.0", features = ["web-actix-web"] } +shuttle-shared-db = { version = "0.8.0", features = ["postgres"] } +sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } diff --git a/actix-web/postgres/schema.sql b/actix-web/postgres/schema.sql new file mode 100644 index 00000000..460e7c23 --- /dev/null +++ b/actix-web/postgres/schema.sql @@ -0,0 +1,6 @@ +DROP TABLE IF EXISTS todos; + +CREATE TABLE todos ( + id serial PRIMARY KEY, + note TEXT NOT NULL +); diff --git a/actix-web/postgres/src/lib.rs b/actix-web/postgres/src/lib.rs new file mode 100644 index 00000000..3e18ae7f --- /dev/null +++ b/actix-web/postgres/src/lib.rs @@ -0,0 +1,68 @@ +use actix_web::middleware::Logger; +use actix_web::{ + error, get, post, + web::{self, Json, ServiceConfig}, + Result, +}; +use serde::{Deserialize, Serialize}; +use shuttle_service::{error::CustomError, ShuttleActixWeb}; +use sqlx::{Executor, FromRow, PgPool}; + +#[get("/{id}")] +async fn retrieve(path: web::Path, state: web::Data) -> Result> { + let todo = sqlx::query_as("SELECT * FROM todos WHERE id = $1") + .bind(*path) + .fetch_one(&state.pool) + .await + .map_err(|e| error::ErrorBadRequest(e.to_string()))?; + + Ok(Json(todo)) +} + +#[post("")] +async fn add(todo: web::Json, state: web::Data) -> Result> { + let todo = sqlx::query_as("INSERT INTO todos(note) VALUES ($1) RETURNING id, note") + .bind(&todo.note) + .fetch_one(&state.pool) + .await + .map_err(|e| error::ErrorBadRequest(e.to_string()))?; + + Ok(Json(todo)) +} + +#[derive(Clone)] +struct AppState { + pool: PgPool, +} + +#[shuttle_service::main] +async fn actix_web( + #[shuttle_shared_db::Postgres] pool: PgPool, +) -> ShuttleActixWeb { + pool.execute(include_str!("../schema.sql")) + .await + .map_err(CustomError::new)?; + + let state = web::Data::new(AppState { pool }); + + Ok(move |cfg: &mut ServiceConfig| { + cfg.service( + web::scope("/todos") + .wrap(Logger::default()) + .service(retrieve) + .service(add) + .app_data(state), + ); + }) +} + +#[derive(Deserialize)] +struct TodoNew { + pub note: String, +} + +#[derive(Serialize, Deserialize, FromRow)] +struct Todo { + pub id: i32, + pub note: String, +} From afb11e6c95e7bb436e67db90c016a526f71effdb Mon Sep 17 00:00:00 2001 From: chesedo Date: Thu, 26 Jan 2023 16:19:34 +0200 Subject: [PATCH 013/239] bug: websocket status url --- axum/websocket/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/axum/websocket/src/lib.rs b/axum/websocket/src/lib.rs index b9328771..9d9f4912 100644 --- a/axum/websocket/src/lib.rs +++ b/axum/websocket/src/lib.rs @@ -29,7 +29,7 @@ struct State { } const PAUSE_SECS: u64 = 15; -const STATUS_URI: &str = "https://api.shuttle.rs/status"; +const STATUS_URI: &str = "https://api.shuttle.rs"; #[derive(Serialize)] struct Response { From 7a665b189744f411479455191037942f0db66032 Mon Sep 17 00:00:00 2001 From: Roberto Huertas Date: Fri, 27 Jan 2023 14:37:28 +0100 Subject: [PATCH 014/239] fix(axum): fixes ws protocol (#12) The example was not working locally due to the hardcoded wss protocol. This PR fixes that, formats the html using prettier and avoids `datetime` in favor of `date_time`. --- axum/websocket/src/lib.rs | 5 +- axum/websocket/static/index.html | 155 ++++++++++++++++++------------- 2 files changed, 95 insertions(+), 65 deletions(-) diff --git a/axum/websocket/src/lib.rs b/axum/websocket/src/lib.rs index 9d9f4912..7d3888b2 100644 --- a/axum/websocket/src/lib.rs +++ b/axum/websocket/src/lib.rs @@ -34,7 +34,8 @@ const STATUS_URI: &str = "https://api.shuttle.rs"; #[derive(Serialize)] struct Response { clients_count: usize, - datetime: DateTime, + #[serde(rename = "dateTime")] + date_time: DateTime, is_up: bool, } @@ -61,7 +62,7 @@ async fn main(#[shuttle_static_folder::StaticFolder] static_folder: PathBuf) -> let response = Response { clients_count: state_send.lock().await.clients_count, - datetime: Utc::now(), + date_time: Utc::now(), is_up, }; let msg = serde_json::to_string(&response).unwrap(); diff --git a/axum/websocket/static/index.html b/axum/websocket/static/index.html index f7fbdf5c..3f5b5699 100644 --- a/axum/websocket/static/index.html +++ b/axum/websocket/static/index.html @@ -1,75 +1,104 @@ - - - - - Websocket status page - - - -
-
- Current API status -
-
-
-
-
- Last check time -
-
-
-
-
- Clients watching -
-
-
+ + + + + Websocket status page + + + +
+
+ Current API status +
+
+
+
+
+ Last check time +
+
+
+
+
+ Clients watching +
+
+
- + - - + track(); + button.addEventListener('click', track); + + From 23d133131c026e878f38a7d6453de6312ffdc9e7 Mon Sep 17 00:00:00 2001 From: Roberto Huertas Date: Fri, 27 Jan 2023 14:52:12 +0100 Subject: [PATCH 015/239] feat(actix): actorless ws example (#13) --- actix-web/websocket-actorless/Cargo.toml | 21 ++ actix-web/websocket-actorless/Shuttle.toml | 1 + actix-web/websocket-actorless/src/lib.rs | 195 ++++++++++++++++++ .../websocket-actorless/static/index.html | 173 ++++++++++++++++ 4 files changed, 390 insertions(+) create mode 100644 actix-web/websocket-actorless/Cargo.toml create mode 100644 actix-web/websocket-actorless/Shuttle.toml create mode 100644 actix-web/websocket-actorless/src/lib.rs create mode 100644 actix-web/websocket-actorless/static/index.html diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml new file mode 100644 index 00000000..9ce66004 --- /dev/null +++ b/actix-web/websocket-actorless/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "websocket-actorless" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] + +[dependencies] +shuttle-service = { version = "0.8.0", features = ["web-actix-web"] } +shuttle-static-folder = "0.8.0" +actix-web = "4.2.1" +actix-ws = "0.2.5" +actix-files = "0.6.2" +futures = "0.3" +reqwest = "0.11" +tokio = { version = "1", features = ["rt-multi-thread", "sync"] } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +chrono = { version = "0.4.23", features = ["serde"] } +tracing = "0.1" diff --git a/actix-web/websocket-actorless/Shuttle.toml b/actix-web/websocket-actorless/Shuttle.toml new file mode 100644 index 00000000..3254b9d5 --- /dev/null +++ b/actix-web/websocket-actorless/Shuttle.toml @@ -0,0 +1 @@ +name = "websocket-actorless-actix-web-app" diff --git a/actix-web/websocket-actorless/src/lib.rs b/actix-web/websocket-actorless/src/lib.rs new file mode 100644 index 00000000..d2012e02 --- /dev/null +++ b/actix-web/websocket-actorless/src/lib.rs @@ -0,0 +1,195 @@ +use actix_files::NamedFile; +use actix_web::{ + web::{self, ServiceConfig}, + HttpRequest, HttpResponse, Responder, +}; +use actix_ws::Message; +use chrono::{DateTime, Utc}; +use futures::StreamExt; +use serde::Serialize; +use shuttle_service::ShuttleActixWeb; +use std::{ + sync::{atomic::AtomicUsize, Arc}, + time::Duration, +}; +use tokio::sync::{mpsc, watch}; + +const PAUSE_SECS: u64 = 15; +const STATUS_URI: &str = "https://api.shuttle.rs"; + +type AppState = ( + mpsc::UnboundedSender, + watch::Receiver, +); + +#[derive(Debug, Clone)] +enum WsState { + Connected, + Disconnected, +} + +#[derive(Serialize, Default, Clone, Debug)] +struct ApiStateMessage { + client_count: usize, + origin: String, + date_time: DateTime, + is_up: bool, +} + +async fn echo_handler( + mut session: actix_ws::Session, + mut msg_stream: actix_ws::MessageStream, + tx: mpsc::UnboundedSender, +) { + while let Some(Ok(msg)) = msg_stream.next().await { + match msg { + Message::Ping(bytes) => { + if session.pong(&bytes).await.is_err() { + return; + } + } + Message::Text(s) => { + session.text(s.clone()).await.unwrap(); + tracing::info!("Got text, {}", s); + } + _ => break, + } + } + + if let Err(e) = tx.send(WsState::Disconnected) { + tracing::error!("Failed to send disconnected state: {e:?}"); + } + + let _ = session.close(None).await; +} + +async fn websocket( + req: HttpRequest, + body: web::Payload, + app_state: web::Data, +) -> actix_web::Result { + let app_state = app_state.into_inner(); + let (response, session, msg_stream) = actix_ws::handle(&req, body)?; + + let tx_ws_state = app_state.0.clone(); + let tx_ws_state2 = tx_ws_state.clone(); + + // send connected state + if let Err(e) = tx_ws_state.send(WsState::Connected) { + tracing::error!("Failed to send connected state: {e:?}"); + } + + // listen for api state changes + let mut session_clone = session.clone(); + let mut rx_api_state = app_state.1.clone(); + actix_web::rt::spawn(async move { + // adding some delay to avoid getting the first message too soon. + tokio::time::sleep(Duration::from_millis(500)).await; + while rx_api_state.changed().await.is_ok() { + let msg = rx_api_state.borrow().clone(); + tracing::info!("Handling ApiStateMessage: {msg:?}"); + let msg = serde_json::to_string(&msg).unwrap(); + session_clone.text(msg).await.unwrap(); + } + }); + + // echo handler + actix_web::rt::spawn(echo_handler(session, msg_stream, tx_ws_state2)); + Ok(response) +} + +async fn index() -> impl Responder { + NamedFile::open_async("./static/index.html") + .await + .map_err(|e| actix_web::error::ErrorInternalServerError(e)) +} + +#[shuttle_service::main] +async fn actix_web( +) -> ShuttleActixWeb { + // We're going to use channels to communicate between threads. + // api state channel + let (tx_api_state, rx_api_state) = watch::channel(ApiStateMessage::default()); + // websocket state channel + let (tx_ws_state, mut rx_ws_state) = mpsc::unbounded_channel::(); + + // create a shared state for the client counter + let client_count = Arc::new(AtomicUsize::new(0)); + let client_count2 = client_count.clone(); + + // share tx_api_state + let shared_tx_api_state = Arc::new(tx_api_state); + let shared_tx_api_state2 = shared_tx_api_state.clone(); + + // share reqwest client + let client = reqwest::Client::default(); + let client2 = client.clone(); + + // Spawn a thread to continually check the status of the api + tokio::spawn(async move { + let duration = Duration::from_secs(PAUSE_SECS); + + loop { + tokio::time::sleep(duration).await; + let is_up = get_api_status(&client).await; + + let response = ApiStateMessage { + client_count: client_count.load(std::sync::atomic::Ordering::SeqCst), + origin: "api_update loop".to_string(), + date_time: Utc::now(), + is_up, + }; + + if shared_tx_api_state.send(response).is_err() { + tracing::error!("Failed to send api state from checker thread"); + break; + } + } + }); + + // spawn a thread to continuously check the status of the websocket connections + tokio::spawn(async move { + while let Some(state) = rx_ws_state.recv().await { + match state { + WsState::Connected => { + tracing::info!("Client connected"); + client_count2.fetch_add(1, std::sync::atomic::Ordering::SeqCst); + } + WsState::Disconnected => { + tracing::info!("Client disconnected"); + client_count2.fetch_sub(1, std::sync::atomic::Ordering::SeqCst); + } + } + + let client_count = client_count2.load(std::sync::atomic::Ordering::SeqCst); + tracing::info!("Client count: {client_count}"); + + let is_up = get_api_status(&client2).await; + + if let Err(e) = shared_tx_api_state2.send(ApiStateMessage { + client_count, + origin: format!("ws_update"), + date_time: Utc::now(), + is_up, + }) { + tracing::error!("Failed to send api state: {e:?}"); + } + } + }); + + let app_state = web::Data::new((tx_ws_state, rx_api_state)); + + Ok(move |cfg: &mut ServiceConfig| { + cfg.service(web::resource("/").route(web::get().to(index))) + .service( + web::resource("/ws") + .app_data(app_state) + .route(web::get().to(websocket)), + ); + }) +} + +async fn get_api_status(client: &reqwest::Client) -> bool { + let response = client.get(STATUS_URI).send().await; + response.is_ok() +} diff --git a/actix-web/websocket-actorless/static/index.html b/actix-web/websocket-actorless/static/index.html new file mode 100644 index 00000000..7dea711d --- /dev/null +++ b/actix-web/websocket-actorless/static/index.html @@ -0,0 +1,173 @@ + + + + + WS with Actix + + + + + +

WebSocket example

+ +

+ When you connect you will be notified of the shuttle API status and the + amount of connected users every 15 seconds. +

+

+ You can also send a message to the server and you will get back the echo. +

+ +
+ + Status: + disconnected +
+ +
+ +
+ + +
+ + + + From 63bd58b332caa25968d6818d44f15ed9211c5392 Mon Sep 17 00:00:00 2001 From: Anafabula <57800226+Anafabula@users.noreply.github.com> Date: Fri, 27 Jan 2023 15:31:16 +0100 Subject: [PATCH 016/239] Feat/poise example (#9) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add poise hello-world example * fix: remove the local crate override patch * chore: bump to 0.9 Co-authored-by: Oddbjørn Grødem <29732646+oddgrd@users.noreply.github.com> --- poise/hello-world/Cargo.toml | 14 ++++++++++++ poise/hello-world/README.md | 16 +++++++++++++ poise/hello-world/Secrets.toml | 1 + poise/hello-world/Shuttle.toml | 1 + poise/hello-world/src/lib.rs | 42 ++++++++++++++++++++++++++++++++++ 5 files changed, 74 insertions(+) create mode 100644 poise/hello-world/Cargo.toml create mode 100644 poise/hello-world/README.md create mode 100644 poise/hello-world/Secrets.toml create mode 100644 poise/hello-world/Shuttle.toml create mode 100644 poise/hello-world/src/lib.rs diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml new file mode 100644 index 00000000..b88fb37b --- /dev/null +++ b/poise/hello-world/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "hello-world" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] + +[dependencies] +shuttle-service = { version = "0.9.0", features = ["bot-poise"] } +anyhow = "1.0.68" +shuttle-secrets = "0.9.0" +tracing = "0.1.37" +poise = "0.5.2" diff --git a/poise/hello-world/README.md b/poise/hello-world/README.md new file mode 100644 index 00000000..2b5f36d9 --- /dev/null +++ b/poise/hello-world/README.md @@ -0,0 +1,16 @@ +# Poise Hello World Bot with Shuttle + +In this example we will deploy a Poise/Serenity bot with Shuttle that responds to the `/hello` command with `world!`. To run this bot we need a valid Discord Token. To get started log in to the [Discord developer portal](https://discord.com/developers/applications). + +1. Click the New Application button, name your application and click Create. +2. Navigate to the Bot tab in the lefthand menu, and add a new bot. +3. On the bot page click the Reset Token button to reveal your token. Put this token in your `Secrets.toml`. It's very important that you don't reveal your token to anyone, as it can be abused. Create a `.gitignore` file to omit your `Secrets.toml` from version control. +4. For the sake of this example, you also need to scroll down on the bot page to the Message Content Intent section and enable that option. + +To add the bot to a server we need to create an invite link. + +1. On your bot's application page, open the OAuth2 page via the lefthand panel. +2. Go to the URL Generator via the lefthand panel, and select the `bot` scope as well as the `Send Messages` permission in the Bot Permissions section. +3. Copy the URL, open it in your browser and select a Discord server you wish to invite the bot to. + +For more information please refer to the [Discord docs](https://discord.com/developers/docs/getting-started) as well as the [Poise docs](https://docs.rs/poise) for more examples. diff --git a/poise/hello-world/Secrets.toml b/poise/hello-world/Secrets.toml new file mode 100644 index 00000000..966fdb0c --- /dev/null +++ b/poise/hello-world/Secrets.toml @@ -0,0 +1 @@ +DISCORD_TOKEN = 'the contents of my discord token' diff --git a/poise/hello-world/Shuttle.toml b/poise/hello-world/Shuttle.toml new file mode 100644 index 00000000..4ebb812b --- /dev/null +++ b/poise/hello-world/Shuttle.toml @@ -0,0 +1 @@ +name = "hello-world-poise-bot" diff --git a/poise/hello-world/src/lib.rs b/poise/hello-world/src/lib.rs new file mode 100644 index 00000000..7a0ad310 --- /dev/null +++ b/poise/hello-world/src/lib.rs @@ -0,0 +1,42 @@ +use anyhow::Context as _; +use poise::serenity_prelude as serenity; +use shuttle_secrets::SecretStore; +use shuttle_service::ShuttlePoise; + +struct Data {} // User data, which is stored and accessible in all command invocations +type Error = Box; +type Context<'a> = poise::Context<'a, Data, Error>; + +/// Responds with "world!" +#[poise::command(slash_command)] +async fn hello(ctx: Context<'_>) -> Result<(), Error> { + ctx.say("world!").await?; + Ok(()) +} + +#[shuttle_service::main] +async fn poise(#[shuttle_secrets::Secrets] secret_store: SecretStore) -> ShuttlePoise { + // Get the discord token set in `Secrets.toml` + let discord_token = secret_store + .get("DISCORD_TOKEN") + .context("'DISCORD_TOKEN' was not found")?; + + let framework = poise::Framework::builder() + .options(poise::FrameworkOptions { + commands: vec![hello()], + ..Default::default() + }) + .token(discord_token) + .intents(serenity::GatewayIntents::non_privileged()) + .setup(|ctx, _ready, framework| { + Box::pin(async move { + poise::builtins::register_globally(ctx, &framework.options().commands).await?; + Ok(Data {}) + }) + }) + .build() + .await + .map_err(shuttle_service::error::CustomError::new)?; + + Ok(framework) +} From b1eb0d8c79d316fc4b920dfe2ebe73cc96d982df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Fri, 27 Jan 2023 15:31:39 +0100 Subject: [PATCH 017/239] chore: v0.9.0 (#15) --- actix-web/hello-world/Cargo.toml | 2 +- actix-web/postgres/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 2 +- axum/static-files/Cargo.toml | 4 ++-- axum/websocket/Cargo.toml | 4 ++-- poem/hello-world/Cargo.toml | 2 +- poem/mongodb/Cargo.toml | 4 ++-- poem/postgres/Cargo.toml | 4 ++-- rocket/authentication/Cargo.toml | 2 +- rocket/hello-world/Cargo.toml | 2 +- rocket/persist/Cargo.toml | 4 ++-- rocket/postgres/Cargo.toml | 4 ++-- rocket/secrets/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 2 +- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 6 +++--- thruster/hello-world/Cargo.toml | 2 +- thruster/postgres/Cargo.toml | 4 ++-- tide/hello-world/Cargo.toml | 2 +- tide/postgres/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 2 +- warp/hello-world/Cargo.toml | 2 +- 24 files changed, 39 insertions(+), 39 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 8bdddcb3..d5a1a36f 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,4 +5,4 @@ edition = "2021" [dependencies] actix-web = "4.2.1" -shuttle-service = { version = '0.8.0', features = ["web-actix-web"] } +shuttle-service = { version = '0.9.0', features = ["web-actix-web"] } diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 27aa3d3a..711ad44b 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -8,6 +8,6 @@ edition = "2021" [dependencies] actix-web = "4.2.1" serde = "1.0.148" -shuttle-service = { version = "0.8.0", features = ["web-actix-web"] } -shuttle-shared-db = { version = "0.8.0", features = ["postgres"] } +shuttle-service = { version = "0.9.0", features = ["web-actix-web"] } +shuttle-shared-db = { version = "0.9.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 9ce66004..309c732c 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -7,8 +7,8 @@ publish = false [lib] [dependencies] -shuttle-service = { version = "0.8.0", features = ["web-actix-web"] } -shuttle-static-folder = "0.8.0" +shuttle-service = { version = "0.9.0", features = ["web-actix-web"] } +shuttle-static-folder = "0.9.0" actix-web = "4.2.1" actix-ws = "0.2.5" actix-files = "0.6.2" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 56cab8a9..7e05e870 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -7,5 +7,5 @@ edition = "2021" [dependencies] axum = "0.6.0" -shuttle-service = { version = "0.8.0", features = ["web-axum"] } +shuttle-service = { version = "0.9.0", features = ["web-axum"] } sync_wrapper = "0.1.1" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index ee41800e..047fda2b 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -7,6 +7,6 @@ publish = false [dependencies] axum = "0.6.1" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-service = { version = "0.8.0", features = ["web-axum"] } -shuttle-static-folder = "0.8.0" +shuttle-service = { version = "0.9.0", features = ["web-axum"] } +shuttle-static-folder = "0.9.0" sync_wrapper = "0.1.1" diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 3a575723..d435b875 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -13,8 +13,8 @@ hyper = { version = "0.14.23", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-service = { version = "0.8.0", features = ["web-axum"] } -shuttle-static-folder = "0.8.0" +shuttle-service = { version = "0.9.0", features = ["web-axum"] } +shuttle-static-folder = "0.9.0" sync_wrapper = "0.1.1" tokio = { version = "1.22.0", features = ["full"] } tower-http = { version = "0.3.0", features = ["fs"] } diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 0e09a290..8d01e274 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] poem = "1.3.49" -shuttle-service = { version = "0.8.0", features = ["web-poem"] } +shuttle-service = { version = "0.9.0", features = ["web-poem"] } diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index ad03ceb0..39d6ac48 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -8,5 +8,5 @@ mongodb = "2.3.1" poem = "1.3.49" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-service = { version = "0.8.0", features = ["web-poem"] } -shuttle-shared-db = { version = "0.8.0", features = ["mongodb"] } +shuttle-service = { version = "0.9.0", features = ["web-poem"] } +shuttle-shared-db = { version = "0.9.0", features = ["mongodb"] } diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index ab77a629..639aca48 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -8,6 +8,6 @@ edition = "2021" [dependencies] poem = "1.3.49" serde = "1.0.148" -shuttle-service = { version = "0.8.0", features = ["web-poem"] } -shuttle-shared-db = { version = "0.8.0", features = ["postgres"] } +shuttle-service = { version = "0.9.0", features = ["web-poem"] } +shuttle-shared-db = { version = "0.9.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index 3051f7b7..fbd192d4 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -11,4 +11,4 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-service = { version = "0.8.0", features = ["web-rocket"] } +shuttle-service = { version = "0.9.0", features = ["web-rocket"] } diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 3cdecd5d..b417a435 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-service = { version = "0.8.0", features = ["web-rocket"] } +shuttle-service = { version = "0.9.0", features = ["web-rocket"] } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 638a4990..fc004dc6 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -8,5 +8,5 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.8.0" -shuttle-service = { version = "0.8.0", features = ["web-rocket"] } +shuttle-persist = "0.9.0" +shuttle-service = { version = "0.9.0", features = ["web-rocket"] } diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 94a22e08..cbdb58aa 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -8,6 +8,6 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-service = { version = "0.8.0", features = ["web-rocket"] } -shuttle-shared-db = { version = "0.8.0", features = ["postgres"] } +shuttle-service = { version = "0.9.0", features = ["web-rocket"] } +shuttle-shared-db = { version = "0.9.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 6f7a1219..2b9cbb7a 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -8,5 +8,5 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-secrets = "0.8.0" -shuttle-service = { version = "0.8.0", features = ["web-rocket"] } +shuttle-secrets = "0.9.0" +shuttle-service = { version = "0.9.0", features = ["web-rocket"] } diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 0c829665..780ac49c 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-service = { version = "0.8.0", features = ["web-rocket"] } -shuttle-shared-db = { version = "0.8.0", features = ["postgres"] } +shuttle-service = { version = "0.9.0", features = ["web-rocket"] } +shuttle-shared-db = { version = "0.9.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } url = "2.3.1" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 6532e2b0..148a350e 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] salvo = "0.37.5" -shuttle-service = { version = "0.8.0", features = ["web-salvo"] } +shuttle-service = { version = "0.9.0", features = ["web-salvo"] } diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 8ea7ff51..8677ebe2 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -8,6 +8,6 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.8.0" -shuttle-service = { version = "0.8.0", features = ["bot-serenity"] } +shuttle-secrets = "0.9.0" +shuttle-service = { version = "0.9.0", features = ["bot-serenity"] } tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index e97b71a6..628a3aa6 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -9,8 +9,8 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.8.0" -shuttle-service = { version = "0.8.0", features = ["bot-serenity"] } -shuttle-shared-db = { version = "0.8.0", features = ["postgres"] } +shuttle-secrets = "0.9.0" +shuttle-service = { version = "0.9.0", features = ["bot-serenity"] } +shuttle-shared-db = { version = "0.9.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 7d2db0ba..8bbdc085 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" [lib] [dependencies] -shuttle-service = { version = "0.8.0", features = ["web-thruster"] } +shuttle-service = { version = "0.9.0", features = ["web-thruster"] } thruster = { version = "1.3.0", features = ["hyper_server"] } diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 34f87fcc..c96b204c 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -11,7 +11,7 @@ crate-type = ["cdylib"] hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.8.0", features = ["postgres"] } -shuttle-service = { version = "0.8.0", features = ["web-thruster"] } +shuttle-aws-rds = { version = "0.9.0", features = ["postgres"] } +shuttle-service = { version = "0.9.0", features = ["web-thruster"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 328c3cc0..503fd6bd 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" [lib] [dependencies] -shuttle-service = { version = "0.8.0", features = ["web-tide"] } +shuttle-service = { version = "0.9.0", features = ["web-tide"] } tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index 8d9ac2ac..efcd41b9 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["cdylib"] [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.8.0", features = ["postgres"] } -shuttle-service = { version = "0.8.0", features = ["web-tide"] } +shuttle-aws-rds = { version = "0.9.0", features = ["postgres"] } +shuttle-service = { version = "0.9.0", features = ["web-tide"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index a26cc0b9..cc22e3f2 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -7,5 +7,5 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-service = { version = "0.8.0", features = ["web-tower"] } +shuttle-service = { version = "0.9.0", features = ["web-tower"] } tower = { version = "0.4.13", features = ["full"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 94df2a8f..5a90fb16 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" [lib] [dependencies] -shuttle-service = { version = "0.8.0", features = ["web-warp"] } +shuttle-service = { version = "0.9.0", features = ["web-warp"] } warp = "0.3.3" From 5f9a10938d6d19e12deeb462497403de27fe966c Mon Sep 17 00:00:00 2001 From: Pieter Date: Mon, 6 Feb 2023 12:40:02 +0200 Subject: [PATCH 018/239] feat: next server example (#16) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: next server example * refactor: update readme * refactor: readme title * fix: remove old ticks --------- Co-authored-by: Oddbjørn Grødem <29732646+oddgrd@users.noreply.github.com> --- axum/static-next-server/Cargo.toml | 12 ++++++++++++ axum/static-next-server/README.md | 3 +++ axum/static-next-server/src/lib.rs | 17 +++++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 axum/static-next-server/Cargo.toml create mode 100644 axum/static-next-server/README.md create mode 100644 axum/static-next-server/src/lib.rs diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml new file mode 100644 index 00000000..b6a08f11 --- /dev/null +++ b/axum/static-next-server/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "static-next-server" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +axum = "0.6.1" +axum-extra = { version = "0.4.2", features = ["spa"] } +shuttle-service = { version = "0.9.0", features = ["web-axum"] } +shuttle-static-folder = "0.9.0" +sync_wrapper = "0.1.1" diff --git a/axum/static-next-server/README.md b/axum/static-next-server/README.md new file mode 100644 index 00000000..c8143c23 --- /dev/null +++ b/axum/static-next-server/README.md @@ -0,0 +1,3 @@ +# Serving a NextJS project with Axum + +This example is a template for an [axum](https://github.com/tokio-rs/axum) server that serves a NextJS single-page application as static assets, deployed with shuttle. For more information on how to achieve this, check out this article by one of our contributors: https://joshmo.hashnode.dev/deploying-a-nextjs-front-end-with-a-rust-api-in-one-go diff --git a/axum/static-next-server/src/lib.rs b/axum/static-next-server/src/lib.rs new file mode 100644 index 00000000..66fb9ed3 --- /dev/null +++ b/axum/static-next-server/src/lib.rs @@ -0,0 +1,17 @@ +use std::path::PathBuf; + +use axum::Router; +use axum_extra::routing::SpaRouter; +use sync_wrapper::SyncWrapper; + +#[shuttle_service::main] +async fn axum( + #[shuttle_static_folder::StaticFolder] static_folder: PathBuf, +) -> shuttle_service::ShuttleAxum { + let router = + Router::new().merge(SpaRouter::new("/assets", static_folder).index_file("index.html")); + + let sync_wrapper = SyncWrapper::new(router); + + Ok(sync_wrapper) +} From d9e648e5884ce625880a9101a640a5e598faa34e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Mon, 6 Feb 2023 15:04:34 +0100 Subject: [PATCH 019/239] fix: path to serve assets from (#17) The index.html generated by create-next-app assumes the assets are in `.`, so if we use `/assets` we will just see a page with text, no css, svgs etc. --- axum/static-next-server/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/axum/static-next-server/src/lib.rs b/axum/static-next-server/src/lib.rs index 66fb9ed3..fd2d4623 100644 --- a/axum/static-next-server/src/lib.rs +++ b/axum/static-next-server/src/lib.rs @@ -9,7 +9,7 @@ async fn axum( #[shuttle_static_folder::StaticFolder] static_folder: PathBuf, ) -> shuttle_service::ShuttleAxum { let router = - Router::new().merge(SpaRouter::new("/assets", static_folder).index_file("index.html")); + Router::new().merge(SpaRouter::new("/", static_folder).index_file("index.html")); let sync_wrapper = SyncWrapper::new(router); From 3f6a10ad00481c81b788ba9d7ec86f6064151d9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Mon, 6 Feb 2023 16:03:02 +0100 Subject: [PATCH 020/239] feat: add .gitignore to static-next-server (#18) --- axum/static-next-server/.gitgnore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 axum/static-next-server/.gitgnore diff --git a/axum/static-next-server/.gitgnore b/axum/static-next-server/.gitgnore new file mode 100644 index 00000000..54c8ecc2 --- /dev/null +++ b/axum/static-next-server/.gitgnore @@ -0,0 +1,3 @@ +# Generated by Cargo +# will have compiled files and executables +**/target/ From 1b8e38e55e14db580aded82608e009601fe50a22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Mon, 6 Feb 2023 17:16:52 +0100 Subject: [PATCH 021/239] fix: gitignore filename (#19) --- axum/static-next-server/{.gitgnore => .gitignore} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename axum/static-next-server/{.gitgnore => .gitignore} (100%) diff --git a/axum/static-next-server/.gitgnore b/axum/static-next-server/.gitignore similarity index 100% rename from axum/static-next-server/.gitgnore rename to axum/static-next-server/.gitignore From c28f1637068944ffdd75e81da9c1708729a1d17a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Fri, 10 Feb 2023 14:06:50 +0000 Subject: [PATCH 022/239] chore: v0.10.0 (#20) --- actix-web/hello-world/Cargo.toml | 2 +- actix-web/postgres/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 2 +- axum/static-files/Cargo.toml | 4 ++-- axum/static-next-server/Cargo.toml | 4 ++-- axum/websocket/Cargo.toml | 4 ++-- poem/hello-world/Cargo.toml | 2 +- poem/mongodb/Cargo.toml | 4 ++-- poem/postgres/Cargo.toml | 4 ++-- poise/hello-world/Cargo.toml | 4 ++-- rocket/authentication/Cargo.toml | 2 +- rocket/hello-world/Cargo.toml | 2 +- rocket/persist/Cargo.toml | 4 ++-- rocket/postgres/Cargo.toml | 4 ++-- rocket/secrets/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 2 +- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 6 +++--- thruster/hello-world/Cargo.toml | 2 +- thruster/postgres/Cargo.toml | 4 ++-- tide/hello-world/Cargo.toml | 2 +- tide/postgres/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 2 +- warp/hello-world/Cargo.toml | 2 +- 26 files changed, 43 insertions(+), 43 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index d5a1a36f..73f86f12 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,4 +5,4 @@ edition = "2021" [dependencies] actix-web = "4.2.1" -shuttle-service = { version = '0.9.0', features = ["web-actix-web"] } +shuttle-service = { version = '0.10.0', features = ["web-actix-web"] } diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 711ad44b..cf2f7035 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -8,6 +8,6 @@ edition = "2021" [dependencies] actix-web = "4.2.1" serde = "1.0.148" -shuttle-service = { version = "0.9.0", features = ["web-actix-web"] } -shuttle-shared-db = { version = "0.9.0", features = ["postgres"] } +shuttle-service = { version = "0.10.0", features = ["web-actix-web"] } +shuttle-shared-db = { version = "0.10.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 309c732c..a29ed279 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -7,8 +7,8 @@ publish = false [lib] [dependencies] -shuttle-service = { version = "0.9.0", features = ["web-actix-web"] } -shuttle-static-folder = "0.9.0" +shuttle-service = { version = "0.10.0", features = ["web-actix-web"] } +shuttle-static-folder = "0.10.0" actix-web = "4.2.1" actix-ws = "0.2.5" actix-files = "0.6.2" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 7e05e870..e5a59679 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -7,5 +7,5 @@ edition = "2021" [dependencies] axum = "0.6.0" -shuttle-service = { version = "0.9.0", features = ["web-axum"] } +shuttle-service = { version = "0.10.0", features = ["web-axum"] } sync_wrapper = "0.1.1" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 047fda2b..cda0a552 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -7,6 +7,6 @@ publish = false [dependencies] axum = "0.6.1" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-service = { version = "0.9.0", features = ["web-axum"] } -shuttle-static-folder = "0.9.0" +shuttle-service = { version = "0.10.0", features = ["web-axum"] } +shuttle-static-folder = "0.10.0" sync_wrapper = "0.1.1" diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index b6a08f11..bca9fb7f 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,6 +7,6 @@ publish = false [dependencies] axum = "0.6.1" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-service = { version = "0.9.0", features = ["web-axum"] } -shuttle-static-folder = "0.9.0" +shuttle-service = { version = "0.10.0", features = ["web-axum"] } +shuttle-static-folder = "0.10.0" sync_wrapper = "0.1.1" diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index d435b875..09d71edc 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -13,8 +13,8 @@ hyper = { version = "0.14.23", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-service = { version = "0.9.0", features = ["web-axum"] } -shuttle-static-folder = "0.9.0" +shuttle-service = { version = "0.10.0", features = ["web-axum"] } +shuttle-static-folder = "0.10.0" sync_wrapper = "0.1.1" tokio = { version = "1.22.0", features = ["full"] } tower-http = { version = "0.3.0", features = ["fs"] } diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 8d01e274..f8ca097f 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] poem = "1.3.49" -shuttle-service = { version = "0.9.0", features = ["web-poem"] } +shuttle-service = { version = "0.10.0", features = ["web-poem"] } diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 39d6ac48..ce2e6dd1 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -8,5 +8,5 @@ mongodb = "2.3.1" poem = "1.3.49" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-service = { version = "0.9.0", features = ["web-poem"] } -shuttle-shared-db = { version = "0.9.0", features = ["mongodb"] } +shuttle-service = { version = "0.10.0", features = ["web-poem"] } +shuttle-shared-db = { version = "0.10.0", features = ["mongodb"] } diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 639aca48..94e05425 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -8,6 +8,6 @@ edition = "2021" [dependencies] poem = "1.3.49" serde = "1.0.148" -shuttle-service = { version = "0.9.0", features = ["web-poem"] } -shuttle-shared-db = { version = "0.9.0", features = ["postgres"] } +shuttle-service = { version = "0.10.0", features = ["web-poem"] } +shuttle-shared-db = { version = "0.10.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index b88fb37b..40bee3c0 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [lib] [dependencies] -shuttle-service = { version = "0.9.0", features = ["bot-poise"] } +shuttle-service = { version = "0.10.0", features = ["bot-poise"] } anyhow = "1.0.68" -shuttle-secrets = "0.9.0" +shuttle-secrets = "0.10.0" tracing = "0.1.37" poise = "0.5.2" diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index fbd192d4..fd86848d 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -11,4 +11,4 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-service = { version = "0.9.0", features = ["web-rocket"] } +shuttle-service = { version = "0.10.0", features = ["web-rocket"] } diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index b417a435..1b2da0aa 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-service = { version = "0.9.0", features = ["web-rocket"] } +shuttle-service = { version = "0.10.0", features = ["web-rocket"] } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index fc004dc6..91390719 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -8,5 +8,5 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.9.0" -shuttle-service = { version = "0.9.0", features = ["web-rocket"] } +shuttle-persist = "0.10.0" +shuttle-service = { version = "0.10.0", features = ["web-rocket"] } diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index cbdb58aa..86ccae79 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -8,6 +8,6 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-service = { version = "0.9.0", features = ["web-rocket"] } -shuttle-shared-db = { version = "0.9.0", features = ["postgres"] } +shuttle-service = { version = "0.10.0", features = ["web-rocket"] } +shuttle-shared-db = { version = "0.10.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 2b9cbb7a..94a0f836 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -8,5 +8,5 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-secrets = "0.9.0" -shuttle-service = { version = "0.9.0", features = ["web-rocket"] } +shuttle-secrets = "0.10.0" +shuttle-service = { version = "0.10.0", features = ["web-rocket"] } diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 780ac49c..1a934ed4 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-service = { version = "0.9.0", features = ["web-rocket"] } -shuttle-shared-db = { version = "0.9.0", features = ["postgres"] } +shuttle-service = { version = "0.10.0", features = ["web-rocket"] } +shuttle-shared-db = { version = "0.10.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } url = "2.3.1" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 148a350e..94763ddc 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] salvo = "0.37.5" -shuttle-service = { version = "0.9.0", features = ["web-salvo"] } +shuttle-service = { version = "0.10.0", features = ["web-salvo"] } diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 8677ebe2..903d12e1 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -8,6 +8,6 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.9.0" -shuttle-service = { version = "0.9.0", features = ["bot-serenity"] } +shuttle-secrets = "0.10.0" +shuttle-service = { version = "0.10.0", features = ["bot-serenity"] } tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 628a3aa6..31a047fa 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -9,8 +9,8 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.9.0" -shuttle-service = { version = "0.9.0", features = ["bot-serenity"] } -shuttle-shared-db = { version = "0.9.0", features = ["postgres"] } +shuttle-secrets = "0.10.0" +shuttle-service = { version = "0.10.0", features = ["bot-serenity"] } +shuttle-shared-db = { version = "0.10.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 8bbdc085..f2141994 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" [lib] [dependencies] -shuttle-service = { version = "0.9.0", features = ["web-thruster"] } +shuttle-service = { version = "0.10.0", features = ["web-thruster"] } thruster = { version = "1.3.0", features = ["hyper_server"] } diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index c96b204c..7847420c 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -11,7 +11,7 @@ crate-type = ["cdylib"] hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.9.0", features = ["postgres"] } -shuttle-service = { version = "0.9.0", features = ["web-thruster"] } +shuttle-aws-rds = { version = "0.10.0", features = ["postgres"] } +shuttle-service = { version = "0.10.0", features = ["web-thruster"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 503fd6bd..34d3d471 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" [lib] [dependencies] -shuttle-service = { version = "0.9.0", features = ["web-tide"] } +shuttle-service = { version = "0.10.0", features = ["web-tide"] } tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index efcd41b9..db8815ee 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["cdylib"] [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.9.0", features = ["postgres"] } -shuttle-service = { version = "0.9.0", features = ["web-tide"] } +shuttle-aws-rds = { version = "0.10.0", features = ["postgres"] } +shuttle-service = { version = "0.10.0", features = ["web-tide"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index cc22e3f2..0a04589f 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -7,5 +7,5 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-service = { version = "0.9.0", features = ["web-tower"] } +shuttle-service = { version = "0.10.0", features = ["web-tower"] } tower = { version = "0.4.13", features = ["full"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 5a90fb16..c3fbb9ce 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" [lib] [dependencies] -shuttle-service = { version = "0.9.0", features = ["web-warp"] } +shuttle-service = { version = "0.10.0", features = ["web-warp"] } warp = "0.3.3" From 3ad8b148d0969188f618654bd11ebcbd825d0057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Tue, 14 Feb 2023 13:33:18 +0000 Subject: [PATCH 023/239] feat: gitignore static folder, but allow it for shuttle (#21) --- axum/static-next-server/.gitignore | 1 + axum/static-next-server/.ignore | 1 + 2 files changed, 2 insertions(+) create mode 100644 axum/static-next-server/.ignore diff --git a/axum/static-next-server/.gitignore b/axum/static-next-server/.gitignore index 54c8ecc2..0580e83d 100644 --- a/axum/static-next-server/.gitignore +++ b/axum/static-next-server/.gitignore @@ -1,3 +1,4 @@ # Generated by Cargo # will have compiled files and executables **/target/ +static/ diff --git a/axum/static-next-server/.ignore b/axum/static-next-server/.ignore new file mode 100644 index 00000000..5016c4e0 --- /dev/null +++ b/axum/static-next-server/.ignore @@ -0,0 +1 @@ +!static/ From 94c5dd331e47f7177637c7f119ed51c59f172236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Mon, 27 Feb 2023 18:33:59 +0000 Subject: [PATCH 024/239] chore: v0.11.0 (#22) --- actix-web/hello-world/Cargo.toml | 2 +- actix-web/postgres/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 2 +- axum/static-files/Cargo.toml | 4 ++-- axum/static-next-server/Cargo.toml | 4 ++-- axum/websocket/Cargo.toml | 4 ++-- poem/hello-world/Cargo.toml | 2 +- poem/mongodb/Cargo.toml | 4 ++-- poem/postgres/Cargo.toml | 4 ++-- poise/hello-world/Cargo.toml | 4 ++-- rocket/authentication/Cargo.toml | 2 +- rocket/hello-world/Cargo.toml | 2 +- rocket/persist/Cargo.toml | 4 ++-- rocket/postgres/Cargo.toml | 4 ++-- rocket/secrets/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 2 +- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 6 +++--- thruster/hello-world/Cargo.toml | 2 +- thruster/postgres/Cargo.toml | 4 ++-- tide/hello-world/Cargo.toml | 2 +- tide/postgres/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 2 +- warp/hello-world/Cargo.toml | 2 +- 26 files changed, 43 insertions(+), 43 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 73f86f12..f7944ee0 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,4 +5,4 @@ edition = "2021" [dependencies] actix-web = "4.2.1" -shuttle-service = { version = '0.10.0', features = ["web-actix-web"] } +shuttle-service = { version = '0.11.0', features = ["web-actix-web"] } diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index cf2f7035..d5cd42bb 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -8,6 +8,6 @@ edition = "2021" [dependencies] actix-web = "4.2.1" serde = "1.0.148" -shuttle-service = { version = "0.10.0", features = ["web-actix-web"] } -shuttle-shared-db = { version = "0.10.0", features = ["postgres"] } +shuttle-service = { version = "0.11.0", features = ["web-actix-web"] } +shuttle-shared-db = { version = "0.11.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index a29ed279..3f765d36 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -7,8 +7,8 @@ publish = false [lib] [dependencies] -shuttle-service = { version = "0.10.0", features = ["web-actix-web"] } -shuttle-static-folder = "0.10.0" +shuttle-service = { version = "0.11.0", features = ["web-actix-web"] } +shuttle-static-folder = "0.11.0" actix-web = "4.2.1" actix-ws = "0.2.5" actix-files = "0.6.2" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index e5a59679..4bf2e42f 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -7,5 +7,5 @@ edition = "2021" [dependencies] axum = "0.6.0" -shuttle-service = { version = "0.10.0", features = ["web-axum"] } +shuttle-service = { version = "0.11.0", features = ["web-axum"] } sync_wrapper = "0.1.1" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index cda0a552..3010c1b3 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -7,6 +7,6 @@ publish = false [dependencies] axum = "0.6.1" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-service = { version = "0.10.0", features = ["web-axum"] } -shuttle-static-folder = "0.10.0" +shuttle-service = { version = "0.11.0", features = ["web-axum"] } +shuttle-static-folder = "0.11.0" sync_wrapper = "0.1.1" diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index bca9fb7f..c8b1f8a5 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,6 +7,6 @@ publish = false [dependencies] axum = "0.6.1" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-service = { version = "0.10.0", features = ["web-axum"] } -shuttle-static-folder = "0.10.0" +shuttle-service = { version = "0.11.0", features = ["web-axum"] } +shuttle-static-folder = "0.11.0" sync_wrapper = "0.1.1" diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 09d71edc..9e06ff44 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -13,8 +13,8 @@ hyper = { version = "0.14.23", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-service = { version = "0.10.0", features = ["web-axum"] } -shuttle-static-folder = "0.10.0" +shuttle-service = { version = "0.11.0", features = ["web-axum"] } +shuttle-static-folder = "0.11.0" sync_wrapper = "0.1.1" tokio = { version = "1.22.0", features = ["full"] } tower-http = { version = "0.3.0", features = ["fs"] } diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index f8ca097f..c1e21d8f 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] poem = "1.3.49" -shuttle-service = { version = "0.10.0", features = ["web-poem"] } +shuttle-service = { version = "0.11.0", features = ["web-poem"] } diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index ce2e6dd1..07e14501 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -8,5 +8,5 @@ mongodb = "2.3.1" poem = "1.3.49" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-service = { version = "0.10.0", features = ["web-poem"] } -shuttle-shared-db = { version = "0.10.0", features = ["mongodb"] } +shuttle-service = { version = "0.11.0", features = ["web-poem"] } +shuttle-shared-db = { version = "0.11.0", features = ["mongodb"] } diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 94e05425..d54a82b4 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -8,6 +8,6 @@ edition = "2021" [dependencies] poem = "1.3.49" serde = "1.0.148" -shuttle-service = { version = "0.10.0", features = ["web-poem"] } -shuttle-shared-db = { version = "0.10.0", features = ["postgres"] } +shuttle-service = { version = "0.11.0", features = ["web-poem"] } +shuttle-shared-db = { version = "0.11.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 40bee3c0..334fea1e 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [lib] [dependencies] -shuttle-service = { version = "0.10.0", features = ["bot-poise"] } +shuttle-service = { version = "0.11.0", features = ["bot-poise"] } anyhow = "1.0.68" -shuttle-secrets = "0.10.0" +shuttle-secrets = "0.11.0" tracing = "0.1.37" poise = "0.5.2" diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index fd86848d..3719877d 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -11,4 +11,4 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-service = { version = "0.10.0", features = ["web-rocket"] } +shuttle-service = { version = "0.11.0", features = ["web-rocket"] } diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 1b2da0aa..4cc9ffc1 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-service = { version = "0.10.0", features = ["web-rocket"] } +shuttle-service = { version = "0.11.0", features = ["web-rocket"] } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 91390719..268a7cdb 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -8,5 +8,5 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.10.0" -shuttle-service = { version = "0.10.0", features = ["web-rocket"] } +shuttle-persist = "0.11.0" +shuttle-service = { version = "0.11.0", features = ["web-rocket"] } diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 86ccae79..2d8d6db9 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -8,6 +8,6 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-service = { version = "0.10.0", features = ["web-rocket"] } -shuttle-shared-db = { version = "0.10.0", features = ["postgres"] } +shuttle-service = { version = "0.11.0", features = ["web-rocket"] } +shuttle-shared-db = { version = "0.11.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 94a0f836..efa8f77f 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -8,5 +8,5 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-secrets = "0.10.0" -shuttle-service = { version = "0.10.0", features = ["web-rocket"] } +shuttle-secrets = "0.11.0" +shuttle-service = { version = "0.11.0", features = ["web-rocket"] } diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 1a934ed4..9251ca98 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-service = { version = "0.10.0", features = ["web-rocket"] } -shuttle-shared-db = { version = "0.10.0", features = ["postgres"] } +shuttle-service = { version = "0.11.0", features = ["web-rocket"] } +shuttle-shared-db = { version = "0.11.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } url = "2.3.1" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 94763ddc..3f1e8a38 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] salvo = "0.37.5" -shuttle-service = { version = "0.10.0", features = ["web-salvo"] } +shuttle-service = { version = "0.11.0", features = ["web-salvo"] } diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 903d12e1..e60312c7 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -8,6 +8,6 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.10.0" -shuttle-service = { version = "0.10.0", features = ["bot-serenity"] } +shuttle-secrets = "0.11.0" +shuttle-service = { version = "0.11.0", features = ["bot-serenity"] } tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 31a047fa..f61c1a38 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -9,8 +9,8 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.10.0" -shuttle-service = { version = "0.10.0", features = ["bot-serenity"] } -shuttle-shared-db = { version = "0.10.0", features = ["postgres"] } +shuttle-secrets = "0.11.0" +shuttle-service = { version = "0.11.0", features = ["bot-serenity"] } +shuttle-shared-db = { version = "0.11.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index f2141994..d6a211da 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" [lib] [dependencies] -shuttle-service = { version = "0.10.0", features = ["web-thruster"] } +shuttle-service = { version = "0.11.0", features = ["web-thruster"] } thruster = { version = "1.3.0", features = ["hyper_server"] } diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 7847420c..e8ca94b4 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -11,7 +11,7 @@ crate-type = ["cdylib"] hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.10.0", features = ["postgres"] } -shuttle-service = { version = "0.10.0", features = ["web-thruster"] } +shuttle-aws-rds = { version = "0.11.0", features = ["postgres"] } +shuttle-service = { version = "0.11.0", features = ["web-thruster"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 34d3d471..a55bf8c1 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" [lib] [dependencies] -shuttle-service = { version = "0.10.0", features = ["web-tide"] } +shuttle-service = { version = "0.11.0", features = ["web-tide"] } tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index db8815ee..d1fbabcb 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["cdylib"] [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.10.0", features = ["postgres"] } -shuttle-service = { version = "0.10.0", features = ["web-tide"] } +shuttle-aws-rds = { version = "0.11.0", features = ["postgres"] } +shuttle-service = { version = "0.11.0", features = ["web-tide"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 0a04589f..00a0820a 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -7,5 +7,5 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-service = { version = "0.10.0", features = ["web-tower"] } +shuttle-service = { version = "0.11.0", features = ["web-tower"] } tower = { version = "0.4.13", features = ["full"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index c3fbb9ce..33946168 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" [lib] [dependencies] -shuttle-service = { version = "0.10.0", features = ["web-warp"] } +shuttle-service = { version = "0.11.0", features = ["web-warp"] } warp = "0.3.3" From 2a599dd9fbf5ea9b1ce675a946ecebb9cae92524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Wed, 8 Mar 2023 11:10:27 +0000 Subject: [PATCH 025/239] chore: v0.11.3 (#25) --- actix-web/websocket-actorless/Cargo.toml | 2 +- axum/static-files/Cargo.toml | 2 +- axum/static-next-server/Cargo.toml | 2 +- axum/websocket/Cargo.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 3f765d36..a8bcaaea 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dependencies] shuttle-service = { version = "0.11.0", features = ["web-actix-web"] } -shuttle-static-folder = "0.11.0" +shuttle-static-folder = "0.11.3" actix-web = "4.2.1" actix-ws = "0.2.5" actix-files = "0.6.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 3010c1b3..c2425b6c 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -8,5 +8,5 @@ publish = false axum = "0.6.1" axum-extra = { version = "0.4.2", features = ["spa"] } shuttle-service = { version = "0.11.0", features = ["web-axum"] } -shuttle-static-folder = "0.11.0" +shuttle-static-folder = "0.11.3" sync_wrapper = "0.1.1" diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index c8b1f8a5..d9eeaf33 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -8,5 +8,5 @@ publish = false axum = "0.6.1" axum-extra = { version = "0.4.2", features = ["spa"] } shuttle-service = { version = "0.11.0", features = ["web-axum"] } -shuttle-static-folder = "0.11.0" +shuttle-static-folder = "0.11.3" sync_wrapper = "0.1.1" diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 9e06ff44..12f7433c 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -14,7 +14,7 @@ hyper-tls = "0.5.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" shuttle-service = { version = "0.11.0", features = ["web-axum"] } -shuttle-static-folder = "0.11.0" +shuttle-static-folder = "0.11.3" sync_wrapper = "0.1.1" tokio = { version = "1.22.0", features = ["full"] } tower-http = { version = "0.3.0", features = ["fs"] } From ecc256fc9cb4d9d642c20efd21d2b9714856a72d Mon Sep 17 00:00:00 2001 From: Iulian Barbu <14218860+iulianbarbu@users.noreply.github.com> Date: Fri, 17 Mar 2023 15:26:46 +0200 Subject: [PATCH 026/239] chore(static-next-server/README): added notes on why static... (#31) ...folder is missing Co-authored-by: Iulian Barbu --- axum/static-next-server/README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/axum/static-next-server/README.md b/axum/static-next-server/README.md index c8143c23..ca599ac6 100644 --- a/axum/static-next-server/README.md +++ b/axum/static-next-server/README.md @@ -1,3 +1,9 @@ # Serving a NextJS project with Axum -This example is a template for an [axum](https://github.com/tokio-rs/axum) server that serves a NextJS single-page application as static assets, deployed with shuttle. For more information on how to achieve this, check out this article by one of our contributors: https://joshmo.hashnode.dev/deploying-a-nextjs-front-end-with-a-rust-api-in-one-go +This example is a template for an [axum](https://github.com/tokio-rs/axum) server that serves a NextJS single-page application as static assets, deployed with shuttle. For more information on how to achieve this, check out this article by one of our contributors: https://joshmo.hashnode.dev/deploying-a-nextjs-front-end-with-a-rust-api-in-one-go. + +## Note + +This project misses the `static` NextJS bundle because it's common to not commit it to GitHub. This is done through a `.gitignore`, but Shuttle uses a `.ignore` file which waves the `.gitignore` rule. That's because otherwise Shuttle wouldn't package the `static` directory to be able to deploy it, because of the `.gitignore` filtering. + +As a result, building this project or trying to run it locally will fail because of the missing `static` folder. From 64b2cd2dc826863525519bbcf4617cb9ca54f69f Mon Sep 17 00:00:00 2001 From: Pieter Date: Mon, 20 Mar 2023 11:38:05 +0200 Subject: [PATCH 027/239] feat: shuttle next (#27) * feat: initial commit of shuttle-next example * feat: add post endpoint * feat: convert all examples to bins * feat: remove syncwrapper * feat: refactor axum hello-world * feat: from impl for AxumService * feat: update all axum examples * feat: update actix examples (postgres not working) * feat: update poem examples * feat: update poise example * feat: update rocket examples * feat: update serenity and salvo * feat: update thruster examples * feat: update the tower and warp examples * feat: update tide examples * misc: bump versions (#28) * misc: v0.12.0-rc1 (#29) * refactor: update next example (#30) * chore: v0.12.0 (#32) --------- Co-authored-by: oddgrd <29732646+oddgrd@users.noreply.github.com> --- .gitignore | 1 + actix-web/hello-world/Cargo.toml | 6 ++-- actix-web/hello-world/src/lib.rs | 15 --------- actix-web/hello-world/src/main.rs | 17 ++++++++++ actix-web/postgres/Cargo.toml | 10 +++--- actix-web/postgres/src/{lib.rs => main.rs} | 13 +++++--- actix-web/websocket-actorless/Cargo.toml | 15 ++++----- .../src/{lib.rs => main.rs} | 11 ++++--- axum/hello-world/Cargo.toml | 9 +++-- axum/hello-world/src/lib.rs | 14 -------- axum/hello-world/src/main.rs | 12 +++++++ axum/static-files/Cargo.toml | 9 ++--- axum/static-files/src/{lib.rs => main.rs} | 9 ++--- axum/static-next-server/Cargo.toml | 9 ++--- .../src/{lib.rs => main.rs} | 9 ++--- axum/websocket/Cargo.toml | 12 +++---- axum/websocket/src/{lib.rs => main.rs} | 11 +++---- next/hello-world/Cargo.toml | 13 ++++++++ next/hello-world/src/lib.rs | 33 +++++++++++++++++++ poem/hello-world/Cargo.toml | 8 ++--- poem/hello-world/src/{lib.rs => main.rs} | 7 ++-- poem/mongodb/Cargo.toml | 10 +++--- poem/mongodb/src/{lib.rs => main.rs} | 9 ++--- poem/postgres/Cargo.toml | 10 +++--- poem/postgres/src/{lib.rs => main.rs} | 11 ++++--- poise/hello-world/Cargo.toml | 10 +++--- poise/hello-world/src/{lib.rs => main.rs} | 8 ++--- rocket/authentication/Cargo.toml | 6 ++-- rocket/authentication/src/{lib.rs => main.rs} | 6 ++-- rocket/hello-world/Cargo.toml | 6 ++-- rocket/hello-world/src/{lib.rs => main.rs} | 6 ++-- rocket/persist/Cargo.toml | 8 ++--- rocket/persist/src/{lib.rs => main.rs} | 6 ++-- rocket/postgres/Cargo.toml | 8 ++--- rocket/postgres/src/{lib.rs => main.rs} | 8 ++--- rocket/secrets/Cargo.toml | 10 +++--- rocket/secrets/src/{lib.rs => main.rs} | 6 ++-- rocket/url-shortener/Cargo.toml | 8 ++--- rocket/url-shortener/src/{lib.rs => main.rs} | 8 ++--- salvo/hello-world/Cargo.toml | 7 ++-- salvo/hello-world/src/{lib.rs => main.rs} | 6 ++-- serenity/hello-world/Cargo.toml | 8 ++--- serenity/hello-world/src/{lib.rs => main.rs} | 6 ++-- serenity/postgres/Cargo.toml | 10 +++--- serenity/postgres/src/{lib.rs => main.rs} | 6 ++-- thruster/hello-world/Cargo.toml | 6 ++-- thruster/hello-world/src/{lib.rs => main.rs} | 10 +++--- thruster/postgres/Cargo.toml | 10 +++--- thruster/postgres/src/{lib.rs => main.rs} | 12 ++++--- tide/hello-world/Cargo.toml | 6 ++-- tide/hello-world/src/{lib.rs => main.rs} | 6 ++-- tide/postgres/Cargo.toml | 10 +++--- tide/postgres/src/{lib.rs => main.rs} | 7 ++-- tower/hello-world/Cargo.toml | 6 ++-- tower/hello-world/src/{lib.rs => main.rs} | 8 +++-- warp/hello-world/Cargo.toml | 6 ++-- warp/hello-world/src/lib.rs | 8 ----- warp/hello-world/src/main.rs | 8 +++++ 58 files changed, 292 insertions(+), 241 deletions(-) delete mode 100644 actix-web/hello-world/src/lib.rs create mode 100644 actix-web/hello-world/src/main.rs rename actix-web/postgres/src/{lib.rs => main.rs} (85%) rename actix-web/websocket-actorless/src/{lib.rs => main.rs} (96%) delete mode 100644 axum/hello-world/src/lib.rs create mode 100644 axum/hello-world/src/main.rs rename axum/static-files/src/{lib.rs => main.rs} (77%) rename axum/static-next-server/src/{lib.rs => main.rs} (62%) rename axum/websocket/src/{lib.rs => main.rs} (94%) create mode 100644 next/hello-world/Cargo.toml create mode 100644 next/hello-world/src/lib.rs rename poem/hello-world/src/{lib.rs => main.rs} (56%) rename poem/mongodb/src/{lib.rs => main.rs} (93%) rename poem/postgres/src/{lib.rs => main.rs} (88%) rename poise/hello-world/src/{lib.rs => main.rs} (90%) rename rocket/authentication/src/{lib.rs => main.rs} (94%) rename rocket/hello-world/src/{lib.rs => main.rs} (62%) rename rocket/persist/src/{lib.rs => main.rs} (94%) rename rocket/postgres/src/{lib.rs => main.rs} (92%) rename rocket/secrets/src/{lib.rs => main.rs} (89%) rename rocket/url-shortener/src/{lib.rs => main.rs} (94%) rename salvo/hello-world/src/{lib.rs => main.rs} (66%) rename serenity/hello-world/src/{lib.rs => main.rs} (93%) rename serenity/postgres/src/{lib.rs => main.rs} (98%) rename thruster/hello-world/src/{lib.rs => main.rs} (72%) rename thruster/postgres/src/{lib.rs => main.rs} (93%) rename tide/hello-world/src/{lib.rs => main.rs} (60%) rename tide/postgres/src/{lib.rs => main.rs} (92%) rename tower/hello-world/src/{lib.rs => main.rs} (86%) delete mode 100644 warp/hello-world/src/lib.rs create mode 100644 warp/hello-world/src/main.rs diff --git a/.gitignore b/.gitignore index 2c96eb1b..246d500b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ target/ Cargo.lock +.cargo diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index f7944ee0..cae47b6c 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -4,5 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -actix-web = "4.2.1" -shuttle-service = { version = '0.11.0', features = ["web-actix-web"] } +actix-web = "4.3.1" +shuttle-actix-web = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } +tokio = { version = "1.26.0" } diff --git a/actix-web/hello-world/src/lib.rs b/actix-web/hello-world/src/lib.rs deleted file mode 100644 index a78719db..00000000 --- a/actix-web/hello-world/src/lib.rs +++ /dev/null @@ -1,15 +0,0 @@ -use actix_web::{get, web::ServiceConfig}; -use shuttle_service::ShuttleActixWeb; - -#[get("/hello")] -async fn hello_world() -> &'static str { - "Hello World!" -} - -#[shuttle_service::main] -async fn actix_web( -) -> ShuttleActixWeb { - Ok(move |cfg: &mut ServiceConfig| { - cfg.service(hello_world); - }) -} diff --git a/actix-web/hello-world/src/main.rs b/actix-web/hello-world/src/main.rs new file mode 100644 index 00000000..e1bc4b0e --- /dev/null +++ b/actix-web/hello-world/src/main.rs @@ -0,0 +1,17 @@ +use actix_web::{get, web::ServiceConfig}; +use shuttle_actix_web::ShuttleActixWeb; + +#[get("/hello")] +async fn hello_world() -> &'static str { + "Hello World!" +} + +#[shuttle_runtime::main] +async fn actix_web( +) -> ShuttleActixWeb { + let config = move |cfg: &mut ServiceConfig| { + cfg.service(hello_world); + }; + + Ok(config.into()) +} diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index d5cd42bb..6b9c3aa4 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -3,11 +3,11 @@ name = "postgres" version = "0.1.0" edition = "2021" -[lib] - [dependencies] -actix-web = "4.2.1" +actix-web = "4.3.1" +shuttle-actix-web = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } serde = "1.0.148" -shuttle-service = { version = "0.11.0", features = ["web-actix-web"] } -shuttle-shared-db = { version = "0.11.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.12.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } +tokio = { version = "1.26.0" } diff --git a/actix-web/postgres/src/lib.rs b/actix-web/postgres/src/main.rs similarity index 85% rename from actix-web/postgres/src/lib.rs rename to actix-web/postgres/src/main.rs index 3e18ae7f..c6b018d1 100644 --- a/actix-web/postgres/src/lib.rs +++ b/actix-web/postgres/src/main.rs @@ -5,7 +5,8 @@ use actix_web::{ Result, }; use serde::{Deserialize, Serialize}; -use shuttle_service::{error::CustomError, ShuttleActixWeb}; +use shuttle_actix_web::ShuttleActixWeb; +use shuttle_runtime::{CustomError}; use sqlx::{Executor, FromRow, PgPool}; #[get("/{id}")] @@ -35,17 +36,17 @@ struct AppState { pool: PgPool, } -#[shuttle_service::main] +#[shuttle_runtime::main] async fn actix_web( #[shuttle_shared_db::Postgres] pool: PgPool, -) -> ShuttleActixWeb { +) -> ShuttleActixWeb { pool.execute(include_str!("../schema.sql")) .await .map_err(CustomError::new)?; let state = web::Data::new(AppState { pool }); - Ok(move |cfg: &mut ServiceConfig| { + let config = move |cfg: &mut ServiceConfig| { cfg.service( web::scope("/todos") .wrap(Logger::default()) @@ -53,7 +54,9 @@ async fn actix_web( .service(add) .app_data(state), ); - }) + }; + + Ok(config.into()) } #[derive(Deserialize)] diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index a8bcaaea..9427f832 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -4,18 +4,17 @@ version = "0.1.0" edition = "2021" publish = false -[lib] - [dependencies] -shuttle-service = { version = "0.11.0", features = ["web-actix-web"] } -shuttle-static-folder = "0.11.3" -actix-web = "4.2.1" -actix-ws = "0.2.5" actix-files = "0.6.2" +actix-web = "4.3.1" +actix-ws = "0.2.5" +chrono = { version = "0.4.23", features = ["serde"] } futures = "0.3" reqwest = "0.11" -tokio = { version = "1", features = ["rt-multi-thread", "sync"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -chrono = { version = "0.4.23", features = ["serde"] } +shuttle-actix-web = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } +shuttle-static-folder = "0.12.0" +tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/actix-web/websocket-actorless/src/lib.rs b/actix-web/websocket-actorless/src/main.rs similarity index 96% rename from actix-web/websocket-actorless/src/lib.rs rename to actix-web/websocket-actorless/src/main.rs index d2012e02..459b6870 100644 --- a/actix-web/websocket-actorless/src/lib.rs +++ b/actix-web/websocket-actorless/src/main.rs @@ -7,7 +7,7 @@ use actix_ws::Message; use chrono::{DateTime, Utc}; use futures::StreamExt; use serde::Serialize; -use shuttle_service::ShuttleActixWeb; +use shuttle_actix_web::ShuttleActixWeb; use std::{ sync::{atomic::AtomicUsize, Arc}, time::Duration, @@ -104,9 +104,9 @@ async fn index() -> impl Responder { .map_err(|e| actix_web::error::ErrorInternalServerError(e)) } -#[shuttle_service::main] +#[shuttle_runtime::main] async fn actix_web( -) -> ShuttleActixWeb { +) -> ShuttleActixWeb { // We're going to use channels to communicate between threads. // api state channel let (tx_api_state, rx_api_state) = watch::channel(ApiStateMessage::default()); @@ -179,14 +179,15 @@ async fn actix_web( let app_state = web::Data::new((tx_ws_state, rx_api_state)); - Ok(move |cfg: &mut ServiceConfig| { + let config = move |cfg: &mut ServiceConfig| { cfg.service(web::resource("/").route(web::get().to(index))) .service( web::resource("/ws") .app_data(app_state) .route(web::get().to(websocket)), ); - }) + }; + Ok(config.into()) } async fn get_api_status(client: &reqwest::Client) -> bool { diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 4bf2e42f..57143b3a 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -3,9 +3,8 @@ name = "hello-world" version = "0.1.0" edition = "2021" -[lib] - [dependencies] -axum = "0.6.0" -shuttle-service = { version = "0.11.0", features = ["web-axum"] } -sync_wrapper = "0.1.1" +axum = "0.6.10" +shuttle-axum = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } +tokio = { version = "1.26.0" } diff --git a/axum/hello-world/src/lib.rs b/axum/hello-world/src/lib.rs deleted file mode 100644 index 58137a39..00000000 --- a/axum/hello-world/src/lib.rs +++ /dev/null @@ -1,14 +0,0 @@ -use axum::{routing::get, Router}; -use sync_wrapper::SyncWrapper; - -async fn hello_world() -> &'static str { - "Hello, world!" -} - -#[shuttle_service::main] -async fn axum() -> shuttle_service::ShuttleAxum { - let router = Router::new().route("/hello", get(hello_world)); - let sync_wrapper = SyncWrapper::new(router); - - Ok(sync_wrapper) -} diff --git a/axum/hello-world/src/main.rs b/axum/hello-world/src/main.rs new file mode 100644 index 00000000..01c791f0 --- /dev/null +++ b/axum/hello-world/src/main.rs @@ -0,0 +1,12 @@ +use axum::{routing::get, Router}; + +async fn hello_world() -> &'static str { + "Hello, world!" +} + +#[shuttle_runtime::main] +async fn axum() -> shuttle_axum::ShuttleAxum { + let router = Router::new().route("/hello", get(hello_world)); + + Ok(router.into()) +} diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index c2425b6c..81ee9d0c 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -5,8 +5,9 @@ edition = "2021" publish = false [dependencies] -axum = "0.6.1" +axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-service = { version = "0.11.0", features = ["web-axum"] } -shuttle-static-folder = "0.11.3" -sync_wrapper = "0.1.1" +shuttle-axum = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } +shuttle-static-folder = "0.12.0" +tokio = { version = "1.26.0" } diff --git a/axum/static-files/src/lib.rs b/axum/static-files/src/main.rs similarity index 77% rename from axum/static-files/src/lib.rs rename to axum/static-files/src/main.rs index e48a15ed..65a504e4 100644 --- a/axum/static-files/src/lib.rs +++ b/axum/static-files/src/main.rs @@ -2,23 +2,20 @@ use std::path::PathBuf; use axum::{routing::get, Router}; use axum_extra::routing::SpaRouter; -use sync_wrapper::SyncWrapper; async fn hello_world() -> &'static str { "Hello, world!" } -#[shuttle_service::main] +#[shuttle_runtime::main] async fn axum( // Name your static assets folder by passing `folder = ` to `StaticFolder` // If you don't pass a name, it will default to `static`. #[shuttle_static_folder::StaticFolder(folder = "assets")] static_folder: PathBuf, -) -> shuttle_service::ShuttleAxum { +) -> shuttle_axum::ShuttleAxum { let router = Router::new() .route("/hello", get(hello_world)) .merge(SpaRouter::new("/assets", static_folder).index_file("index.html")); - let sync_wrapper = SyncWrapper::new(router); - - Ok(sync_wrapper) + Ok(router.into()) } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index d9eeaf33..3554b6e9 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -5,8 +5,9 @@ edition = "2021" publish = false [dependencies] -axum = "0.6.1" +axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-service = { version = "0.11.0", features = ["web-axum"] } -shuttle-static-folder = "0.11.3" -sync_wrapper = "0.1.1" +shuttle-axum = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } +shuttle-static-folder = "0.12.0" +tokio = { version = "1.26.0" } diff --git a/axum/static-next-server/src/lib.rs b/axum/static-next-server/src/main.rs similarity index 62% rename from axum/static-next-server/src/lib.rs rename to axum/static-next-server/src/main.rs index fd2d4623..6ce5e935 100644 --- a/axum/static-next-server/src/lib.rs +++ b/axum/static-next-server/src/main.rs @@ -2,16 +2,13 @@ use std::path::PathBuf; use axum::Router; use axum_extra::routing::SpaRouter; -use sync_wrapper::SyncWrapper; -#[shuttle_service::main] +#[shuttle_runtime::main] async fn axum( #[shuttle_static_folder::StaticFolder] static_folder: PathBuf, -) -> shuttle_service::ShuttleAxum { +) -> shuttle_axum::ShuttleAxum { let router = Router::new().merge(SpaRouter::new("/", static_folder).index_file("index.html")); - let sync_wrapper = SyncWrapper::new(router); - - Ok(sync_wrapper) + Ok(router.into()) } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 12f7433c..9aefdd1e 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -3,18 +3,16 @@ name = "websocket" version = "0.1.0" edition = "2021" -[lib] - [dependencies] -axum = { version = "0.6.0", features = ["ws"] } +axum = { version = "0.6.10", features = ["ws"] } chrono = { version = "0.4.23", features = ["serde"] } futures = "0.3.25" hyper = { version = "0.14.23", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-service = { version = "0.11.0", features = ["web-axum"] } -shuttle-static-folder = "0.11.3" -sync_wrapper = "0.1.1" -tokio = { version = "1.22.0", features = ["full"] } +shuttle-axum = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } +shuttle-static-folder = "0.12.0" +tokio = { version = "1.26.0" } tower-http = { version = "0.3.0", features = ["fs"] } diff --git a/axum/websocket/src/lib.rs b/axum/websocket/src/main.rs similarity index 94% rename from axum/websocket/src/lib.rs rename to axum/websocket/src/main.rs index 7d3888b2..913a2aa7 100644 --- a/axum/websocket/src/lib.rs +++ b/axum/websocket/src/main.rs @@ -15,8 +15,7 @@ use futures::{SinkExt, StreamExt}; use hyper::{Client, Uri}; use hyper_tls::HttpsConnector; use serde::Serialize; -use shuttle_service::ShuttleAxum; -use sync_wrapper::SyncWrapper; +use shuttle_axum::ShuttleAxum; use tokio::{ sync::{watch, Mutex}, time::sleep, @@ -39,8 +38,8 @@ struct Response { is_up: bool, } -#[shuttle_service::main] -async fn main(#[shuttle_static_folder::StaticFolder] static_folder: PathBuf) -> ShuttleAxum { +#[shuttle_runtime::main] +async fn axum(#[shuttle_static_folder::StaticFolder] static_folder: PathBuf) -> ShuttleAxum { let (tx, rx) = watch::channel(Message::Text("{}".to_string())); let state = Arc::new(Mutex::new(State { @@ -82,9 +81,7 @@ async fn main(#[shuttle_static_folder::StaticFolder] static_folder: PathBuf) -> .fallback_service(serve_dir) .layer(Extension(state)); - let sync_wrapper = SyncWrapper::new(router); - - Ok(sync_wrapper) + Ok(router.into()) } async fn handle_error(_err: std::io::Error) -> impl IntoResponse { diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml new file mode 100644 index 00000000..1e883021 --- /dev/null +++ b/next/hello-world/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "hello-world" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = [ "cdylib" ] + +[dependencies] +# TODO: bump to 0.9 before merge +shuttle-next = "0.12.0" +tracing = "0.1.37" +futures = "0.3.25" diff --git a/next/hello-world/src/lib.rs b/next/hello-world/src/lib.rs new file mode 100644 index 00000000..af8ad1e0 --- /dev/null +++ b/next/hello-world/src/lib.rs @@ -0,0 +1,33 @@ +shuttle_next::app! { + use futures::TryStreamExt; + use tracing::debug; + use shuttle_next::body::StreamBody; + use shuttle_next::extract::BodyStream; + use shuttle_next::response::{Response, IntoResponse}; + + #[shuttle_next::endpoint(method = get, route = "/hello")] + async fn hello() -> &'static str { + "Hello, World!" + } + + // We can also use tracing/log macros directly: + #[shuttle_next::endpoint(method = get, route = "/goodbye")] + async fn goodbye() -> &'static str { + debug!("goodbye endpoint called"); + "Goodbye, World!" + } + + // We can also extract the http body in our handlers. + // The endpoint below takes the body from the request using the axum `BodyStream` + // extractor, lazily maps its bytes to uppercase and streams it back in our response: + #[shuttle_next::endpoint(method = post, route = "/uppercase")] + async fn uppercase(body: BodyStream) -> impl IntoResponse { + let chunk_stream = body.map_ok(|chunk| { + chunk + .iter() + .map(|byte| byte.to_ascii_uppercase()) + .collect::>() + }); + Response::new(StreamBody::new(chunk_stream)) + } +} diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index c1e21d8f..70315244 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -3,8 +3,8 @@ name = "hello-world" version = "0.1.0" edition = "2021" -[lib] - [dependencies] -poem = "1.3.49" -shuttle-service = { version = "0.11.0", features = ["web-poem"] } +poem = "1.3.55" +shuttle-poem = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } +tokio = { version = "1.26.0" } diff --git a/poem/hello-world/src/lib.rs b/poem/hello-world/src/main.rs similarity index 56% rename from poem/hello-world/src/lib.rs rename to poem/hello-world/src/main.rs index f7630400..95d339c0 100644 --- a/poem/hello-world/src/lib.rs +++ b/poem/hello-world/src/main.rs @@ -1,13 +1,14 @@ use poem::{get, handler, Route}; +use shuttle_poem::ShuttlePoem; #[handler] fn hello_world() -> &'static str { "Hello, world!" } -#[shuttle_service::main] -async fn main() -> shuttle_service::ShuttlePoem { +#[shuttle_runtime::main] +async fn poem() -> ShuttlePoem { let app = Route::new().at("/hello", get(hello_world)); - Ok(app) + Ok(app.into()) } diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 07e14501..626b407a 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -4,9 +4,11 @@ version = "0.1.0" edition = "2021" [dependencies] -mongodb = "2.3.1" -poem = "1.3.49" +mongodb = "2.4.0" +poem = "1.3.55" +shuttle-poem = { version = "0.12.0" } +shuttle-shared-db = { version = "0.12.0", features = ["mongodb"] } +shuttle-runtime = { version = "0.12.0" } serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-service = { version = "0.11.0", features = ["web-poem"] } -shuttle-shared-db = { version = "0.11.0", features = ["mongodb"] } +tokio = { version = "1.26.0" } diff --git a/poem/mongodb/src/lib.rs b/poem/mongodb/src/main.rs similarity index 93% rename from poem/mongodb/src/lib.rs rename to poem/mongodb/src/main.rs index a247a948..82b754cb 100644 --- a/poem/mongodb/src/lib.rs +++ b/poem/mongodb/src/main.rs @@ -10,6 +10,7 @@ use poem::{ EndpointExt, FromRequest, Request, RequestBody, Result, Route, }; use serde::{Deserialize, Serialize}; +use shuttle_poem::ShuttlePoem; struct ObjectIdGuard(ObjectId); @@ -53,10 +54,10 @@ async fn add(Json(todo): Json, collection: Data<&Collection>) -> Res .to_string()) } -#[shuttle_service::main] -async fn main( +#[shuttle_runtime::main] +async fn poem( #[shuttle_shared_db::MongoDb] db: Database, -) -> shuttle_service::ShuttlePoem { +) -> ShuttlePoem { let collection = db.collection::("todos"); let app = Route::new() @@ -64,7 +65,7 @@ async fn main( .at("/todo/:id", get(retrieve)) .with(AddData::new(collection)); - Ok(app) + Ok(app.into()) } #[derive(Debug, Serialize, Deserialize)] diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index d54a82b4..22c477b4 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -3,11 +3,11 @@ name = "postgres" version = "0.1.0" edition = "2021" -[lib] - [dependencies] -poem = "1.3.49" +poem = "1.3.55" serde = "1.0.148" -shuttle-service = { version = "0.11.0", features = ["web-poem"] } -shuttle-shared-db = { version = "0.11.0", features = ["postgres"] } +shuttle-poem = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } +shuttle-shared-db = { version = "0.12.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } +tokio = { version = "1.26.0" } diff --git a/poem/postgres/src/lib.rs b/poem/postgres/src/main.rs similarity index 88% rename from poem/postgres/src/lib.rs rename to poem/postgres/src/main.rs index d25787d9..bd4986b4 100644 --- a/poem/postgres/src/lib.rs +++ b/poem/postgres/src/main.rs @@ -7,7 +7,8 @@ use poem::{ EndpointExt, Result, Route, }; use serde::{Deserialize, Serialize}; -use shuttle_service::error::CustomError; +use shuttle_runtime::CustomError; +use shuttle_poem::ShuttlePoem; use sqlx::{Executor, FromRow, PgPool}; #[handler] @@ -32,10 +33,10 @@ async fn add(Json(data): Json, state: Data<&PgPool>) -> Result shuttle_service::ShuttlePoem { +) -> ShuttlePoem { pool.execute(include_str!("../schema.sql")) .await .map_err(CustomError::new)?; @@ -45,7 +46,7 @@ async fn main( .at("/todo/:id", get(retrieve)) .with(AddData::new(pool)); - Ok(app) + Ok(app.into()) } #[derive(Deserialize)] diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 334fea1e..3c714c69 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -4,11 +4,11 @@ version = "0.1.0" edition = "2021" publish = false -[lib] - [dependencies] -shuttle-service = { version = "0.11.0", features = ["bot-poise"] } anyhow = "1.0.68" -shuttle-secrets = "0.11.0" -tracing = "0.1.37" poise = "0.5.2" +shuttle-poise = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } +shuttle-secrets = "0.12.0" +tracing = "0.1.37" +tokio = { version = "1.26.0" } diff --git a/poise/hello-world/src/lib.rs b/poise/hello-world/src/main.rs similarity index 90% rename from poise/hello-world/src/lib.rs rename to poise/hello-world/src/main.rs index 7a0ad310..ef3a302a 100644 --- a/poise/hello-world/src/lib.rs +++ b/poise/hello-world/src/main.rs @@ -1,7 +1,7 @@ use anyhow::Context as _; use poise::serenity_prelude as serenity; use shuttle_secrets::SecretStore; -use shuttle_service::ShuttlePoise; +use shuttle_poise::ShuttlePoise; struct Data {} // User data, which is stored and accessible in all command invocations type Error = Box; @@ -14,7 +14,7 @@ async fn hello(ctx: Context<'_>) -> Result<(), Error> { Ok(()) } -#[shuttle_service::main] +#[shuttle_runtime::main] async fn poise(#[shuttle_secrets::Secrets] secret_store: SecretStore) -> ShuttlePoise { // Get the discord token set in `Secrets.toml` let discord_token = secret_store @@ -36,7 +36,7 @@ async fn poise(#[shuttle_secrets::Secrets] secret_store: SecretStore) -> Shuttle }) .build() .await - .map_err(shuttle_service::error::CustomError::new)?; + .map_err(shuttle_runtime::CustomError::new)?; - Ok(framework) + Ok(framework.into()) } diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index 3719877d..fd8e72b2 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -3,12 +3,12 @@ name = "authentication" version = "0.1.0" edition = "2021" -[lib] - [dependencies] chrono = "0.4.23" jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-service = { version = "0.11.0", features = ["web-rocket"] } +shuttle-rocket = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } +tokio = { version = "1.26.0" } diff --git a/rocket/authentication/src/lib.rs b/rocket/authentication/src/main.rs similarity index 94% rename from rocket/authentication/src/lib.rs rename to rocket/authentication/src/main.rs index 5fb1b103..5f6651c8 100644 --- a/rocket/authentication/src/lib.rs +++ b/rocket/authentication/src/main.rs @@ -69,9 +69,9 @@ fn login(login: Json) -> Result, Custom shuttle_service::ShuttleRocket { +#[shuttle_runtime::main] +async fn rocket() -> shuttle_rocket::ShuttleRocket { let rocket = rocket::build().mount("/", routes![public, private, login]); - Ok(rocket) + Ok(rocket.into()) } diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 4cc9ffc1..ea2d213b 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -3,8 +3,8 @@ name = "hello-world" version = "0.1.0" edition = "2021" -[lib] - [dependencies] rocket = "0.5.0-rc.2" -shuttle-service = { version = "0.11.0", features = ["web-rocket"] } +shuttle-rocket = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } +tokio = { version = "1.26.0" } diff --git a/rocket/hello-world/src/lib.rs b/rocket/hello-world/src/main.rs similarity index 62% rename from rocket/hello-world/src/lib.rs rename to rocket/hello-world/src/main.rs index cb788dea..847d04aa 100644 --- a/rocket/hello-world/src/lib.rs +++ b/rocket/hello-world/src/main.rs @@ -6,9 +6,9 @@ fn index() -> &'static str { "Hello, world!" } -#[shuttle_service::main] -async fn rocket() -> shuttle_service::ShuttleRocket { +#[shuttle_runtime::main] +async fn rocket() -> shuttle_rocket::ShuttleRocket { let rocket = rocket::build().mount("/hello", routes![index]); - Ok(rocket) + Ok(rocket.into()) } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 268a7cdb..45055856 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -3,10 +3,10 @@ name = "persist" version = "0.1.0" edition = "2021" -[lib] - [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.11.0" -shuttle-service = { version = "0.11.0", features = ["web-rocket"] } +shuttle-persist = "0.12.0" +shuttle-rocket = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } +tokio = { version = "1.26.0" } diff --git a/rocket/persist/src/lib.rs b/rocket/persist/src/main.rs similarity index 94% rename from rocket/persist/src/lib.rs rename to rocket/persist/src/main.rs index f85bcd42..2e7d2a7d 100644 --- a/rocket/persist/src/lib.rs +++ b/rocket/persist/src/main.rs @@ -50,14 +50,14 @@ async fn retrieve( Ok(Json(weather)) } -#[shuttle_service::main] +#[shuttle_runtime::main] async fn rocket( #[shuttle_persist::Persist] persist: PersistInstance, -) -> shuttle_service::ShuttleRocket { +) -> shuttle_rocket::ShuttleRocket { let state = MyState { persist }; let rocket = rocket::build() .mount("/", routes![retrieve, add]) .manage(state); - Ok(rocket) + Ok(rocket.into()) } diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 2d8d6db9..5d0b7bde 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -3,11 +3,11 @@ name = "postgres" version = "0.1.0" edition = "2021" -[lib] - [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-service = { version = "0.11.0", features = ["web-rocket"] } -shuttle-shared-db = { version = "0.11.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.12.0", features = ["postgres"] } +shuttle-rocket = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } +tokio = { version = "1.26.0" } diff --git a/rocket/postgres/src/lib.rs b/rocket/postgres/src/main.rs similarity index 92% rename from rocket/postgres/src/lib.rs rename to rocket/postgres/src/main.rs index dd036fe2..c7a3553b 100644 --- a/rocket/postgres/src/lib.rs +++ b/rocket/postgres/src/main.rs @@ -5,7 +5,7 @@ use rocket::response::status::BadRequest; use rocket::serde::json::Json; use rocket::State; use serde::{Deserialize, Serialize}; -use shuttle_service::error::CustomError; +use shuttle_runtime::CustomError; use sqlx::{Executor, FromRow, PgPool}; #[get("/")] @@ -37,8 +37,8 @@ struct MyState { pool: PgPool, } -#[shuttle_service::main] -async fn rocket(#[shuttle_shared_db::Postgres] pool: PgPool) -> shuttle_service::ShuttleRocket { +#[shuttle_runtime::main] +async fn rocket(#[shuttle_shared_db::Postgres] pool: PgPool) -> shuttle_rocket::ShuttleRocket { pool.execute(include_str!("../schema.sql")) .await .map_err(CustomError::new)?; @@ -48,7 +48,7 @@ async fn rocket(#[shuttle_shared_db::Postgres] pool: PgPool) -> shuttle_service: .mount("/todo", routes![retrieve, add]) .manage(state); - Ok(rocket) + Ok(rocket.into()) } #[derive(Deserialize)] diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index efa8f77f..4390b7b7 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -3,10 +3,10 @@ name = "secrets" version = "0.1.0" edition = "2021" -[lib] - [dependencies] anyhow = "1.0.66" -rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-secrets = "0.11.0" -shuttle-service = { version = "0.11.0", features = ["web-rocket"] } +rocket = "0.5.0-rc.2" +shuttle-rocket = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } +shuttle-secrets = "0.12.0" +tokio = { version = "1.26.0" } diff --git a/rocket/secrets/src/lib.rs b/rocket/secrets/src/main.rs similarity index 89% rename from rocket/secrets/src/lib.rs rename to rocket/secrets/src/main.rs index 65755319..879d38ce 100644 --- a/rocket/secrets/src/lib.rs +++ b/rocket/secrets/src/main.rs @@ -15,10 +15,10 @@ struct MyState { secret: String, } -#[shuttle_service::main] +#[shuttle_runtime::main] async fn rocket( #[shuttle_secrets::Secrets] secret_store: SecretStore, -) -> shuttle_service::ShuttleRocket { +) -> shuttle_rocket::ShuttleRocket { // get secret defined in `Secrets.toml` file. let secret = if let Some(secret) = secret_store.get("MY_API_KEY") { secret @@ -29,5 +29,5 @@ async fn rocket( let state = MyState { secret }; let rocket = rocket::build().mount("/", routes![secret]).manage(state); - Ok(rocket) + Ok(rocket.into()) } diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 9251ca98..2acdd1e6 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -3,13 +3,13 @@ name = "url-shortener" version = "0.1.0" edition = "2021" -[lib] - [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } +shuttle-rocket = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } serde = "1.0.148" -shuttle-service = { version = "0.11.0", features = ["web-rocket"] } -shuttle-shared-db = { version = "0.11.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.12.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } +tokio = { version = "1.26.0" } url = "2.3.1" diff --git a/rocket/url-shortener/src/lib.rs b/rocket/url-shortener/src/main.rs similarity index 94% rename from rocket/url-shortener/src/lib.rs rename to rocket/url-shortener/src/main.rs index fa0f17ba..73cc139f 100644 --- a/rocket/url-shortener/src/lib.rs +++ b/rocket/url-shortener/src/main.rs @@ -7,7 +7,7 @@ use rocket::{ routes, State, }; use serde::Serialize; -use shuttle_service::{error::CustomError, ShuttleRocket}; +use shuttle_runtime::CustomError; use sqlx::migrate::Migrator; use sqlx::{FromRow, PgPool}; use url::Url; @@ -70,8 +70,8 @@ async fn shorten(url: String, state: &State) -> Result ShuttleRocket { +#[shuttle_runtime::main] +async fn rocket(#[shuttle_shared_db::Postgres] pool: PgPool) -> shuttle_rocket::ShuttleRocket { MIGRATOR.run(&pool).await.map_err(CustomError::new)?; let state = AppState { pool }; @@ -79,5 +79,5 @@ async fn rocket(#[shuttle_shared_db::Postgres] pool: PgPool) -> ShuttleRocket { .mount("/", routes![redirect, shorten]) .manage(state); - Ok(rocket) + Ok(rocket.into()) } diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 3f1e8a38..00c51532 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -3,8 +3,9 @@ name = "hello-world" version = "0.1.0" edition = "2021" -[lib] - [dependencies] salvo = "0.37.5" -shuttle-service = { version = "0.11.0", features = ["web-salvo"] } +shuttle-salvo = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } +tokio = { version = "1.26.0" } + diff --git a/salvo/hello-world/src/lib.rs b/salvo/hello-world/src/main.rs similarity index 66% rename from salvo/hello-world/src/lib.rs rename to salvo/hello-world/src/main.rs index d5ce829d..39ed4ff7 100644 --- a/salvo/hello-world/src/lib.rs +++ b/salvo/hello-world/src/main.rs @@ -5,9 +5,9 @@ async fn hello_world(res: &mut Response) { res.render(Text::Plain("Hello, world!")); } -#[shuttle_service::main] -async fn salvo() -> shuttle_service::ShuttleSalvo { +#[shuttle_runtime::main] +async fn salvo() -> shuttle_salvo::ShuttleSalvo { let router = Router::with_path("hello").get(hello_world); - Ok(router) + Ok(router.into()) } diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index e60312c7..0a5927d6 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -3,11 +3,11 @@ name = "hello-world" version = "0.1.0" edition = "2021" -[lib] - [dependencies] anyhow = "1.0.66" +shuttle-serenity = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.11.0" -shuttle-service = { version = "0.11.0", features = ["bot-serenity"] } +shuttle-secrets = "0.12.0" +tokio = { version = "1.26.0" } tracing = "0.1.37" diff --git a/serenity/hello-world/src/lib.rs b/serenity/hello-world/src/main.rs similarity index 93% rename from serenity/hello-world/src/lib.rs rename to serenity/hello-world/src/main.rs index 9c3716c5..2b01b6a8 100644 --- a/serenity/hello-world/src/lib.rs +++ b/serenity/hello-world/src/main.rs @@ -23,10 +23,10 @@ impl EventHandler for Bot { } } -#[shuttle_service::main] +#[shuttle_runtime::main] async fn serenity( #[shuttle_secrets::Secrets] secret_store: SecretStore, -) -> shuttle_service::ShuttleSerenity { +) -> shuttle_serenity::ShuttleSerenity { // Get the discord token set in `Secrets.toml` let token = if let Some(token) = secret_store.get("DISCORD_TOKEN") { token @@ -42,5 +42,5 @@ async fn serenity( .await .expect("Err creating client"); - Ok(client) + Ok(client.into()) } diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index f61c1a38..9c66c839 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -3,14 +3,14 @@ name = "serenity-postgres" version = "0.1.0" edition = "2021" -[lib] - [dependencies] anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.11.0" -shuttle-service = { version = "0.11.0", features = ["bot-serenity"] } -shuttle-shared-db = { version = "0.11.0", features = ["postgres"] } +shuttle-secrets = "0.12.0" +shuttle-serenity = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } +shuttle-shared-db = { version = "0.12.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } +tokio = { version = "1.26.0" } tracing = "0.1.37" diff --git a/serenity/postgres/src/lib.rs b/serenity/postgres/src/main.rs similarity index 98% rename from serenity/postgres/src/lib.rs rename to serenity/postgres/src/main.rs index 8815dcdb..c878fb39 100644 --- a/serenity/postgres/src/lib.rs +++ b/serenity/postgres/src/main.rs @@ -123,11 +123,11 @@ impl EventHandler for Bot { } } -#[shuttle_service::main] +#[shuttle_runtime::main] async fn serenity( #[shuttle_shared_db::Postgres] pool: PgPool, #[shuttle_secrets::Secrets] secret_store: SecretStore, -) -> shuttle_service::ShuttleSerenity { +) -> shuttle_serenity::ShuttleSerenity { // Get the discord token set in `Secrets.toml` let token = secret_store .get("DISCORD_TOKEN") @@ -151,5 +151,5 @@ async fn serenity( .await .expect("Err creating client"); - Ok(client) + Ok(client.into()) } diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index d6a211da..d0d5bee8 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -3,8 +3,8 @@ name = "hello-world" version = "0.1.0" edition = "2021" -[lib] - [dependencies] -shuttle-service = { version = "0.11.0", features = ["web-thruster"] } +shuttle-thruster = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } thruster = { version = "1.3.0", features = ["hyper_server"] } +tokio = { version = "1.26.0" } diff --git a/thruster/hello-world/src/lib.rs b/thruster/hello-world/src/main.rs similarity index 72% rename from thruster/hello-world/src/lib.rs rename to thruster/hello-world/src/main.rs index 1e6de6da..97d95f40 100644 --- a/thruster/hello-world/src/lib.rs +++ b/thruster/hello-world/src/main.rs @@ -9,9 +9,11 @@ async fn hello(mut context: Ctx, _next: MiddlewareNext) -> MiddlewareResult Ok(context) } -#[shuttle_service::main] -async fn thruster() -> shuttle_service::ShuttleThruster> { - Ok(HyperServer::new( +#[shuttle_runtime::main] +async fn thruster() -> shuttle_thruster::ShuttleThruster> { + let server = HyperServer::new( App::::create(generate_context, ()).get("/hello", m![hello]), - )) + ); + + Ok(server.into()) } diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index e8ca94b4..e02e6c62 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -3,15 +3,13 @@ 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.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.11.0", features = ["postgres"] } -shuttle-service = { version = "0.11.0", features = ["web-thruster"] } +shuttle-aws-rds = { version = "0.12.0", features = ["postgres"] } +shuttle-thruster = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } +tokio = { version = "1.26.0" } diff --git a/thruster/postgres/src/lib.rs b/thruster/postgres/src/main.rs similarity index 93% rename from thruster/postgres/src/lib.rs rename to thruster/postgres/src/main.rs index 275428b2..73981e64 100644 --- a/thruster/postgres/src/lib.rs +++ b/thruster/postgres/src/main.rs @@ -1,5 +1,5 @@ use serde::{Deserialize, Serialize}; -use shuttle_service::error::CustomError; +use shuttle_runtime::CustomError; use sqlx::{Executor, FromRow, PgPool}; use thruster::{ context::{ @@ -96,17 +96,19 @@ async fn add(mut context: Ctx, _next: MiddlewareNext) -> MiddlewareResult shuttle_service::ShuttleThruster> { +) -> shuttle_thruster::ShuttleThruster> { pool.execute(include_str!("../schema.sql")) .await .map_err(CustomError::new)?; - Ok(HyperServer::new( + let server = HyperServer::new( App::::create(generate_context, ServerConfig { pool }) .post("/todos", m![add]) .get("/todos/:id", m![retrieve]), - )) + ); + + Ok(server.into()) } diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index a55bf8c1..15cfd145 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -3,8 +3,8 @@ name = "hello-world" version = "0.1.0" edition = "2021" -[lib] - [dependencies] -shuttle-service = { version = "0.11.0", features = ["web-tide"] } +shuttle-tide = { version = "0.12.0" } +shuttle-runtime = { version = "0.12.0" } +tokio = { version = "1.26.0" } tide = "0.16.0" diff --git a/tide/hello-world/src/lib.rs b/tide/hello-world/src/main.rs similarity index 60% rename from tide/hello-world/src/lib.rs rename to tide/hello-world/src/main.rs index db95792b..cab1c3a9 100644 --- a/tide/hello-world/src/lib.rs +++ b/tide/hello-world/src/main.rs @@ -1,9 +1,9 @@ -#[shuttle_service::main] -async fn tide() -> shuttle_service::ShuttleTide<()> { +#[shuttle_runtime::main] +async fn tide() -> shuttle_tide::ShuttleTide<()> { let mut app = tide::new(); app.with(tide::log::LogMiddleware::new()); app.at("/hello").get(|_| async { Ok("Hello, world!") }); - Ok(app) + Ok(app.into()) } diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index d1fbabcb..f3bd2c9f 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -3,13 +3,11 @@ 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] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.11.0", features = ["postgres"] } -shuttle-service = { version = "0.11.0", features = ["web-tide"] } +shuttle-aws-rds = { version = "0.12.0", features = ["postgres"] } +shuttle-runtime = { version = "0.12.0" } +shuttle-tide = { version = "0.12.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } +tokio = { version = "1.26.0" } tide = "0.16.0" diff --git a/tide/postgres/src/lib.rs b/tide/postgres/src/main.rs similarity index 92% rename from tide/postgres/src/lib.rs rename to tide/postgres/src/main.rs index 0ad8dd16..f405646b 100644 --- a/tide/postgres/src/lib.rs +++ b/tide/postgres/src/main.rs @@ -1,5 +1,6 @@ use serde::{Deserialize, Serialize}; -use shuttle_service::{error::CustomError, ShuttleTide}; +use shuttle_runtime::{CustomError}; +use shuttle_tide::ShuttleTide; use sqlx::{Executor, FromRow, PgPool}; use tide::{Body, Request}; @@ -28,7 +29,7 @@ struct MyState { pool: PgPool, } -#[shuttle_service::main] +#[shuttle_runtime::main] async fn tide(#[shuttle_aws_rds::Postgres] pool: PgPool) -> ShuttleTide { pool.execute(include_str!("../schema.sql")) .await @@ -41,7 +42,7 @@ async fn tide(#[shuttle_aws_rds::Postgres] pool: PgPool) -> ShuttleTide app.at("/todo").post(add); app.at("/todo/:id").get(retrieve); - Ok(app) + Ok(app.into()) } #[derive(Deserialize)] diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 00a0820a..ac8022ec 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -3,9 +3,9 @@ name = "hello-world" version = "0.1.0" edition = "2021" -[lib] - [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-service = { version = "0.11.0", features = ["web-tower"] } +shuttle-runtime = { version = "0.12.0" } +shuttle-tower = { version = "0.12.0" } tower = { version = "0.4.13", features = ["full"] } +tokio = { version = "1.26.0" } diff --git a/tower/hello-world/src/lib.rs b/tower/hello-world/src/main.rs similarity index 86% rename from tower/hello-world/src/lib.rs rename to tower/hello-world/src/main.rs index 20a49545..0980d5e6 100644 --- a/tower/hello-world/src/lib.rs +++ b/tower/hello-world/src/main.rs @@ -28,7 +28,9 @@ impl tower::Service> for HelloWorld { } } -#[shuttle_service::main] -async fn tower() -> Result { - Ok(HelloWorld) +#[shuttle_runtime::main] +async fn tower() -> shuttle_tower::ShuttleTower { + let service = HelloWorld; + + Ok(service.into()) } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 33946168..2aaeb992 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -3,8 +3,8 @@ name = "hello-world" version = "0.1.0" edition = "2021" -[lib] - [dependencies] -shuttle-service = { version = "0.11.0", features = ["web-warp"] } +shuttle-runtime = { version = "0.12.0" } +shuttle-warp = { version = "0.12.0" } +tokio = { version = "1.26.0" } warp = "0.3.3" diff --git a/warp/hello-world/src/lib.rs b/warp/hello-world/src/lib.rs deleted file mode 100644 index 9b253098..00000000 --- a/warp/hello-world/src/lib.rs +++ /dev/null @@ -1,8 +0,0 @@ -use warp::Filter; -use warp::Reply; - -#[shuttle_service::main] -async fn warp() -> shuttle_service::ShuttleWarp<(impl Reply,)> { - let route = warp::any().map(|| "Hello, World!"); - Ok(route.boxed()) -} diff --git a/warp/hello-world/src/main.rs b/warp/hello-world/src/main.rs new file mode 100644 index 00000000..277226f2 --- /dev/null +++ b/warp/hello-world/src/main.rs @@ -0,0 +1,8 @@ +use warp::Filter; +use warp::Reply; + +#[shuttle_runtime::main] +async fn warp() -> shuttle_warp::ShuttleWarp<(impl Reply,)> { + let route = warp::any().map(|| "Hello, World!"); + Ok(route.boxed().into()) +} From 53b6911d36fd1d8881767e976534b3f6340f49a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Mon, 27 Mar 2023 09:41:19 +0000 Subject: [PATCH 028/239] chore: v0.13.0 (#33) --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 6 +++--- axum/hello-world/Cargo.toml | 4 ++-- axum/static-files/Cargo.toml | 6 +++--- axum/static-next-server/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 6 +++--- next/hello-world/Cargo.toml | 2 +- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 27 files changed, 70 insertions(+), 70 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index cae47b6c..9f6df577 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } +shuttle-actix-web = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } tokio = { version = "1.26.0" } diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 6b9c3aa4..ac9216bc 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } +shuttle-actix-web = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } serde = "1.0.148" -shuttle-shared-db = { version = "0.12.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.13.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 9427f832..45aa6bc6 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,8 +13,8 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } -shuttle-static-folder = "0.12.0" +shuttle-actix-web = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } +shuttle-static-folder = "0.13.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 57143b3a..a70d575c 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } +shuttle-axum = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } tokio = { version = "1.26.0" } diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 81ee9d0c..984a5226 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } -shuttle-static-folder = "0.12.0" +shuttle-axum = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } +shuttle-static-folder = "0.13.0" tokio = { version = "1.26.0" } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 3554b6e9..51e752f1 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } -shuttle-static-folder = "0.12.0" +shuttle-axum = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } +shuttle-static-folder = "0.13.0" tokio = { version = "1.26.0" } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 9aefdd1e..6f9c535b 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,8 +11,8 @@ hyper = { version = "0.14.23", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-axum = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } -shuttle-static-folder = "0.12.0" +shuttle-axum = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } +shuttle-static-folder = "0.13.0" tokio = { version = "1.26.0" } tower-http = { version = "0.3.0", features = ["fs"] } diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index 1e883021..d300b0c0 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -8,6 +8,6 @@ crate-type = [ "cdylib" ] [dependencies] # TODO: bump to 0.9 before merge -shuttle-next = "0.12.0" +shuttle-next = "0.13.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 70315244..d62c2014 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } +shuttle-poem = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } tokio = { version = "1.26.0" } diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 626b407a..ff5df19e 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = { version = "0.12.0" } -shuttle-shared-db = { version = "0.12.0", features = ["mongodb"] } -shuttle-runtime = { version = "0.12.0" } +shuttle-poem = { version = "0.13.0" } +shuttle-shared-db = { version = "0.13.0", features = ["mongodb"] } +shuttle-runtime = { version = "0.13.0" } serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = { version = "1.26.0" } diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 22c477b4..ab6afb4d 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } -shuttle-shared-db = { version = "0.12.0", features = ["postgres"] } +shuttle-poem = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } +shuttle-shared-db = { version = "0.13.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 3c714c69..068e2e60 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } -shuttle-secrets = "0.12.0" +shuttle-poise = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } +shuttle-secrets = "0.13.0" tracing = "0.1.37" tokio = { version = "1.26.0" } diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index fd8e72b2..557758ad 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } +shuttle-rocket = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } tokio = { version = "1.26.0" } diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index ea2d213b..874febc7 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } +shuttle-rocket = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } tokio = { version = "1.26.0" } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 45055856..07a9fcfe 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.12.0" -shuttle-rocket = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } +shuttle-persist = "0.13.0" +shuttle-rocket = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } tokio = { version = "1.26.0" } diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 5d0b7bde..1ba95a85 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.12.0", features = ["postgres"] } -shuttle-rocket = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } +shuttle-shared-db = { version = "0.13.0", features = ["postgres"] } +shuttle-rocket = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 4390b7b7..af2d8f43 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } -shuttle-secrets = "0.12.0" +shuttle-rocket = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } +shuttle-secrets = "0.13.0" tokio = { version = "1.26.0" } diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 2acdd1e6..5f20e124 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } +shuttle-rocket = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } serde = "1.0.148" -shuttle-shared-db = { version = "0.12.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.13.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } url = "2.3.1" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 00c51532..68eac302 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.37.5" -shuttle-salvo = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } +shuttle-salvo = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } tokio = { version = "1.26.0" } diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 0a5927d6..91116e69 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } +shuttle-serenity = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.12.0" +shuttle-secrets = "0.13.0" tokio = { version = "1.26.0" } tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 9c66c839..ed47ae03 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.12.0" -shuttle-serenity = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } -shuttle-shared-db = { version = "0.12.0", features = ["postgres"] } +shuttle-secrets = "0.13.0" +shuttle-serenity = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } +shuttle-shared-db = { version = "0.13.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index d0d5bee8..c8a2113c 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } +shuttle-thruster = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = { version = "1.26.0" } diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index e02e6c62..b2b2b6ac 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.12.0", features = ["postgres"] } -shuttle-thruster = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } +shuttle-aws-rds = { version = "0.13.0", features = ["postgres"] } +shuttle-thruster = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = { version = "1.26.0" } diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 15cfd145..65d544f1 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = { version = "0.12.0" } -shuttle-runtime = { version = "0.12.0" } +shuttle-tide = { version = "0.13.0" } +shuttle-runtime = { version = "0.13.0" } tokio = { version = "1.26.0" } tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index f3bd2c9f..bbd02385 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.12.0", features = ["postgres"] } -shuttle-runtime = { version = "0.12.0" } -shuttle-tide = { version = "0.12.0" } +shuttle-aws-rds = { version = "0.13.0", features = ["postgres"] } +shuttle-runtime = { version = "0.13.0" } +shuttle-tide = { version = "0.13.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index ac8022ec..53f4b9bc 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = { version = "0.12.0" } -shuttle-tower = { version = "0.12.0" } +shuttle-runtime = { version = "0.13.0" } +shuttle-tower = { version = "0.13.0" } tower = { version = "0.4.13", features = ["full"] } tokio = { version = "1.26.0" } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 2aaeb992..cec8baa6 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = { version = "0.12.0" } -shuttle-warp = { version = "0.12.0" } +shuttle-runtime = { version = "0.13.0" } +shuttle-warp = { version = "0.13.0" } tokio = { version = "1.26.0" } warp = "0.3.3" From 2642519c13ba0d8fd23226604629257a55614f9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Tue, 28 Mar 2023 08:06:58 +0000 Subject: [PATCH 029/239] chore: bump static folder to 0.13.1 (#34) --- actix-web/websocket-actorless/Cargo.toml | 2 +- axum/static-files/Cargo.toml | 2 +- axum/static-next-server/Cargo.toml | 2 +- axum/websocket/Cargo.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 45aa6bc6..7f708340 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -15,6 +15,6 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" shuttle-actix-web = { version = "0.13.0" } shuttle-runtime = { version = "0.13.0" } -shuttle-static-folder = "0.13.0" +shuttle-static-folder = "0.13.1" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 984a5226..9e9010e9 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -9,5 +9,5 @@ axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } shuttle-axum = { version = "0.13.0" } shuttle-runtime = { version = "0.13.0" } -shuttle-static-folder = "0.13.0" +shuttle-static-folder = "0.13.1" tokio = { version = "1.26.0" } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 51e752f1..bcca4a95 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -9,5 +9,5 @@ axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } shuttle-axum = { version = "0.13.0" } shuttle-runtime = { version = "0.13.0" } -shuttle-static-folder = "0.13.0" +shuttle-static-folder = "0.13.1" tokio = { version = "1.26.0" } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 6f9c535b..dc7b9b4a 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -13,6 +13,6 @@ serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" shuttle-axum = { version = "0.13.0" } shuttle-runtime = { version = "0.13.0" } -shuttle-static-folder = "0.13.0" +shuttle-static-folder = "0.13.1" tokio = { version = "1.26.0" } tower-http = { version = "0.3.0", features = ["fs"] } From da693ce91f4b9c1648aec65fc2ebf65c8e10b236 Mon Sep 17 00:00:00 2001 From: Pieter Date: Wed, 12 Apr 2023 09:41:15 +0200 Subject: [PATCH 030/239] feat: workspace example (#35) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: workspace example * fix: bump shuttle versions * chore: v0.14.0 --------- Co-authored-by: Oddbjørn Grødem <29732646+oddgrd@users.noreply.github.com> --- rocket/workspace/Cargo.toml | 6 ++++++ rocket/workspace/hello-world/Cargo.toml | 11 +++++++++++ rocket/workspace/hello-world/src/main.rs | 14 ++++++++++++++ rocket/workspace/shared/Cargo.toml | 8 ++++++++ rocket/workspace/shared/src/lib.rs | 3 +++ 5 files changed, 42 insertions(+) create mode 100644 rocket/workspace/Cargo.toml create mode 100644 rocket/workspace/hello-world/Cargo.toml create mode 100644 rocket/workspace/hello-world/src/main.rs create mode 100644 rocket/workspace/shared/Cargo.toml create mode 100644 rocket/workspace/shared/src/lib.rs diff --git a/rocket/workspace/Cargo.toml b/rocket/workspace/Cargo.toml new file mode 100644 index 00000000..9bca4b63 --- /dev/null +++ b/rocket/workspace/Cargo.toml @@ -0,0 +1,6 @@ +[workspace] + +members = [ + "hello-world", + "shared", +] diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml new file mode 100644 index 00000000..82c7e45c --- /dev/null +++ b/rocket/workspace/hello-world/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "hello-world" +version = "0.1.0" +edition = "2021" + +[dependencies] +rocket = "0.5.0-rc.2" +shared = { path = "../shared", version = "0.1.0" } +shuttle-rocket = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } +tokio = { version = "1.26.0" } diff --git a/rocket/workspace/hello-world/src/main.rs b/rocket/workspace/hello-world/src/main.rs new file mode 100644 index 00000000..61399340 --- /dev/null +++ b/rocket/workspace/hello-world/src/main.rs @@ -0,0 +1,14 @@ +#[macro_use] +extern crate rocket; + +#[get("/")] +fn index() -> &'static str { + shared::hello() +} + +#[shuttle_runtime::main] +async fn rocket() -> shuttle_rocket::ShuttleRocket { + let rocket = rocket::build().mount("/hello", routes![index]); + + Ok(rocket.into()) +} diff --git a/rocket/workspace/shared/Cargo.toml b/rocket/workspace/shared/Cargo.toml new file mode 100644 index 00000000..886aebd6 --- /dev/null +++ b/rocket/workspace/shared/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "shared" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/rocket/workspace/shared/src/lib.rs b/rocket/workspace/shared/src/lib.rs new file mode 100644 index 00000000..c46c675b --- /dev/null +++ b/rocket/workspace/shared/src/lib.rs @@ -0,0 +1,3 @@ +pub fn hello() -> &'static str { + "Hello, shared" +} From 5d7268bc67f7a488eb8492303dbdd017b05b112d Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 12 Apr 2023 09:41:42 +0200 Subject: [PATCH 031/239] Update project cmd (#36) --- README.md | 8 ++++---- rocket/authentication/README.md | 18 +++++++++--------- rocket/persist/README.md | 8 ++++---- rocket/url-shortener/README.md | 12 ++++++------ 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index a01ff228..c5dcc901 100644 --- a/README.md +++ b/README.md @@ -7,19 +7,19 @@ Some example apps to show what you can do with shuttle. To deploy the examples, check out the repository locally ```bash -$ git clone https://github.com/shuttle-hq/examples.git +git clone https://github.com/shuttle-hq/examples.git ``` navigate to an example root folder ```bash -$ cd axum/hello-world +cd axum/hello-world ``` Pick a project name that is something unique - in shuttle, projects are globally unique. Then run ```bash -$ cargo shuttle project new --name=$PROJECT_NAME -$ cargo shuttle deploy --name=$PROJECT_NAME +cargo shuttle project start --name=$PROJECT_NAME +cargo shuttle deploy --name=$PROJECT_NAME ``` diff --git a/rocket/authentication/README.md b/rocket/authentication/README.md index b4f4f43f..7b077d30 100644 --- a/rocket/authentication/README.md +++ b/rocket/authentication/README.md @@ -1,6 +1,6 @@ # Issue and verify JWT for authentication This example shows how to use [Rocket request guards](https://rocket.rs/v0.5-rc/guide/requests/#request-guards) for authentication with [JSON Web Tokens](https://jwt.io/) (JWT for short). -The idea is that all requests authenticate first at https://authentication-rocket-app.shuttleapp.rs/login to get a JWT. +The idea is that all requests authenticate first at to get a JWT. Then the JWT is sent with all requests requiring authentication using the HTTP header `Authorization: Bearer `. This example uses the [`jsonwebtoken`](https://github.com/Keats/jsonwebtoken) which supports symmetric and asymmetric secret encoding, built-in validations, and most JWT algorithms. @@ -12,8 +12,8 @@ This example has two files to register routes and handle JWT claims. ### src/main.rs Three Rocker routes are registered in this file: 1. `/public`: a route that can be called without needing any authentication. -1. `/login`: a route for posting a JSON object with a username and password to get a JWT. -1. `/private`: a route that can only be accessed with a valid JWT. +2. `/login`: a route for posting a JSON object with a username and password to get a JWT. +3. `/private`: a route that can only be accessed with a valid JWT. ### src/claims.rs The bulk of this example is in this file. Most of the code can be transferred to other frameworks except for the `FromRequest` implementation, which is Rocket specific. @@ -24,8 +24,8 @@ And a `Claims` object can also be converted to a token using `to_token()`. After logging into shuttle, use the following command to deploy this example: ```sh -$ cargo shuttle project new -$ cargo shuttle deploy +cargo shuttle project start +cargo shuttle deploy ``` Now make a note of the `Host` for the deploy to use in the examples below. Or just use `authentication-rocket-app.shuttleapp.rs` as the host below. @@ -34,26 +34,26 @@ Now make a note of the `Host` for the deploy to use in the examples below. Or ju First, we should be able to access the public endpoint without any authentication using: ```sh -$ curl https:///public +curl https:///public ``` But trying to access the private endpoint will fail with a 403 forbidden: ```sh -$ curl https:///private +curl https:///private ``` So let's get a JWT from the login route first: ```sh -$ curl --request POST --data '{"username": "username", "password": "password"}' https:///login +curl --request POST --data '{"username": "username", "password": "password"}' https:///login ``` Accessing the private endpoint with the token will now succeed: ```sh -$ curl --header "Authorization: Bearer " https:///private +curl --header "Authorization: Bearer " https:///private ``` The token is set to expire in 5 minutus, so wait a while and try to access the private endpoint again. Once the token has expired, a user will need to get a new token from login. diff --git a/rocket/persist/README.md b/rocket/persist/README.md index 9a409c2a..7278bd0b 100644 --- a/rocket/persist/README.md +++ b/rocket/persist/README.md @@ -7,21 +7,21 @@ An example app to show what you can do with shuttle. To deploy the examples, check out the repository locally ```bash -$ git clone https://github.com/shuttle-hq/shuttle.git +git clone https://github.com/shuttle-hq/shuttle.git ``` navigate to the Persist root folder ```bash -$ cd examples/rocket/persist +cd examples/rocket/persist ``` Pick a project name that is something unique - in shuttle, projects are globally unique. Then run ```bash -$ cargo shuttle project new --name=$PROJECT_NAME -$ cargo shuttle deploy --name=$PROJECT_NAME +cargo shuttle project start --name=$PROJECT_NAME +cargo shuttle deploy --name=$PROJECT_NAME ``` Once deployed you can post to the endpoint the following values: diff --git a/rocket/url-shortener/README.md b/rocket/url-shortener/README.md index c8bf8684..ccffb3fd 100644 --- a/rocket/url-shortener/README.md +++ b/rocket/url-shortener/README.md @@ -31,31 +31,31 @@ The project consists of the following files To deploy this app, check out the repository locally ```bash -$ git clone https://github.com/shuttle-hq/shuttle.git +git clone https://github.com/shuttle-hq/shuttle.git ``` navigate to `examples/rocket/url-shortener` ```bash -$ cd examples/rocket/url-shortener +cd examples/rocket/url-shortener ``` install shuttle ```bash -$ cargo install cargo-shuttle +cargo install cargo-shuttle ``` login to shuttle ```bash -$ cargo shuttle login +cargo shuttle login ``` Pick a project name that is something unique - in shuttle, projects are globally unique. Then run ```bash -$ cargo shuttle project new --name=$PROJECT_NAME -$ cargo shuttle deploy --name=$PROJECT_NAME +cargo shuttle project start --name=$PROJECT_NAME +cargo shuttle deploy --name=$PROJECT_NAME ``` From 099b4099a342ac4b0dfd9ddb290e473e99a1e346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Wed, 12 Apr 2023 09:41:56 +0200 Subject: [PATCH 032/239] chore: v0.14.0 (#37) --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 6 +++--- axum/hello-world/Cargo.toml | 4 ++-- axum/static-files/Cargo.toml | 6 +++--- axum/static-next-server/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 6 +++--- next/hello-world/Cargo.toml | 2 +- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 27 files changed, 70 insertions(+), 70 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 9f6df577..074063a8 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } +shuttle-actix-web = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } tokio = { version = "1.26.0" } diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index ac9216bc..11ba16ad 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } +shuttle-actix-web = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } serde = "1.0.148" -shuttle-shared-db = { version = "0.13.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.14.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 7f708340..8f48daf8 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,8 +13,8 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } -shuttle-static-folder = "0.13.1" +shuttle-actix-web = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } +shuttle-static-folder = "0.14.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index a70d575c..a599d0e3 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } +shuttle-axum = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } tokio = { version = "1.26.0" } diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 9e9010e9..3a90ac89 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } -shuttle-static-folder = "0.13.1" +shuttle-axum = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } +shuttle-static-folder = "0.14.0" tokio = { version = "1.26.0" } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index bcca4a95..4ffd6bca 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } -shuttle-static-folder = "0.13.1" +shuttle-axum = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } +shuttle-static-folder = "0.14.0" tokio = { version = "1.26.0" } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index dc7b9b4a..ba32b587 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,8 +11,8 @@ hyper = { version = "0.14.23", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-axum = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } -shuttle-static-folder = "0.13.1" +shuttle-axum = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } +shuttle-static-folder = "0.14.0" tokio = { version = "1.26.0" } tower-http = { version = "0.3.0", features = ["fs"] } diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index d300b0c0..c15f4e2f 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -8,6 +8,6 @@ crate-type = [ "cdylib" ] [dependencies] # TODO: bump to 0.9 before merge -shuttle-next = "0.13.0" +shuttle-next = "0.14.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index d62c2014..2603ee0f 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } +shuttle-poem = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } tokio = { version = "1.26.0" } diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index ff5df19e..484f0879 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = { version = "0.13.0" } -shuttle-shared-db = { version = "0.13.0", features = ["mongodb"] } -shuttle-runtime = { version = "0.13.0" } +shuttle-poem = { version = "0.14.0" } +shuttle-shared-db = { version = "0.14.0", features = ["mongodb"] } +shuttle-runtime = { version = "0.14.0" } serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = { version = "1.26.0" } diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index ab6afb4d..afa030ef 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } -shuttle-shared-db = { version = "0.13.0", features = ["postgres"] } +shuttle-poem = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } +shuttle-shared-db = { version = "0.14.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 068e2e60..009f2606 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } -shuttle-secrets = "0.13.0" +shuttle-poise = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } +shuttle-secrets = "0.14.0" tracing = "0.1.37" tokio = { version = "1.26.0" } diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index 557758ad..fdb535bd 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } +shuttle-rocket = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } tokio = { version = "1.26.0" } diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 874febc7..a9f215a2 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } +shuttle-rocket = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } tokio = { version = "1.26.0" } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 07a9fcfe..74fba9bb 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.13.0" -shuttle-rocket = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } +shuttle-persist = "0.14.0" +shuttle-rocket = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } tokio = { version = "1.26.0" } diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 1ba95a85..a049fc05 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.13.0", features = ["postgres"] } -shuttle-rocket = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } +shuttle-shared-db = { version = "0.14.0", features = ["postgres"] } +shuttle-rocket = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index af2d8f43..cc9827a3 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } -shuttle-secrets = "0.13.0" +shuttle-rocket = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } +shuttle-secrets = "0.14.0" tokio = { version = "1.26.0" } diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 5f20e124..2be58667 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } +shuttle-rocket = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } serde = "1.0.148" -shuttle-shared-db = { version = "0.13.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.14.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } url = "2.3.1" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 68eac302..c0bdb811 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.37.5" -shuttle-salvo = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } +shuttle-salvo = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } tokio = { version = "1.26.0" } diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 91116e69..4a7f1a2d 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } +shuttle-serenity = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.13.0" +shuttle-secrets = "0.14.0" tokio = { version = "1.26.0" } tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index ed47ae03..ab92c493 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.13.0" -shuttle-serenity = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } -shuttle-shared-db = { version = "0.13.0", features = ["postgres"] } +shuttle-secrets = "0.14.0" +shuttle-serenity = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } +shuttle-shared-db = { version = "0.14.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index c8a2113c..a27425ca 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } +shuttle-thruster = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = { version = "1.26.0" } diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index b2b2b6ac..93b4a9e6 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.13.0", features = ["postgres"] } -shuttle-thruster = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } +shuttle-aws-rds = { version = "0.14.0", features = ["postgres"] } +shuttle-thruster = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = { version = "1.26.0" } diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 65d544f1..5392605c 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = { version = "0.13.0" } -shuttle-runtime = { version = "0.13.0" } +shuttle-tide = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } tokio = { version = "1.26.0" } tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index bbd02385..208c237d 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.13.0", features = ["postgres"] } -shuttle-runtime = { version = "0.13.0" } -shuttle-tide = { version = "0.13.0" } +shuttle-aws-rds = { version = "0.14.0", features = ["postgres"] } +shuttle-runtime = { version = "0.14.0" } +shuttle-tide = { version = "0.14.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 53f4b9bc..74b2509c 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = { version = "0.13.0" } -shuttle-tower = { version = "0.13.0" } +shuttle-runtime = { version = "0.14.0" } +shuttle-tower = { version = "0.14.0" } tower = { version = "0.4.13", features = ["full"] } tokio = { version = "1.26.0" } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index cec8baa6..4f2a6010 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = { version = "0.13.0" } -shuttle-warp = { version = "0.13.0" } +shuttle-runtime = { version = "0.14.0" } +shuttle-warp = { version = "0.14.0" } tokio = { version = "1.26.0" } warp = "0.3.3" From 6fd2a8afd6f21ef6389a25db3a05289aeff69cb7 Mon Sep 17 00:00:00 2001 From: jhawkesworth Date: Thu, 20 Apr 2023 12:23:39 +0100 Subject: [PATCH 033/239] feat examples: add rocket dynamic template (shuttle-static-folder) example (#38) * feat examples: add rocket static files and dynamic template example projects. * feat examples: remove unneeded static-files rocket example * examples docs: fix incorrect comment * feat examples: code now formatted with rustfmt and comment regarding serving static content --- rocket/dyn_template_hbs/Cargo.toml | 12 +++++ rocket/dyn_template_hbs/README.md | 5 ++ rocket/dyn_template_hbs/Shuttle.toml | 1 + rocket/dyn_template_hbs/src/main.rs | 46 +++++++++++++++++++ .../dyn_template_hbs/templates/index.html.hbs | 21 +++++++++ 5 files changed, 85 insertions(+) create mode 100644 rocket/dyn_template_hbs/Cargo.toml create mode 100644 rocket/dyn_template_hbs/README.md create mode 100644 rocket/dyn_template_hbs/Shuttle.toml create mode 100644 rocket/dyn_template_hbs/src/main.rs create mode 100644 rocket/dyn_template_hbs/templates/index.html.hbs diff --git a/rocket/dyn_template_hbs/Cargo.toml b/rocket/dyn_template_hbs/Cargo.toml new file mode 100644 index 00000000..8beeb548 --- /dev/null +++ b/rocket/dyn_template_hbs/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "hello-world" +version = "0.1.0" +edition = "2021" + +[dependencies] +rocket = "0.5.0-rc.2" +shuttle-rocket = { version = "0.14.0" } +shuttle-runtime = { version = "0.14.0" } +shuttle-static-folder = "0.14.0" +rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } +tokio = { version = "1.26.0" } diff --git a/rocket/dyn_template_hbs/README.md b/rocket/dyn_template_hbs/README.md new file mode 100644 index 00000000..58b00112 --- /dev/null +++ b/rocket/dyn_template_hbs/README.md @@ -0,0 +1,5 @@ +# Rendering Handlebars dynamic templates with Rocket + +This example shows how to render templated content using Handlebars templates from [rocket](https://github.com/SergioBenitez/Rocket/) and shuttle. + +This example is inspired by templating example from the rocket repo, to see more ways to do this checkout the [original](https://github.com/SergioBenitez/Rocket/tree/master/examples/templating). diff --git a/rocket/dyn_template_hbs/Shuttle.toml b/rocket/dyn_template_hbs/Shuttle.toml new file mode 100644 index 00000000..148562f8 --- /dev/null +++ b/rocket/dyn_template_hbs/Shuttle.toml @@ -0,0 +1 @@ +name = "static-files-rocket-app" diff --git a/rocket/dyn_template_hbs/src/main.rs b/rocket/dyn_template_hbs/src/main.rs new file mode 100644 index 00000000..99ff8d16 --- /dev/null +++ b/rocket/dyn_template_hbs/src/main.rs @@ -0,0 +1,46 @@ +#[macro_use] +extern crate rocket; +// uncomment if you also wish to serve static resources +// use rocket::fs::{FileServer, relative}; +use rocket::response::Redirect; +use rocket_dyn_templates::{context, Template}; +use std::path::PathBuf; + +#[get("/")] +fn index() -> Redirect { + Redirect::to(uri!("/", hello(name = "Your Name"))) +} +#[get("/hello/")] +pub fn hello(name: &str) -> Template { + Template::render( + "index", + context! { + title: "Hello", + name: Some(name), + items: vec!["Example", "List", "Of", "Five", "Items"], + }, + ) +} + +#[shuttle_runtime::main] +async fn rocket( + #[shuttle_static_folder::StaticFolder(folder = "templates")] static_folder: PathBuf, +) -> shuttle_rocket::ShuttleRocket { + /* The provisioned static folder template directory will not be a sub folder + of the location of the executable so it is necessary to merge the + template_dir setting into the configuration at runtime so that dynamic templates work. + + Note that shuttle does not include Rocket.toml + so merging config is the preferred way to modify any settings + that would otherwise be set in Rocket.toml + */ + let template_dir = static_folder.to_str().unwrap(); + let figment = rocket::Config::figment().merge(("template_dir", template_dir)); + let rocket = rocket::custom(figment) + // If you also wish to serve static content, uncomment line below and corresponding 'use' on line 4 + // .mount("/", FileServer::from(relative!("templates"))) + .mount("/", routes![index, hello]) + .attach(Template::fairing()); + + Ok(rocket.into()) +} diff --git a/rocket/dyn_template_hbs/templates/index.html.hbs b/rocket/dyn_template_hbs/templates/index.html.hbs new file mode 100644 index 00000000..84b7d9cd --- /dev/null +++ b/rocket/dyn_template_hbs/templates/index.html.hbs @@ -0,0 +1,21 @@ + + + + Shuttle example: Rocket with Handlebars dynamic templates + + +
+

Hi {{ name }}!

+

Try entering your own name in the page url to see the page content change ./hello/edit_this_part_of_url

+

Here are the items supplied by the vec! macro in the Template::render context:

+
    + {{#each items}} +
  • {{ this }}
  • + {{/each}} +
+
+
+

Templates are evaluated on request, so if you edit a template while running locally using cargo shuttle run there is no need to rebuild.

+
+ + From 61ad08ab99188f42d1312e9a92aa837f4aad23b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Thu, 27 Apr 2023 13:11:54 +0200 Subject: [PATCH 034/239] chore: v0.15.0 (#39) --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 6 +++--- axum/hello-world/Cargo.toml | 4 ++-- axum/static-files/Cargo.toml | 6 +++--- axum/static-next-server/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 6 +++--- next/hello-world/Cargo.toml | 2 +- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/dyn_template_hbs/Cargo.toml | 6 +++--- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 29 files changed, 75 insertions(+), 75 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 074063a8..aecd2f60 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } +shuttle-actix-web = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } tokio = { version = "1.26.0" } diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 11ba16ad..82e2c09f 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } +shuttle-actix-web = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } serde = "1.0.148" -shuttle-shared-db = { version = "0.14.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.15.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 8f48daf8..2b712670 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,8 +13,8 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } -shuttle-static-folder = "0.14.0" +shuttle-actix-web = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } +shuttle-static-folder = "0.15.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index a599d0e3..d1be73b9 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } +shuttle-axum = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } tokio = { version = "1.26.0" } diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 3a90ac89..7afe2c92 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } -shuttle-static-folder = "0.14.0" +shuttle-axum = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } +shuttle-static-folder = "0.15.0" tokio = { version = "1.26.0" } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 4ffd6bca..7bbf0d25 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } -shuttle-static-folder = "0.14.0" +shuttle-axum = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } +shuttle-static-folder = "0.15.0" tokio = { version = "1.26.0" } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index ba32b587..b8632189 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,8 +11,8 @@ hyper = { version = "0.14.23", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-axum = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } -shuttle-static-folder = "0.14.0" +shuttle-axum = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } +shuttle-static-folder = "0.15.0" tokio = { version = "1.26.0" } tower-http = { version = "0.3.0", features = ["fs"] } diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index c15f4e2f..40b66491 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -8,6 +8,6 @@ crate-type = [ "cdylib" ] [dependencies] # TODO: bump to 0.9 before merge -shuttle-next = "0.14.0" +shuttle-next = "0.15.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 2603ee0f..b878f473 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } +shuttle-poem = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } tokio = { version = "1.26.0" } diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 484f0879..d9f0fa63 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = { version = "0.14.0" } -shuttle-shared-db = { version = "0.14.0", features = ["mongodb"] } -shuttle-runtime = { version = "0.14.0" } +shuttle-poem = { version = "0.15.0" } +shuttle-shared-db = { version = "0.15.0", features = ["mongodb"] } +shuttle-runtime = { version = "0.15.0" } serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = { version = "1.26.0" } diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index afa030ef..1b3def68 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } -shuttle-shared-db = { version = "0.14.0", features = ["postgres"] } +shuttle-poem = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } +shuttle-shared-db = { version = "0.15.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 009f2606..fa265335 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } -shuttle-secrets = "0.14.0" +shuttle-poise = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } +shuttle-secrets = "0.15.0" tracing = "0.1.37" tokio = { version = "1.26.0" } diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index fdb535bd..33ed2059 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } +shuttle-rocket = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } tokio = { version = "1.26.0" } diff --git a/rocket/dyn_template_hbs/Cargo.toml b/rocket/dyn_template_hbs/Cargo.toml index 8beeb548..16e89c18 100644 --- a/rocket/dyn_template_hbs/Cargo.toml +++ b/rocket/dyn_template_hbs/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } -shuttle-static-folder = "0.14.0" +shuttle-rocket = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } +shuttle-static-folder = "0.15.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = { version = "1.26.0" } diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index a9f215a2..1db5e5b3 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } +shuttle-rocket = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } tokio = { version = "1.26.0" } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 74fba9bb..7d3ceebb 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.14.0" -shuttle-rocket = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } +shuttle-persist = "0.15.0" +shuttle-rocket = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } tokio = { version = "1.26.0" } diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index a049fc05..37974539 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.14.0", features = ["postgres"] } -shuttle-rocket = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } +shuttle-shared-db = { version = "0.15.0", features = ["postgres"] } +shuttle-rocket = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index cc9827a3..d3e3852f 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } -shuttle-secrets = "0.14.0" +shuttle-rocket = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } +shuttle-secrets = "0.15.0" tokio = { version = "1.26.0" } diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 2be58667..2535d528 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } +shuttle-rocket = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } serde = "1.0.148" -shuttle-shared-db = { version = "0.14.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.15.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 82c7e45c..8a97c290 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } +shuttle-rocket = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } tokio = { version = "1.26.0" } diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index c0bdb811..33fa87a9 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.37.5" -shuttle-salvo = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } +shuttle-salvo = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } tokio = { version = "1.26.0" } diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 4a7f1a2d..26631ae7 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } +shuttle-serenity = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.14.0" +shuttle-secrets = "0.15.0" tokio = { version = "1.26.0" } tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index ab92c493..9cb49e84 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.14.0" -shuttle-serenity = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } -shuttle-shared-db = { version = "0.14.0", features = ["postgres"] } +shuttle-secrets = "0.15.0" +shuttle-serenity = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } +shuttle-shared-db = { version = "0.15.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index a27425ca..1554f6bb 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } +shuttle-thruster = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = { version = "1.26.0" } diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 93b4a9e6..e8796d52 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.14.0", features = ["postgres"] } -shuttle-thruster = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } +shuttle-aws-rds = { version = "0.15.0", features = ["postgres"] } +shuttle-thruster = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = { version = "1.26.0" } diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 5392605c..69ced1ca 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = { version = "0.14.0" } -shuttle-runtime = { version = "0.14.0" } +shuttle-tide = { version = "0.15.0" } +shuttle-runtime = { version = "0.15.0" } tokio = { version = "1.26.0" } tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index 208c237d..d820b189 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.14.0", features = ["postgres"] } -shuttle-runtime = { version = "0.14.0" } -shuttle-tide = { version = "0.14.0" } +shuttle-aws-rds = { version = "0.15.0", features = ["postgres"] } +shuttle-runtime = { version = "0.15.0" } +shuttle-tide = { version = "0.15.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 74b2509c..16baceaf 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = { version = "0.14.0" } -shuttle-tower = { version = "0.14.0" } +shuttle-runtime = { version = "0.15.0" } +shuttle-tower = { version = "0.15.0" } tower = { version = "0.4.13", features = ["full"] } tokio = { version = "1.26.0" } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 4f2a6010..d17bb366 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = { version = "0.14.0" } -shuttle-warp = { version = "0.14.0" } +shuttle-runtime = { version = "0.15.0" } +shuttle-warp = { version = "0.15.0" } tokio = { version = "1.26.0" } warp = "0.3.3" From 66ad6cf7e5f30c184cdc525915eaa633cef23aa4 Mon Sep 17 00:00:00 2001 From: morlinbrot Date: Wed, 3 May 2023 10:31:52 +0200 Subject: [PATCH 035/239] Basic Service impl --- crontab/Cargo.toml | 15 +++++++++++++++ crontab/src/main.rs | 33 +++++++++++++++++++++++++++++++++ crontab/src/router.rs | 11 +++++++++++ 3 files changed, 59 insertions(+) create mode 100644 crontab/Cargo.toml create mode 100644 crontab/src/main.rs create mode 100644 crontab/src/router.rs diff --git a/crontab/Cargo.toml b/crontab/Cargo.toml new file mode 100644 index 00000000..519a63fe --- /dev/null +++ b/crontab/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "crontab" +version = "0.1.0" +edition = "2021" +publish = false + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.71" +async-trait = "0.1.68" +axum = "0.6.18" +shuttle-runtime = "0.15.0" +shuttle-service = "0.15.0" +tokio = "1.28.0" diff --git a/crontab/src/main.rs b/crontab/src/main.rs new file mode 100644 index 00000000..4b24cebc --- /dev/null +++ b/crontab/src/main.rs @@ -0,0 +1,33 @@ +use axum::Router; +use shuttle_runtime::async_trait; + +mod router; + +pub struct CronService { + router: Router, +} + +#[async_trait] +impl shuttle_service::Service for CronService { + async fn bind( + mut self, + addr: std::net::SocketAddr, + ) -> Result<(), shuttle_service::error::Error> { + let router = self.router; + + let serve_router = axum::Server::bind(&addr).serve(router.into_make_service()); + + tokio::select!( + _ = serve_router => {} + ); + + Ok(()) + } +} + +#[shuttle_runtime::main] +async fn init() -> Result { + let router = router::build_router(); + + Ok(CronService { router }) +} diff --git a/crontab/src/router.rs b/crontab/src/router.rs new file mode 100644 index 00000000..f9938ccd --- /dev/null +++ b/crontab/src/router.rs @@ -0,0 +1,11 @@ +use axum::http::StatusCode; +use axum::response::IntoResponse; +use axum::{routing::get, Router}; + +pub fn build_router() -> Router { + Router::new().route("/", get(hello_world)) +} + +pub async fn hello_world() -> impl IntoResponse { + (StatusCode::OK, "Hello world!").into_response() +} From d2dab07ecb5542b0a7ea0550ffd2f15b25be3300 Mon Sep 17 00:00:00 2001 From: morlinbrot Date: Wed, 3 May 2023 12:32:45 +0200 Subject: [PATCH 036/239] Add simple job execution --- crontab/Cargo.toml | 2 ++ crontab/src/main.rs | 56 ++++++++++++++++++++++++++++++------------- crontab/src/router.rs | 11 --------- 3 files changed, 42 insertions(+), 27 deletions(-) delete mode 100644 crontab/src/router.rs diff --git a/crontab/Cargo.toml b/crontab/Cargo.toml index 519a63fe..f60133ca 100644 --- a/crontab/Cargo.toml +++ b/crontab/Cargo.toml @@ -10,6 +10,8 @@ publish = false anyhow = "1.0.71" async-trait = "0.1.68" axum = "0.6.18" +chrono = "0.4.24" +cron = "0.12.0" shuttle-runtime = "0.15.0" shuttle-service = "0.15.0" tokio = "1.28.0" diff --git a/crontab/src/main.rs b/crontab/src/main.rs index 4b24cebc..2ddde743 100644 --- a/crontab/src/main.rs +++ b/crontab/src/main.rs @@ -1,33 +1,57 @@ -use axum::Router; +use chrono::Utc; +use std::{future::Future, str::FromStr}; + +use cron::Schedule; use shuttle_runtime::async_trait; -mod router; +pub struct CronService { + schedule: Schedule, + job: fn() -> F, +} -pub struct CronService { - router: Router, +impl CronService { + async fn start(&self) { + for time in self.schedule.upcoming(Utc).take(4) { + let now = chrono::offset::Utc::now(); + let dur = time.signed_duration_since(now); + + let now_tok = tokio::time::Instant::now(); + if let Some(instant) = now_tok.checked_add(dur.to_std().unwrap()) { + tokio::time::sleep_until(instant).await; + (self.job)().await; + } + } + } } #[async_trait] -impl shuttle_service::Service for CronService { +impl shuttle_service::Service for CronService +where + F: Future + Send + Sync + 'static, +{ async fn bind( mut self, - addr: std::net::SocketAddr, + _addr: std::net::SocketAddr, ) -> Result<(), shuttle_service::error::Error> { - let router = self.router; - - let serve_router = axum::Server::bind(&addr).serve(router.into_make_service()); + self.start().await; - tokio::select!( - _ = serve_router => {} - ); + println!("All done."); Ok(()) } } -#[shuttle_runtime::main] -async fn init() -> Result { - let router = router::build_router(); +async fn my_job() { + let now = chrono::offset::Utc::now(); + println!("It is {}", now.format("%Y-%m-%d %H:%M:%S")); +} - Ok(CronService { router }) +#[shuttle_runtime::main] +async fn init( +) -> Result + Send + 'static>, shuttle_service::Error> { + let schedule = Schedule::from_str("*/1 * * * * *").unwrap(); + Ok(CronService { + schedule, + job: my_job, + }) } diff --git a/crontab/src/router.rs b/crontab/src/router.rs deleted file mode 100644 index f9938ccd..00000000 --- a/crontab/src/router.rs +++ /dev/null @@ -1,11 +0,0 @@ -use axum::http::StatusCode; -use axum::response::IntoResponse; -use axum::{routing::get, Router}; - -pub fn build_router() -> Router { - Router::new().route("/", get(hello_world)) -} - -pub async fn hello_world() -> impl IntoResponse { - (StatusCode::OK, "Hello world!").into_response() -} From 412febbd95251ba73488b7d936a3a3b9e395462c Mon Sep 17 00:00:00 2001 From: Krzysztof Urbaniak Date: Wed, 3 May 2023 18:35:50 +0200 Subject: [PATCH 037/239] run CronService job in a loop --- crontab/src/main.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/crontab/src/main.rs b/crontab/src/main.rs index 2ddde743..fffbfa11 100644 --- a/crontab/src/main.rs +++ b/crontab/src/main.rs @@ -1,5 +1,6 @@ use chrono::Utc; use std::{future::Future, str::FromStr}; +use tokio::time::sleep; use cron::Schedule; use shuttle_runtime::async_trait; @@ -11,15 +12,13 @@ pub struct CronService { impl CronService { async fn start(&self) { - for time in self.schedule.upcoming(Utc).take(4) { - let now = chrono::offset::Utc::now(); - let dur = time.signed_duration_since(now); - - let now_tok = tokio::time::Instant::now(); - if let Some(instant) = now_tok.checked_add(dur.to_std().unwrap()) { - tokio::time::sleep_until(instant).await; - (self.job)().await; - } + while let Some(next_run) = self.schedule.upcoming(Utc).next() { + let next_run_in = next_run + .signed_duration_since(chrono::offset::Utc::now()) + .to_std() + .unwrap(); + sleep(next_run_in).await; + (self.job)().await; } } } @@ -49,7 +48,7 @@ async fn my_job() { #[shuttle_runtime::main] async fn init( ) -> Result + Send + 'static>, shuttle_service::Error> { - let schedule = Schedule::from_str("*/1 * * * * *").unwrap(); + let schedule = Schedule::from_str("*/5 * * * * *").unwrap(); Ok(CronService { schedule, job: my_job, From 53d4fe3e361bd72fa68dff7444840df5421bf4d5 Mon Sep 17 00:00:00 2001 From: morlinbrot Date: Thu, 4 May 2023 11:11:50 +0200 Subject: [PATCH 038/239] Add some documentation --- crontab/README.md | 6 ++++++ crontab/src/main.rs | 16 ++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 crontab/README.md diff --git a/crontab/README.md b/crontab/README.md new file mode 100644 index 00000000..85aecc64 --- /dev/null +++ b/crontab/README.md @@ -0,0 +1,6 @@ +# crontab service example + +A service that runs a job at the specified cron intervals. + +This example demonstrates how to implement `shuttle_runtime::Service` for your own type to set up a custom service without any web framework. + diff --git a/crontab/src/main.rs b/crontab/src/main.rs index fffbfa11..0b2a660c 100644 --- a/crontab/src/main.rs +++ b/crontab/src/main.rs @@ -5,6 +5,15 @@ use tokio::time::sleep; use cron::Schedule; use shuttle_runtime::async_trait; +// "Run every 2 seconds" +const SCHEDULE: &str = "*/2 * * * * *"; + +// The function that will be run. +async fn my_job() { + let now = chrono::offset::Utc::now(); + println!("It is {}", now.format("%Y-%m-%d %H:%M:%S")); +} + pub struct CronService { schedule: Schedule, job: fn() -> F, @@ -40,15 +49,10 @@ where } } -async fn my_job() { - let now = chrono::offset::Utc::now(); - println!("It is {}", now.format("%Y-%m-%d %H:%M:%S")); -} - #[shuttle_runtime::main] async fn init( ) -> Result + Send + 'static>, shuttle_service::Error> { - let schedule = Schedule::from_str("*/5 * * * * *").unwrap(); + let schedule = Schedule::from_str(SCHEDULE).unwrap(); Ok(CronService { schedule, job: my_job, From 2eb52d54c5bb01cfcac011b0e343cd43ac3ac2df Mon Sep 17 00:00:00 2001 From: morlinbrot Date: Fri, 5 May 2023 12:50:30 +0200 Subject: [PATCH 039/239] Use tracing for output, clean up dependencies --- crontab/Cargo.toml | 3 +-- crontab/src/main.rs | 9 ++++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/crontab/Cargo.toml b/crontab/Cargo.toml index f60133ca..2275580e 100644 --- a/crontab/Cargo.toml +++ b/crontab/Cargo.toml @@ -7,11 +7,10 @@ publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -anyhow = "1.0.71" async-trait = "0.1.68" -axum = "0.6.18" chrono = "0.4.24" cron = "0.12.0" shuttle-runtime = "0.15.0" shuttle-service = "0.15.0" tokio = "1.28.0" +tracing = "0.1.37" diff --git a/crontab/src/main.rs b/crontab/src/main.rs index 0b2a660c..2445ea49 100644 --- a/crontab/src/main.rs +++ b/crontab/src/main.rs @@ -1,9 +1,10 @@ use chrono::Utc; use std::{future::Future, str::FromStr}; use tokio::time::sleep; +use tracing::info; use cron::Schedule; -use shuttle_runtime::async_trait; +use shuttle_runtime::{async_trait, Service}; // "Run every 2 seconds" const SCHEDULE: &str = "*/2 * * * * *"; @@ -11,7 +12,7 @@ const SCHEDULE: &str = "*/2 * * * * *"; // The function that will be run. async fn my_job() { let now = chrono::offset::Utc::now(); - println!("It is {}", now.format("%Y-%m-%d %H:%M:%S")); + info!("It is {}", now.format("%Y-%m-%d %H:%M:%S")); } pub struct CronService { @@ -33,7 +34,7 @@ impl CronService { } #[async_trait] -impl shuttle_service::Service for CronService +impl Service for CronService where F: Future + Send + Sync + 'static, { @@ -43,8 +44,6 @@ where ) -> Result<(), shuttle_service::error::Error> { self.start().await; - println!("All done."); - Ok(()) } } From 026fc302c593dd591aaa73da332f36793df9905b Mon Sep 17 00:00:00 2001 From: mikegin Date: Fri, 5 May 2023 07:55:58 -0400 Subject: [PATCH 040/239] feat: changing '/hello' routes to '/' (#41) * feat: changing '/hello' routes to '/' * feat: change "/hello" routes to "/" --------- Co-authored-by: Paul Otten --- actix-web/hello-world/src/main.rs | 2 +- axum/hello-world/src/main.rs | 2 +- next/hello-world/src/lib.rs | 2 +- poem/hello-world/src/main.rs | 2 +- rocket/hello-world/src/main.rs | 2 +- salvo/hello-world/src/main.rs | 2 +- thruster/hello-world/src/main.rs | 2 +- tide/hello-world/src/main.rs | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/actix-web/hello-world/src/main.rs b/actix-web/hello-world/src/main.rs index e1bc4b0e..c0c2f056 100644 --- a/actix-web/hello-world/src/main.rs +++ b/actix-web/hello-world/src/main.rs @@ -1,7 +1,7 @@ use actix_web::{get, web::ServiceConfig}; use shuttle_actix_web::ShuttleActixWeb; -#[get("/hello")] +#[get("/")] async fn hello_world() -> &'static str { "Hello World!" } diff --git a/axum/hello-world/src/main.rs b/axum/hello-world/src/main.rs index 01c791f0..158c1055 100644 --- a/axum/hello-world/src/main.rs +++ b/axum/hello-world/src/main.rs @@ -6,7 +6,7 @@ async fn hello_world() -> &'static str { #[shuttle_runtime::main] async fn axum() -> shuttle_axum::ShuttleAxum { - let router = Router::new().route("/hello", get(hello_world)); + let router = Router::new().route("/", get(hello_world)); Ok(router.into()) } diff --git a/next/hello-world/src/lib.rs b/next/hello-world/src/lib.rs index af8ad1e0..a4ad78a2 100644 --- a/next/hello-world/src/lib.rs +++ b/next/hello-world/src/lib.rs @@ -5,7 +5,7 @@ shuttle_next::app! { use shuttle_next::extract::BodyStream; use shuttle_next::response::{Response, IntoResponse}; - #[shuttle_next::endpoint(method = get, route = "/hello")] + #[shuttle_next::endpoint(method = get, route = "/")] async fn hello() -> &'static str { "Hello, World!" } diff --git a/poem/hello-world/src/main.rs b/poem/hello-world/src/main.rs index 95d339c0..00bc883f 100644 --- a/poem/hello-world/src/main.rs +++ b/poem/hello-world/src/main.rs @@ -8,7 +8,7 @@ fn hello_world() -> &'static str { #[shuttle_runtime::main] async fn poem() -> ShuttlePoem { - let app = Route::new().at("/hello", get(hello_world)); + let app = Route::new().at("/", get(hello_world)); Ok(app.into()) } diff --git a/rocket/hello-world/src/main.rs b/rocket/hello-world/src/main.rs index 847d04aa..25ca1a77 100644 --- a/rocket/hello-world/src/main.rs +++ b/rocket/hello-world/src/main.rs @@ -8,7 +8,7 @@ fn index() -> &'static str { #[shuttle_runtime::main] async fn rocket() -> shuttle_rocket::ShuttleRocket { - let rocket = rocket::build().mount("/hello", routes![index]); + let rocket = rocket::build().mount("/", routes![index]); Ok(rocket.into()) } diff --git a/salvo/hello-world/src/main.rs b/salvo/hello-world/src/main.rs index 39ed4ff7..f4ab9a49 100644 --- a/salvo/hello-world/src/main.rs +++ b/salvo/hello-world/src/main.rs @@ -7,7 +7,7 @@ async fn hello_world(res: &mut Response) { #[shuttle_runtime::main] async fn salvo() -> shuttle_salvo::ShuttleSalvo { - let router = Router::with_path("hello").get(hello_world); + let router = Router::new().get(hello_world); Ok(router.into()) } diff --git a/thruster/hello-world/src/main.rs b/thruster/hello-world/src/main.rs index 97d95f40..6abe5adc 100644 --- a/thruster/hello-world/src/main.rs +++ b/thruster/hello-world/src/main.rs @@ -12,7 +12,7 @@ async fn hello(mut context: Ctx, _next: MiddlewareNext) -> MiddlewareResult #[shuttle_runtime::main] async fn thruster() -> shuttle_thruster::ShuttleThruster> { let server = HyperServer::new( - App::::create(generate_context, ()).get("/hello", m![hello]), + App::::create(generate_context, ()).get("/", m![hello]), ); Ok(server.into()) diff --git a/tide/hello-world/src/main.rs b/tide/hello-world/src/main.rs index cab1c3a9..c211b1f8 100644 --- a/tide/hello-world/src/main.rs +++ b/tide/hello-world/src/main.rs @@ -3,7 +3,7 @@ async fn tide() -> shuttle_tide::ShuttleTide<()> { let mut app = tide::new(); app.with(tide::log::LogMiddleware::new()); - app.at("/hello").get(|_| async { Ok("Hello, world!") }); + app.at("/").get(|_| async { Ok("Hello, world!") }); Ok(app.into()) } From 43c0758eebaa73255966ac349047a1eaa7b5f5d3 Mon Sep 17 00:00:00 2001 From: Pieter Date: Fri, 5 May 2023 18:58:43 +0200 Subject: [PATCH 041/239] misc: rename examples to shuttle-examples (#44) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c5dcc901..30da79b8 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Some example apps to show what you can do with shuttle. To deploy the examples, check out the repository locally ```bash -git clone https://github.com/shuttle-hq/examples.git +git clone https://github.com/shuttle-hq/shuttle-examples.git ``` navigate to an example root folder From 0c5b8c236c816c19f48f859e2adf66d413a3e17e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Mon, 8 May 2023 10:40:44 +0200 Subject: [PATCH 042/239] chore: v0.16.0 (#46) --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 6 +++--- axum/hello-world/Cargo.toml | 4 ++-- axum/static-files/Cargo.toml | 6 +++--- axum/static-next-server/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 6 +++--- next/hello-world/Cargo.toml | 2 +- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/dyn_template_hbs/Cargo.toml | 6 +++--- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 29 files changed, 75 insertions(+), 75 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index aecd2f60..ea296a0e 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } +shuttle-actix-web = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } tokio = { version = "1.26.0" } diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 82e2c09f..9b657a91 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } +shuttle-actix-web = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } serde = "1.0.148" -shuttle-shared-db = { version = "0.15.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.16.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 2b712670..0890d70d 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,8 +13,8 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } -shuttle-static-folder = "0.15.0" +shuttle-actix-web = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } +shuttle-static-folder = "0.16.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index d1be73b9..7ed2f03a 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } +shuttle-axum = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } tokio = { version = "1.26.0" } diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 7afe2c92..297c8ee9 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } -shuttle-static-folder = "0.15.0" +shuttle-axum = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } +shuttle-static-folder = "0.16.0" tokio = { version = "1.26.0" } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 7bbf0d25..3e9eb810 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } -shuttle-static-folder = "0.15.0" +shuttle-axum = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } +shuttle-static-folder = "0.16.0" tokio = { version = "1.26.0" } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index b8632189..04992a12 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,8 +11,8 @@ hyper = { version = "0.14.23", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-axum = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } -shuttle-static-folder = "0.15.0" +shuttle-axum = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } +shuttle-static-folder = "0.16.0" tokio = { version = "1.26.0" } tower-http = { version = "0.3.0", features = ["fs"] } diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index 40b66491..cf57762f 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -8,6 +8,6 @@ crate-type = [ "cdylib" ] [dependencies] # TODO: bump to 0.9 before merge -shuttle-next = "0.15.0" +shuttle-next = "0.16.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index b878f473..f086ac0e 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } +shuttle-poem = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } tokio = { version = "1.26.0" } diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index d9f0fa63..12acb4ae 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = { version = "0.15.0" } -shuttle-shared-db = { version = "0.15.0", features = ["mongodb"] } -shuttle-runtime = { version = "0.15.0" } +shuttle-poem = { version = "0.16.0" } +shuttle-shared-db = { version = "0.16.0", features = ["mongodb"] } +shuttle-runtime = { version = "0.16.0" } serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = { version = "1.26.0" } diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 1b3def68..758f4dae 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } -shuttle-shared-db = { version = "0.15.0", features = ["postgres"] } +shuttle-poem = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } +shuttle-shared-db = { version = "0.16.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index fa265335..4bf3ba71 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } -shuttle-secrets = "0.15.0" +shuttle-poise = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } +shuttle-secrets = "0.16.0" tracing = "0.1.37" tokio = { version = "1.26.0" } diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index 33ed2059..0d7bc2da 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } +shuttle-rocket = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } tokio = { version = "1.26.0" } diff --git a/rocket/dyn_template_hbs/Cargo.toml b/rocket/dyn_template_hbs/Cargo.toml index 16e89c18..861c1c7f 100644 --- a/rocket/dyn_template_hbs/Cargo.toml +++ b/rocket/dyn_template_hbs/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } -shuttle-static-folder = "0.15.0" +shuttle-rocket = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } +shuttle-static-folder = "0.16.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = { version = "1.26.0" } diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 1db5e5b3..4092f7ac 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } +shuttle-rocket = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } tokio = { version = "1.26.0" } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 7d3ceebb..8630ec8e 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.15.0" -shuttle-rocket = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } +shuttle-persist = "0.16.0" +shuttle-rocket = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } tokio = { version = "1.26.0" } diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 37974539..67822146 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.15.0", features = ["postgres"] } -shuttle-rocket = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } +shuttle-shared-db = { version = "0.16.0", features = ["postgres"] } +shuttle-rocket = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index d3e3852f..688f12e7 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } -shuttle-secrets = "0.15.0" +shuttle-rocket = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } +shuttle-secrets = "0.16.0" tokio = { version = "1.26.0" } diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 2535d528..2b5ba91d 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } +shuttle-rocket = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } serde = "1.0.148" -shuttle-shared-db = { version = "0.15.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.16.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 8a97c290..2f81def3 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } +shuttle-rocket = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } tokio = { version = "1.26.0" } diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 33fa87a9..d15a50f8 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.37.5" -shuttle-salvo = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } +shuttle-salvo = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } tokio = { version = "1.26.0" } diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 26631ae7..fe7fb7be 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } +shuttle-serenity = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.15.0" +shuttle-secrets = "0.16.0" tokio = { version = "1.26.0" } tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 9cb49e84..057b6e2d 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.15.0" -shuttle-serenity = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } -shuttle-shared-db = { version = "0.15.0", features = ["postgres"] } +shuttle-secrets = "0.16.0" +shuttle-serenity = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } +shuttle-shared-db = { version = "0.16.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 1554f6bb..83bb5e48 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } +shuttle-thruster = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = { version = "1.26.0" } diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index e8796d52..68e0dd79 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.15.0", features = ["postgres"] } -shuttle-thruster = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } +shuttle-aws-rds = { version = "0.16.0", features = ["postgres"] } +shuttle-thruster = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = { version = "1.26.0" } diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 69ced1ca..565be4af 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = { version = "0.15.0" } -shuttle-runtime = { version = "0.15.0" } +shuttle-tide = { version = "0.16.0" } +shuttle-runtime = { version = "0.16.0" } tokio = { version = "1.26.0" } tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index d820b189..9b274e8d 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.15.0", features = ["postgres"] } -shuttle-runtime = { version = "0.15.0" } -shuttle-tide = { version = "0.15.0" } +shuttle-aws-rds = { version = "0.16.0", features = ["postgres"] } +shuttle-runtime = { version = "0.16.0" } +shuttle-tide = { version = "0.16.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 16baceaf..2ce12195 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = { version = "0.15.0" } -shuttle-tower = { version = "0.15.0" } +shuttle-runtime = { version = "0.16.0" } +shuttle-tower = { version = "0.16.0" } tower = { version = "0.4.13", features = ["full"] } tokio = { version = "1.26.0" } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index d17bb366..1750c157 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = { version = "0.15.0" } -shuttle-warp = { version = "0.15.0" } +shuttle-runtime = { version = "0.16.0" } +shuttle-warp = { version = "0.16.0" } tokio = { version = "1.26.0" } warp = "0.3.3" From 302459520e3166e247a9b5fdf680061dcdf44c01 Mon Sep 17 00:00:00 2001 From: morlinbrot Date: Mon, 8 May 2023 13:40:34 +0200 Subject: [PATCH 043/239] Basic Axum router impl --- crontab-api/Cargo.toml | 15 ++++++++++++++ crontab-api/request.sh | 6 ++++++ crontab-api/src/main.rs | 33 ++++++++++++++++++++++++++++++ crontab-api/src/router.rs | 42 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+) create mode 100644 crontab-api/Cargo.toml create mode 100644 crontab-api/request.sh create mode 100644 crontab-api/src/main.rs create mode 100644 crontab-api/src/router.rs diff --git a/crontab-api/Cargo.toml b/crontab-api/Cargo.toml new file mode 100644 index 00000000..516791e4 --- /dev/null +++ b/crontab-api/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "crontab-api" +version = "0.1.0" +edition = "2021" +publish = false + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +shuttle-runtime = "0.16.0" +axum = "0.6.18" +shuttle-axum = "0.16.0" +tokio = "1.28.0" +shuttle-secrets = "0.16.0" +serde = "1.0.162" diff --git a/crontab-api/request.sh b/crontab-api/request.sh new file mode 100644 index 00000000..d9224b93 --- /dev/null +++ b/crontab-api/request.sh @@ -0,0 +1,6 @@ +SCHEDULE="*/2 * * * * *" +URL="example.com" + +curl -X POST http://localhost:8000/set-schedule\ + -H "Content-Type: application/x-www-form-urlencoded"\ + -d "schedule=$SCHEDULE&url=$URL" diff --git a/crontab-api/src/main.rs b/crontab-api/src/main.rs new file mode 100644 index 00000000..3fb47873 --- /dev/null +++ b/crontab-api/src/main.rs @@ -0,0 +1,33 @@ +use axum::Router; +use shuttle_secrets::SecretStore; + +mod router; + +pub struct CrontabService { + router: Router, +} + +#[shuttle_runtime::async_trait] +impl shuttle_runtime::Service for CrontabService { + async fn bind(mut self, addr: std::net::SocketAddr) -> Result<(), shuttle_runtime::Error> { + let router = self.router; + + let serve_router = axum::Server::bind(&addr).serve(router.into_make_service()); + + tokio::select!( + // _ = self.discord_bot.run() => {}, + _ = serve_router => {} + ); + + Ok(()) + } +} + +#[shuttle_runtime::main] +async fn init( + #[shuttle_secrets::Secrets] _secrets: SecretStore, +) -> Result { + let router = router::build_router(); + + Ok(CrontabService { router }) +} diff --git a/crontab-api/src/router.rs b/crontab-api/src/router.rs new file mode 100644 index 00000000..f28b8d1f --- /dev/null +++ b/crontab-api/src/router.rs @@ -0,0 +1,42 @@ +use axum::http::StatusCode; +use axum::response::IntoResponse; +use axum::routing::{get, post}; +use axum::{extract::Form, Router}; +use serde::Deserialize; +use shuttle_runtime::tracing::info; + +pub fn build_router() -> Router { + Router::new() + .route("/", get(hello_world)) + .route("/set-schedule", post(set_schedule)) +} + +pub async fn hello_world() -> impl IntoResponse { + (StatusCode::OK, "Hello world!").into_response() +} + +#[derive(Debug, Deserialize)] +pub struct ScheduleRaw { + schedule: String, + url: String, +} + +#[derive(Debug, Deserialize)] +pub struct Schedule { + schedule: String, + url: String, +} + +impl From for Schedule { + fn from(ScheduleRaw { schedule, url }: ScheduleRaw) -> Self { + // TODO: Parse & verify + Self { schedule, url } + } +} + +pub async fn set_schedule(Form(schedule_raw): Form) -> impl IntoResponse { + let schedule: Schedule = schedule_raw.into(); + info!("Setting schedule: {:?}", schedule); + + StatusCode::OK +} From 391f119c407a5d3ae759e0645eede3d097af8525 Mon Sep 17 00:00:00 2001 From: Ethan Holz Date: Mon, 8 May 2023 07:17:29 -0500 Subject: [PATCH 044/239] style: Added rustfmt.toml (#45) --- rustfmt.toml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 rustfmt.toml diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000..7e5ab516 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,2 @@ +edition="2021" +reorder_imports = true From cdf353d49945a1c07bc03b2fe94c52d941331dcd Mon Sep 17 00:00:00 2001 From: morlinbrot Date: Mon, 8 May 2023 18:25:20 +0200 Subject: [PATCH 045/239] Add request.sh for testing, simplify router --- crontab-api/request.sh | 2 +- crontab-api/src/router.rs | 16 +--------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/crontab-api/request.sh b/crontab-api/request.sh index d9224b93..2eb9ac9f 100644 --- a/crontab-api/request.sh +++ b/crontab-api/request.sh @@ -1,6 +1,6 @@ SCHEDULE="*/2 * * * * *" URL="example.com" -curl -X POST http://localhost:8000/set-schedule\ +curl -v http://localhost:8000/set-schedule\ -H "Content-Type: application/x-www-form-urlencoded"\ -d "schedule=$SCHEDULE&url=$URL" diff --git a/crontab-api/src/router.rs b/crontab-api/src/router.rs index f28b8d1f..a9b269ab 100644 --- a/crontab-api/src/router.rs +++ b/crontab-api/src/router.rs @@ -15,27 +15,13 @@ pub async fn hello_world() -> impl IntoResponse { (StatusCode::OK, "Hello world!").into_response() } -#[derive(Debug, Deserialize)] -pub struct ScheduleRaw { - schedule: String, - url: String, -} - #[derive(Debug, Deserialize)] pub struct Schedule { schedule: String, url: String, } -impl From for Schedule { - fn from(ScheduleRaw { schedule, url }: ScheduleRaw) -> Self { - // TODO: Parse & verify - Self { schedule, url } - } -} - -pub async fn set_schedule(Form(schedule_raw): Form) -> impl IntoResponse { - let schedule: Schedule = schedule_raw.into(); +pub async fn set_schedule(Form(schedule): Form) -> impl IntoResponse { info!("Setting schedule: {:?}", schedule); StatusCode::OK From 0991a844f6e033927851998f0f1cd87611357bb8 Mon Sep 17 00:00:00 2001 From: morlinbrot Date: Mon, 8 May 2023 18:41:48 +0200 Subject: [PATCH 046/239] Add shuttle-persist to the mix --- crontab-api/Cargo.toml | 2 +- crontab-api/src/main.rs | 18 ++++++++++++++---- crontab-api/src/router.rs | 18 ++++++++++++++++-- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/crontab-api/Cargo.toml b/crontab-api/Cargo.toml index 516791e4..10c9812e 100644 --- a/crontab-api/Cargo.toml +++ b/crontab-api/Cargo.toml @@ -11,5 +11,5 @@ shuttle-runtime = "0.16.0" axum = "0.6.18" shuttle-axum = "0.16.0" tokio = "1.28.0" -shuttle-secrets = "0.16.0" serde = "1.0.162" +shuttle-persist = "0.16.0" diff --git a/crontab-api/src/main.rs b/crontab-api/src/main.rs index 3fb47873..43717ea5 100644 --- a/crontab-api/src/main.rs +++ b/crontab-api/src/main.rs @@ -1,10 +1,17 @@ +use std::sync::Arc; + use axum::Router; -use shuttle_secrets::SecretStore; +use shuttle_persist::PersistInstance; mod router; pub struct CrontabService { router: Router, + persist: PersistInstance, +} + +pub struct AppState { + persist: PersistInstance, } #[shuttle_runtime::async_trait] @@ -25,9 +32,12 @@ impl shuttle_runtime::Service for CrontabService { #[shuttle_runtime::main] async fn init( - #[shuttle_secrets::Secrets] _secrets: SecretStore, + #[shuttle_persist::Persist] persist: PersistInstance, ) -> Result { - let router = router::build_router(); + let app_state = Arc::new(AppState { + persist: persist.clone(), + }); + let router = router::build_router(app_state); - Ok(CrontabService { router }) + Ok(CrontabService { router, persist }) } diff --git a/crontab-api/src/router.rs b/crontab-api/src/router.rs index a9b269ab..c64cc781 100644 --- a/crontab-api/src/router.rs +++ b/crontab-api/src/router.rs @@ -1,3 +1,6 @@ +use std::sync::Arc; + +use axum::extract::State; use axum::http::StatusCode; use axum::response::IntoResponse; use axum::routing::{get, post}; @@ -5,10 +8,13 @@ use axum::{extract::Form, Router}; use serde::Deserialize; use shuttle_runtime::tracing::info; -pub fn build_router() -> Router { +use crate::AppState; + +pub fn build_router(app_state: Arc) -> Router { Router::new() .route("/", get(hello_world)) .route("/set-schedule", post(set_schedule)) + .with_state(app_state) } pub async fn hello_world() -> impl IntoResponse { @@ -21,8 +27,16 @@ pub struct Schedule { url: String, } -pub async fn set_schedule(Form(schedule): Form) -> impl IntoResponse { +pub async fn set_schedule( + State(app_state): State>, + Form(schedule): Form, +) -> impl IntoResponse { info!("Setting schedule: {:?}", schedule); + app_state.persist.save("some", "key"); + + let val: String = app_state.persist.load("some").unwrap(); + info!("Got state: {:?}", val); + StatusCode::OK } From d05f9dfd44cdafc8c136803cc5138e66073154e6 Mon Sep 17 00:00:00 2001 From: morlinbrot Date: Mon, 8 May 2023 19:27:05 +0200 Subject: [PATCH 047/239] Impl CrontabService with persist, write new schedules to persist --- crontab-api/Cargo.toml | 2 ++ crontab-api/src/main.rs | 50 +++++++++++++++++++++++++++++++++++++++ crontab-api/src/router.rs | 20 +++++++--------- 3 files changed, 60 insertions(+), 12 deletions(-) diff --git a/crontab-api/Cargo.toml b/crontab-api/Cargo.toml index 10c9812e..da81a58a 100644 --- a/crontab-api/Cargo.toml +++ b/crontab-api/Cargo.toml @@ -13,3 +13,5 @@ shuttle-axum = "0.16.0" tokio = "1.28.0" serde = "1.0.162" shuttle-persist = "0.16.0" +chrono = "0.4.24" +cron = "0.12.0" diff --git a/crontab-api/src/main.rs b/crontab-api/src/main.rs index 43717ea5..63b1f2de 100644 --- a/crontab-api/src/main.rs +++ b/crontab-api/src/main.rs @@ -1,15 +1,63 @@ +use std::str::FromStr; use std::sync::Arc; use axum::Router; +use chrono::Utc; +use cron::Schedule; +use serde::{Deserialize, Serialize}; use shuttle_persist::PersistInstance; +use tokio::time::sleep; mod router; +#[derive(Debug, Serialize, Deserialize)] +pub struct Job { + schedule: String, + url: String, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Crontab { + jobs: Vec, +} + pub struct CrontabService { router: Router, persist: PersistInstance, } +impl CrontabService { + async fn start(&self) { + let tab: Crontab = self.persist.load("crontab").unwrap(); + + for Job { schedule, url } in tab.jobs { + let schedule = Schedule::from_str(&schedule).unwrap(); + let job = CronJob { schedule, url }; + + // TODO: spawn blocking thread on tokio::runtime::handle + } + } +} + +pub struct CronJob { + schedule: Schedule, + url: String, +} + +impl CronJob { + async fn start(&self) { + while let Some(next_run) = self.schedule.upcoming(Utc).next() { + let next_run_in = next_run + .signed_duration_since(chrono::offset::Utc::now()) + .to_std() + .unwrap(); + sleep(next_run_in).await; + + // TODO: Use reqwest to call url. + } + } +} + pub struct AppState { persist: PersistInstance, } @@ -21,6 +69,7 @@ impl shuttle_runtime::Service for CrontabService { let serve_router = axum::Server::bind(&addr).serve(router.into_make_service()); + // TODO: Use a channel (?) to be notified about updates to the persisted crontab & rerun `CrontabService.start()` tokio::select!( // _ = self.discord_bot.run() => {}, _ = serve_router => {} @@ -34,6 +83,7 @@ impl shuttle_runtime::Service for CrontabService { async fn init( #[shuttle_persist::Persist] persist: PersistInstance, ) -> Result { + // TODO: `persist` should probably be a channel so `CrontabService` can listen for updates and rerun its `start` method? let app_state = Arc::new(AppState { persist: persist.clone(), }); diff --git a/crontab-api/src/router.rs b/crontab-api/src/router.rs index c64cc781..e1e0cfee 100644 --- a/crontab-api/src/router.rs +++ b/crontab-api/src/router.rs @@ -8,7 +8,7 @@ use axum::{extract::Form, Router}; use serde::Deserialize; use shuttle_runtime::tracing::info; -use crate::AppState; +use crate::{AppState, Crontab, Job}; pub fn build_router(app_state: Arc) -> Router { Router::new() @@ -21,22 +21,18 @@ pub async fn hello_world() -> impl IntoResponse { (StatusCode::OK, "Hello world!").into_response() } -#[derive(Debug, Deserialize)] -pub struct Schedule { - schedule: String, - url: String, -} - pub async fn set_schedule( State(app_state): State>, - Form(schedule): Form, + Form(job): Form, ) -> impl IntoResponse { - info!("Setting schedule: {:?}", schedule); + info!("Setting new job: {:?}", job); + + let mut crontab: Crontab = app_state.persist.load("crontab").unwrap(); - app_state.persist.save("some", "key"); + crontab.jobs.push(job); + info!("Updating state: {:?}", &crontab); - let val: String = app_state.persist.load("some").unwrap(); - info!("Got state: {:?}", val); + app_state.persist.save("crontab", crontab).unwrap(); StatusCode::OK } From d75767f6e2fce1b664796862474a1accc2b1cf66 Mon Sep 17 00:00:00 2001 From: morlinbrot Date: Tue, 9 May 2023 10:09:01 +0200 Subject: [PATCH 048/239] Fix unwrap panics --- crontab-api/src/main.rs | 12 ++++++------ crontab-api/src/router.rs | 5 ++++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/crontab-api/src/main.rs b/crontab-api/src/main.rs index 63b1f2de..69666d5a 100644 --- a/crontab-api/src/main.rs +++ b/crontab-api/src/main.rs @@ -28,13 +28,13 @@ pub struct CrontabService { impl CrontabService { async fn start(&self) { - let tab: Crontab = self.persist.load("crontab").unwrap(); + if let Ok(tab) = self.persist.load::("crontab") { + for Job { schedule, url } in tab.jobs { + let schedule = Schedule::from_str(&schedule).unwrap(); + let job = CronJob { schedule, url }; - for Job { schedule, url } in tab.jobs { - let schedule = Schedule::from_str(&schedule).unwrap(); - let job = CronJob { schedule, url }; - - // TODO: spawn blocking thread on tokio::runtime::handle + // TODO: spawn blocking thread on tokio::runtime::handle + } } } } diff --git a/crontab-api/src/router.rs b/crontab-api/src/router.rs index e1e0cfee..6e87c71c 100644 --- a/crontab-api/src/router.rs +++ b/crontab-api/src/router.rs @@ -27,7 +27,10 @@ pub async fn set_schedule( ) -> impl IntoResponse { info!("Setting new job: {:?}", job); - let mut crontab: Crontab = app_state.persist.load("crontab").unwrap(); + let mut crontab = match app_state.persist.load::("crontab") { + Ok(tab) => tab, + Err(_) => Crontab { jobs: vec![] }, + }; crontab.jobs.push(job); info!("Updating state: {:?}", &crontab); From d5a61a832af56a18879801cb697d2dd66fdb1081 Mon Sep 17 00:00:00 2001 From: morlinbrot Date: Tue, 9 May 2023 10:27:46 +0200 Subject: [PATCH 049/239] Add README.md --- crontab-api/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 crontab-api/README.md diff --git a/crontab-api/README.md b/crontab-api/README.md new file mode 100644 index 00000000..99b04118 --- /dev/null +++ b/crontab-api/README.md @@ -0,0 +1,13 @@ +# crontab-api + +A service that calls URLs at specified cron intervals. + +The service exposes a `/set-schedule` endpoint that accepts a schedule and a URL as form data and persists the cron job with `shuttle_persist` between runs. + +``` +curl -v http://localhost:8000/set-schedule\ + -H "Content-Type: application/x-www-form-urlencoded"\ + -d "schedule='*/2 * * * * *'&url='example.com'" +``` + +The example demonstrates implementation of a custom service with [`shuttle_runtime::Service`](https://docs.shuttle.rs/examples/custom-service), usage of [`shuttle_persist`](https://docs.shuttle.rs/resources/shuttle-persist), and how to run an `axum::Server` and a number of cron job processes in parallel. From c1f1ad4148452a47dc0aa83b25c5bbb292fc0123 Mon Sep 17 00:00:00 2001 From: morlinbrot Date: Wed, 10 May 2023 13:09:21 +0200 Subject: [PATCH 050/239] Add CronRunner to run jobs --- crontab-api/src/main.rs | 111 ++++++++++++++++++++++++++------------ crontab-api/src/router.rs | 19 ++----- 2 files changed, 81 insertions(+), 49 deletions(-) diff --git a/crontab-api/src/main.rs b/crontab-api/src/main.rs index 69666d5a..6ec38638 100644 --- a/crontab-api/src/main.rs +++ b/crontab-api/src/main.rs @@ -6,46 +6,42 @@ use chrono::Utc; use cron::Schedule; use serde::{Deserialize, Serialize}; use shuttle_persist::PersistInstance; -use tokio::time::sleep; +use shuttle_runtime::tracing::info; +use tokio::{ + sync::mpsc::{self, Receiver, Sender}, + time::sleep, +}; mod router; #[derive(Debug, Serialize, Deserialize)] -pub struct Job { +pub struct RawJob { schedule: String, url: String, } #[derive(Debug, Serialize, Deserialize)] pub struct Crontab { - jobs: Vec, -} - -pub struct CrontabService { - router: Router, - persist: PersistInstance, -} - -impl CrontabService { - async fn start(&self) { - if let Ok(tab) = self.persist.load::("crontab") { - for Job { schedule, url } in tab.jobs { - let schedule = Schedule::from_str(&schedule).unwrap(); - let job = CronJob { schedule, url }; - - // TODO: spawn blocking thread on tokio::runtime::handle - } - } - } + jobs: Vec, } +#[derive(Debug)] pub struct CronJob { schedule: Schedule, url: String, } impl CronJob { - async fn start(&self) { + fn from_raw(raw: &RawJob) -> Self { + let schedule = Schedule::from_str(&raw.schedule).expect("Failed to parse schedule"); + Self { + schedule, + url: raw.url.clone(), + } + } + + async fn run(&self) { + info!("Running job for: {:?}", self.url); while let Some(next_run) = self.schedule.upcoming(Utc).next() { let next_run_in = next_run .signed_duration_since(chrono::offset::Utc::now()) @@ -53,27 +49,72 @@ impl CronJob { .unwrap(); sleep(next_run_in).await; + info!("Calling {}", self.url); // TODO: Use reqwest to call url. } } } -pub struct AppState { +pub struct CronRunner { persist: PersistInstance, + receiver: Receiver, +} + +impl CronRunner { + async fn run_jobs(&mut self) { + if let Ok(tab) = self.persist.load::("crontab") { + info!("Found {} jobs", tab.jobs.len()); + for raw in tab.jobs { + info!("Starting job: {:?}", raw); + let job = CronJob::from_raw(&raw); + + tokio::spawn(async move { + job.run().await; + }); + } + } + + while let Some(raw) = self.receiver.recv().await { + info!("Channel received: {:?}", raw); + let mut crontab = match self.persist.load::("crontab") { + Ok(tab) => tab, + Err(_) => Crontab { jobs: vec![] }, + }; + + let job = CronJob::from_raw(&raw); + + crontab.jobs.push(raw); + + info!("Persisting: {:?}", crontab); + self.persist.save("crontab", crontab).unwrap(); + + // Spawn new job + tokio::spawn(async move { + job.run().await; + }); + } + } +} + +pub struct CrontabService { + router: Router, + runner: CronRunner, +} + +pub struct AppState { + sender: Sender, } #[shuttle_runtime::async_trait] impl shuttle_runtime::Service for CrontabService { async fn bind(mut self, addr: std::net::SocketAddr) -> Result<(), shuttle_runtime::Error> { let router = self.router; + let mut runner = self.runner; - let serve_router = axum::Server::bind(&addr).serve(router.into_make_service()); + let server = axum::Server::bind(&addr); - // TODO: Use a channel (?) to be notified about updates to the persisted crontab & rerun `CrontabService.start()` - tokio::select!( - // _ = self.discord_bot.run() => {}, - _ = serve_router => {} - ); + let (_runner_hdl, _axum_hdl) = + tokio::join!(runner.run_jobs(), server.serve(router.into_make_service())); Ok(()) } @@ -83,11 +124,11 @@ impl shuttle_runtime::Service for CrontabService { async fn init( #[shuttle_persist::Persist] persist: PersistInstance, ) -> Result { - // TODO: `persist` should probably be a channel so `CrontabService` can listen for updates and rerun its `start` method? - let app_state = Arc::new(AppState { - persist: persist.clone(), - }); - let router = router::build_router(app_state); + let (sender, receiver) = mpsc::channel(32); + + let runner = CronRunner { persist, receiver }; + let state = Arc::new(AppState { sender }); + let router = router::build_router(state); - Ok(CrontabService { router, persist }) + Ok(CrontabService { router, runner }) } diff --git a/crontab-api/src/router.rs b/crontab-api/src/router.rs index 6e87c71c..4b6b7875 100644 --- a/crontab-api/src/router.rs +++ b/crontab-api/src/router.rs @@ -5,10 +5,9 @@ use axum::http::StatusCode; use axum::response::IntoResponse; use axum::routing::{get, post}; use axum::{extract::Form, Router}; -use serde::Deserialize; use shuttle_runtime::tracing::info; -use crate::{AppState, Crontab, Job}; +use crate::{AppState, RawJob}; pub fn build_router(app_state: Arc) -> Router { Router::new() @@ -22,20 +21,12 @@ pub async fn hello_world() -> impl IntoResponse { } pub async fn set_schedule( - State(app_state): State>, - Form(job): Form, + State(state): State>, + Form(job): Form, ) -> impl IntoResponse { - info!("Setting new job: {:?}", job); + info!("Accepted new job: {:?}", job); - let mut crontab = match app_state.persist.load::("crontab") { - Ok(tab) => tab, - Err(_) => Crontab { jobs: vec![] }, - }; - - crontab.jobs.push(job); - info!("Updating state: {:?}", &crontab); - - app_state.persist.save("crontab", crontab).unwrap(); + state.sender.send(job).await.unwrap(); StatusCode::OK } From 5c9957be928985f3683080f7230dd89dd36c3b33 Mon Sep 17 00:00:00 2001 From: morlinbrot Date: Wed, 10 May 2023 15:54:11 +0200 Subject: [PATCH 051/239] Move CronService to its own crate --- crontab-api/Cargo.toml | 8 +-- crontab-api/src/main.rs | 135 ++------------------------------------ crontab-api/src/router.rs | 32 --------- 3 files changed, 6 insertions(+), 169 deletions(-) delete mode 100644 crontab-api/src/router.rs diff --git a/crontab-api/Cargo.toml b/crontab-api/Cargo.toml index da81a58a..f5dd2b60 100644 --- a/crontab-api/Cargo.toml +++ b/crontab-api/Cargo.toml @@ -7,11 +7,7 @@ publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +shuttle-crontab = { version = "0.15.0", path = "../../services/shuttle-crontab" } +shuttle-persist = "0.16.0" shuttle-runtime = "0.16.0" -axum = "0.6.18" -shuttle-axum = "0.16.0" tokio = "1.28.0" -serde = "1.0.162" -shuttle-persist = "0.16.0" -chrono = "0.4.24" -cron = "0.12.0" diff --git a/crontab-api/src/main.rs b/crontab-api/src/main.rs index 6ec38638..a4bcd36e 100644 --- a/crontab-api/src/main.rs +++ b/crontab-api/src/main.rs @@ -1,134 +1,7 @@ -use std::str::FromStr; -use std::sync::Arc; - -use axum::Router; -use chrono::Utc; -use cron::Schedule; -use serde::{Deserialize, Serialize}; -use shuttle_persist::PersistInstance; -use shuttle_runtime::tracing::info; -use tokio::{ - sync::mpsc::{self, Receiver, Sender}, - time::sleep, -}; - -mod router; - -#[derive(Debug, Serialize, Deserialize)] -pub struct RawJob { - schedule: String, - url: String, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct Crontab { - jobs: Vec, -} - -#[derive(Debug)] -pub struct CronJob { - schedule: Schedule, - url: String, -} - -impl CronJob { - fn from_raw(raw: &RawJob) -> Self { - let schedule = Schedule::from_str(&raw.schedule).expect("Failed to parse schedule"); - Self { - schedule, - url: raw.url.clone(), - } - } - - async fn run(&self) { - info!("Running job for: {:?}", self.url); - while let Some(next_run) = self.schedule.upcoming(Utc).next() { - let next_run_in = next_run - .signed_duration_since(chrono::offset::Utc::now()) - .to_std() - .unwrap(); - sleep(next_run_in).await; - - info!("Calling {}", self.url); - // TODO: Use reqwest to call url. - } - } -} - -pub struct CronRunner { - persist: PersistInstance, - receiver: Receiver, -} - -impl CronRunner { - async fn run_jobs(&mut self) { - if let Ok(tab) = self.persist.load::("crontab") { - info!("Found {} jobs", tab.jobs.len()); - for raw in tab.jobs { - info!("Starting job: {:?}", raw); - let job = CronJob::from_raw(&raw); - - tokio::spawn(async move { - job.run().await; - }); - } - } - - while let Some(raw) = self.receiver.recv().await { - info!("Channel received: {:?}", raw); - let mut crontab = match self.persist.load::("crontab") { - Ok(tab) => tab, - Err(_) => Crontab { jobs: vec![] }, - }; - - let job = CronJob::from_raw(&raw); - - crontab.jobs.push(raw); - - info!("Persisting: {:?}", crontab); - self.persist.save("crontab", crontab).unwrap(); - - // Spawn new job - tokio::spawn(async move { - job.run().await; - }); - } - } -} - -pub struct CrontabService { - router: Router, - runner: CronRunner, -} - -pub struct AppState { - sender: Sender, -} - -#[shuttle_runtime::async_trait] -impl shuttle_runtime::Service for CrontabService { - async fn bind(mut self, addr: std::net::SocketAddr) -> Result<(), shuttle_runtime::Error> { - let router = self.router; - let mut runner = self.runner; - - let server = axum::Server::bind(&addr); - - let (_runner_hdl, _axum_hdl) = - tokio::join!(runner.run_jobs(), server.serve(router.into_make_service())); - - Ok(()) - } -} +use shuttle_crontab::{CrontabService, ShuttleCrontab}; +use shuttle_persist::{Persist, PersistInstance}; #[shuttle_runtime::main] -async fn init( - #[shuttle_persist::Persist] persist: PersistInstance, -) -> Result { - let (sender, receiver) = mpsc::channel(32); - - let runner = CronRunner { persist, receiver }; - let state = Arc::new(AppState { sender }); - let router = router::build_router(state); - - Ok(CrontabService { router, runner }) +async fn crontab(#[Persist] persist: PersistInstance) -> ShuttleCrontab { + CrontabService::new(persist) } diff --git a/crontab-api/src/router.rs b/crontab-api/src/router.rs deleted file mode 100644 index 4b6b7875..00000000 --- a/crontab-api/src/router.rs +++ /dev/null @@ -1,32 +0,0 @@ -use std::sync::Arc; - -use axum::extract::State; -use axum::http::StatusCode; -use axum::response::IntoResponse; -use axum::routing::{get, post}; -use axum::{extract::Form, Router}; -use shuttle_runtime::tracing::info; - -use crate::{AppState, RawJob}; - -pub fn build_router(app_state: Arc) -> Router { - Router::new() - .route("/", get(hello_world)) - .route("/set-schedule", post(set_schedule)) - .with_state(app_state) -} - -pub async fn hello_world() -> impl IntoResponse { - (StatusCode::OK, "Hello world!").into_response() -} - -pub async fn set_schedule( - State(state): State>, - Form(job): Form, -) -> impl IntoResponse { - info!("Accepted new job: {:?}", job); - - state.sender.send(job).await.unwrap(); - - StatusCode::OK -} From cb6306050289fc08614668ec0d456c563b79a962 Mon Sep 17 00:00:00 2001 From: morlinbrot Date: Thu, 11 May 2023 10:23:52 +0200 Subject: [PATCH 052/239] Update request.sh with usable url --- crontab-api/request.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crontab-api/request.sh b/crontab-api/request.sh index 2eb9ac9f..bcc38a63 100644 --- a/crontab-api/request.sh +++ b/crontab-api/request.sh @@ -1,5 +1,5 @@ SCHEDULE="*/2 * * * * *" -URL="example.com" +URL="https://example.com" curl -v http://localhost:8000/set-schedule\ -H "Content-Type: application/x-www-form-urlencoded"\ From 1633d462c70e544bde0a43b8cfb2d5d22dc96fc9 Mon Sep 17 00:00:00 2001 From: morlinbrot Date: Thu, 11 May 2023 11:05:54 +0200 Subject: [PATCH 053/239] Make use of CrontabService::new now accepting a router --- crontab-api/Cargo.toml | 1 + crontab-api/README.md | 8 ++++++-- crontab-api/request.sh | 2 +- crontab-api/src/main.rs | 8 +++++++- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/crontab-api/Cargo.toml b/crontab-api/Cargo.toml index f5dd2b60..b144186d 100644 --- a/crontab-api/Cargo.toml +++ b/crontab-api/Cargo.toml @@ -7,6 +7,7 @@ publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +axum = "0.6.18" shuttle-crontab = { version = "0.15.0", path = "../../services/shuttle-crontab" } shuttle-persist = "0.16.0" shuttle-runtime = "0.16.0" diff --git a/crontab-api/README.md b/crontab-api/README.md index 99b04118..257a28a1 100644 --- a/crontab-api/README.md +++ b/crontab-api/README.md @@ -2,7 +2,8 @@ A service that calls URLs at specified cron intervals. -The service exposes a `/set-schedule` endpoint that accepts a schedule and a URL as form data and persists the cron job with `shuttle_persist` between runs. +The service exposes a `/set-schedule` endpoint that accepts a schedule and a URL +as form data and persists the cron job with `shuttle_persist` between runs. ``` curl -v http://localhost:8000/set-schedule\ @@ -10,4 +11,7 @@ curl -v http://localhost:8000/set-schedule\ -d "schedule='*/2 * * * * *'&url='example.com'" ``` -The example demonstrates implementation of a custom service with [`shuttle_runtime::Service`](https://docs.shuttle.rs/examples/custom-service), usage of [`shuttle_persist`](https://docs.shuttle.rs/resources/shuttle-persist), and how to run an `axum::Server` and a number of cron job processes in parallel. +Internally, `CrontabService` implements a custom service with +[`shuttle_runtime::Service`](https://docs.shuttle.rs/examples/custom-service), +usage of [`shuttle_persist`](https://docs.shuttle.rs/resources/shuttle-persist), +and sets up an `axum::Server` that sends jobs to a `CronRunner`. diff --git a/crontab-api/request.sh b/crontab-api/request.sh index bcc38a63..1d491630 100644 --- a/crontab-api/request.sh +++ b/crontab-api/request.sh @@ -1,6 +1,6 @@ SCHEDULE="*/2 * * * * *" URL="https://example.com" -curl -v http://localhost:8000/set-schedule\ +curl -v http://localhost:8000/crontab/set\ -H "Content-Type: application/x-www-form-urlencoded"\ -d "schedule=$SCHEDULE&url=$URL" diff --git a/crontab-api/src/main.rs b/crontab-api/src/main.rs index a4bcd36e..9c9f1327 100644 --- a/crontab-api/src/main.rs +++ b/crontab-api/src/main.rs @@ -1,7 +1,13 @@ +use axum::{response::IntoResponse, routing::get, Router}; use shuttle_crontab::{CrontabService, ShuttleCrontab}; use shuttle_persist::{Persist, PersistInstance}; +async fn hello_crontab() -> impl IntoResponse { + "Hello there, try making a POST request to '/crontab/set' to create a new job.".to_string() +} + #[shuttle_runtime::main] async fn crontab(#[Persist] persist: PersistInstance) -> ShuttleCrontab { - CrontabService::new(persist) + let router = Router::new().route("/", get(hello_crontab)); + CrontabService::new(persist, router) } From 58a1556476f97b7ab43fea9a7d115c6f61b3c9e0 Mon Sep 17 00:00:00 2001 From: morlinbrot Date: Thu, 11 May 2023 18:54:58 +0200 Subject: [PATCH 054/239] Adapt to changes in shuttle_crontab for code review part 1 --- crontab-api/request.sh | 2 +- crontab-api/src/main.rs | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/crontab-api/request.sh b/crontab-api/request.sh index 1d491630..9b045d66 100644 --- a/crontab-api/request.sh +++ b/crontab-api/request.sh @@ -1,5 +1,5 @@ SCHEDULE="*/2 * * * * *" -URL="https://example.com" +URL="http://localhost:8000/trigger-me" curl -v http://localhost:8000/crontab/set\ -H "Content-Type: application/x-www-form-urlencoded"\ diff --git a/crontab-api/src/main.rs b/crontab-api/src/main.rs index 9c9f1327..93ca1c7b 100644 --- a/crontab-api/src/main.rs +++ b/crontab-api/src/main.rs @@ -6,8 +6,14 @@ async fn hello_crontab() -> impl IntoResponse { "Hello there, try making a POST request to '/crontab/set' to create a new job.".to_string() } +async fn trigger_me() -> impl IntoResponse { + "Triggered by the crontab service".to_string() +} + #[shuttle_runtime::main] async fn crontab(#[Persist] persist: PersistInstance) -> ShuttleCrontab { - let router = Router::new().route("/", get(hello_crontab)); + let router = Router::new() + .route("/", get(hello_crontab)) + .route("/trigger-me", get(trigger_me)); CrontabService::new(persist, router) } From 6681065a1d82009d4b79ca8f90ffd83b412dddcd Mon Sep 17 00:00:00 2001 From: oddgrd <29732646+oddgrd@users.noreply.github.com> Date: Fri, 12 May 2023 15:59:34 +0200 Subject: [PATCH 055/239] chore: bump salvo --- salvo/hello-world/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index d15a50f8..8f4e7ad5 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -salvo = "0.37.5" +salvo = "0.41.0" shuttle-salvo = { version = "0.16.0" } shuttle-runtime = { version = "0.16.0" } tokio = { version = "1.26.0" } From 63d2447e5132fcbe9f67d7d02a009d1b489b17b6 Mon Sep 17 00:00:00 2001 From: morlinbrot Date: Mon, 15 May 2023 10:12:54 +0200 Subject: [PATCH 056/239] Refactor back into an example --- crontab-api/Cargo.toml | 4 + crontab-api/README.md | 16 +++- crontab-api/src/error.rs | 20 ++++ crontab-api/src/lib.rs | 193 ++++++++++++++++++++++++++++++++++++++ crontab-api/src/main.rs | 3 +- crontab-api/src/router.rs | 29 ++++++ 6 files changed, 259 insertions(+), 6 deletions(-) create mode 100644 crontab-api/src/error.rs create mode 100644 crontab-api/src/lib.rs create mode 100644 crontab-api/src/router.rs diff --git a/crontab-api/Cargo.toml b/crontab-api/Cargo.toml index b144186d..ed499726 100644 --- a/crontab-api/Cargo.toml +++ b/crontab-api/Cargo.toml @@ -8,6 +8,10 @@ publish = false [dependencies] axum = "0.6.18" +chrono = "0.4.24" +cron = "0.12.0" +reqwest = "0.11.17" +serde = "1.0.163" shuttle-crontab = { version = "0.15.0", path = "../../services/shuttle-crontab" } shuttle-persist = "0.16.0" shuttle-runtime = "0.16.0" diff --git a/crontab-api/README.md b/crontab-api/README.md index 257a28a1..9a93c9de 100644 --- a/crontab-api/README.md +++ b/crontab-api/README.md @@ -5,13 +5,19 @@ A service that calls URLs at specified cron intervals. The service exposes a `/set-schedule` endpoint that accepts a schedule and a URL as form data and persists the cron job with `shuttle_persist` between runs. +Internally, `CrontabService` implements a custom service with +[`shuttle_runtime::Service`](https://docs.shuttle.rs/examples/custom-service), +usage of [`shuttle_persist`](https://docs.shuttle.rs/resources/shuttle-persist), +and sets up an `axum::Server` that sends jobs to a `CronRunner`. + +# Usage +Run `cargo shuttle run` to spin up the service locally. + +Fire a request to the `set-schedule` URL specifying a new cron job. Use `request.sh` +for a quick example or use the below snippet: + ``` curl -v http://localhost:8000/set-schedule\ -H "Content-Type: application/x-www-form-urlencoded"\ -d "schedule='*/2 * * * * *'&url='example.com'" ``` - -Internally, `CrontabService` implements a custom service with -[`shuttle_runtime::Service`](https://docs.shuttle.rs/examples/custom-service), -usage of [`shuttle_persist`](https://docs.shuttle.rs/resources/shuttle-persist), -and sets up an `axum::Server` that sends jobs to a `CronRunner`. diff --git a/crontab-api/src/error.rs b/crontab-api/src/error.rs new file mode 100644 index 00000000..5d3856d8 --- /dev/null +++ b/crontab-api/src/error.rs @@ -0,0 +1,20 @@ +use axum::{ + http::StatusCode, + response::{IntoResponse, Response}, +}; +use shuttle_persist::PersistError; + +#[derive(Debug)] +pub(crate) struct CrontabServiceError(PersistError); + +impl From for CrontabServiceError { + fn from(err: PersistError) -> Self { + Self(err) + } +} + +impl IntoResponse for CrontabServiceError { + fn into_response(self) -> Response { + (StatusCode::INTERNAL_SERVER_ERROR).into_response() + } +} diff --git a/crontab-api/src/lib.rs b/crontab-api/src/lib.rs new file mode 100644 index 00000000..a124c141 --- /dev/null +++ b/crontab-api/src/lib.rs @@ -0,0 +1,193 @@ +//! Shuttle service integration for cron. +//! +//! ## Example +//! Create a new `CrontabService` by providing a `shuttle_persist::PersistInstance` +//! and an `axum::Router` +//! +//! ```rust,no_run +//! use shuttle_crontab::{CrontabService, ShuttleCrontab}; +//! use shuttle_persist::{Persist, PersistInstance}; +//! +//! #[shuttle_runtime::main] +//! async fn crontab(#[Persist] persist: PersistInstance) -> ShuttleCrontab { +//! let router = Router::new().route("/trigger-me", get(|| async { +//! "Triggered by the crontab service".to_string() +//! })); +//! CrontabService::new(persist, router) +//! } +//! ``` +//! +//! This will create an `axum::Service` with a cron runner mounted at `/crontab`. +//! The `/crontab/set` endpoint accepts a schedule and a URL as form data and +//! persists the cron job with `shuttle_persist` between runs. +//! +//! Call the endpoint with something like the following to set up a +//!``` +//!curl -v http://localhost:8000/crontab/set\ +//! -H "Content-Type: application/x-www-form-urlencoded"\ +//! -d "schedule='*/2 * * * * *'&url='http://localhost:8000/trigger-me'" +//!``` +//! +use std::str::FromStr; +use std::sync::Arc; + +use axum::Router; +use chrono::Utc; +use cron::Schedule; +use router::make_router; +use serde::{Deserialize, Serialize}; +use shuttle_persist::PersistInstance; +use shuttle_runtime::tracing::{debug, info}; +use tokio::{ + sync::mpsc::{self, Receiver, Sender}, + sync::oneshot, + time::sleep, +}; + +mod error; +use error::CrontabServiceError; + +mod router; + +pub type ShuttleCrontab = Result; + +type Responder = oneshot::Sender>; + +#[derive(Debug, Serialize, Deserialize)] +pub struct RawJob { + schedule: String, + url: String, +} + +#[derive(Debug)] +enum Msg { + NewJob(RawJob, Responder<()>), +} + +#[derive(Debug, Serialize, Deserialize)] +struct Crontab { + jobs: Vec, +} + +#[derive(Debug)] +struct CronJob { + schedule: Schedule, + url: String, +} + +impl CronJob { + async fn run(&self) { + debug!("Running job for: {}", self.url); + while let Some(next_run) = self.schedule.upcoming(Utc).next() { + let next_run_in = next_run + .signed_duration_since(chrono::offset::Utc::now()) + .to_std() + .unwrap(); + sleep(next_run_in).await; + + let res = reqwest::get(self.url.clone()).await.unwrap(); + info!("Called {} with response {}", self.url, res.status()); + } + } +} + +impl From<&RawJob> for CronJob { + fn from(raw: &RawJob) -> Self { + let schedule = Schedule::from_str(&raw.schedule).expect("Failed to parse schedule"); + Self { + schedule, + url: raw.url.clone(), + } + } +} + +struct CronRunner { + persist: PersistInstance, + receiver: Receiver, +} + +impl CronRunner { + async fn run_jobs(&mut self) { + if let Ok(tab) = self.persist.load::("crontab") { + debug!("Found {} jobs", tab.jobs.len()); + for raw in tab.jobs { + debug!("Starting job: {:?}", raw); + let job = CronJob::from(&raw); + + tokio::spawn(async move { + job.run().await; + }); + } + } else { + info!("Didn't find any jobs. POST to /crontab/set to create one."); + } + + while let Some(msg) = self.receiver.recv().await { + let (raw, resp) = match msg { + Msg::NewJob(raw, resp) => (raw, resp), + }; + debug!("Channel received: {:?}", raw); + + let mut crontab = match self.persist.load::("crontab") { + Ok(tab) => tab, + Err(_) => Crontab { jobs: vec![] }, + }; + + let job = CronJob::from(&raw); + + crontab.jobs.push(raw); + + debug!("Persisting {:?} jobs", crontab.jobs.len()); + let res = self.persist.save("crontab", crontab).map_err(From::from); + let _ = resp.send(res); + + tokio::spawn(async move { + job.run().await; + }); + } + } +} + +pub struct CrontabService { + router: Router, + runner: CronRunner, +} + +struct CrontabServiceState { + sender: Sender, +} + +impl CrontabService { + pub fn new( + persist: PersistInstance, + user_router: Router, + ) -> Result { + let (sender, receiver) = mpsc::channel(32); + + let cron_runner = CronRunner { persist, receiver }; + let cron_state = Arc::new(CrontabServiceState { sender }); + let cron_router = make_router(cron_state); + + let router = user_router.nest("/crontab", cron_router); + + Ok(Self { + router, + runner: cron_runner, + }) + } +} + +#[shuttle_runtime::async_trait] +impl shuttle_runtime::Service for CrontabService { + async fn bind(mut self, addr: std::net::SocketAddr) -> Result<(), shuttle_runtime::Error> { + let router = self.router; + let mut runner = self.runner; + + let server = axum::Server::bind(&addr); + + let (_runner_hdl, _axum_hdl) = + tokio::join!(runner.run_jobs(), server.serve(router.into_make_service())); + + Ok(()) + } +} diff --git a/crontab-api/src/main.rs b/crontab-api/src/main.rs index 93ca1c7b..37fa47a5 100644 --- a/crontab-api/src/main.rs +++ b/crontab-api/src/main.rs @@ -1,7 +1,8 @@ use axum::{response::IntoResponse, routing::get, Router}; -use shuttle_crontab::{CrontabService, ShuttleCrontab}; use shuttle_persist::{Persist, PersistInstance}; +use crontab_api::{CrontabService, ShuttleCrontab}; + async fn hello_crontab() -> impl IntoResponse { "Hello there, try making a POST request to '/crontab/set' to create a new job.".to_string() } diff --git a/crontab-api/src/router.rs b/crontab-api/src/router.rs new file mode 100644 index 00000000..6b7e1afe --- /dev/null +++ b/crontab-api/src/router.rs @@ -0,0 +1,29 @@ +use std::sync::Arc; + +use axum::extract::State; +use axum::response::IntoResponse; +use axum::routing::post; +use axum::{extract::Form, Router}; +use shuttle_runtime::tracing::debug; +use tokio::sync::oneshot; + +use crate::error::CrontabServiceError; +use crate::{CrontabServiceState, Msg, RawJob}; + +pub(crate) fn make_router(cron_state: Arc) -> Router { + Router::new() + .route("/set", post(set_schedule)) + .with_state(cron_state) +} + +async fn set_schedule( + State(state): State>, + Form(job): Form, +) -> Result { + debug!("Accepted new job: {:?}", job); + let (tx, rx) = oneshot::channel(); + + state.sender.send(Msg::NewJob(job, tx)).await.unwrap(); + + rx.await.expect("Channel transmission failed") +} From 3dff726ea7b8ffa7d2e5f6389699379734ed5896 Mon Sep 17 00:00:00 2001 From: morlinbrot Date: Mon, 15 May 2023 10:26:08 +0200 Subject: [PATCH 057/239] Rename to request-scheduler --- crontab-api/README.md | 23 ----------------- .../request-scheduler}/Cargo.toml | 3 +-- custom/request-scheduler/README.md | 25 +++++++++++++++++++ .../request-scheduler}/request.sh | 0 .../request-scheduler}/src/error.rs | 0 .../request-scheduler}/src/lib.rs | 0 .../request-scheduler}/src/main.rs | 5 +++- .../request-scheduler}/src/router.rs | 0 8 files changed, 30 insertions(+), 26 deletions(-) delete mode 100644 crontab-api/README.md rename {crontab-api => custom/request-scheduler}/Cargo.toml (76%) create mode 100644 custom/request-scheduler/README.md rename {crontab-api => custom/request-scheduler}/request.sh (100%) rename {crontab-api => custom/request-scheduler}/src/error.rs (100%) rename {crontab-api => custom/request-scheduler}/src/lib.rs (100%) rename {crontab-api => custom/request-scheduler}/src/main.rs (78%) rename {crontab-api => custom/request-scheduler}/src/router.rs (100%) diff --git a/crontab-api/README.md b/crontab-api/README.md deleted file mode 100644 index 9a93c9de..00000000 --- a/crontab-api/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# crontab-api - -A service that calls URLs at specified cron intervals. - -The service exposes a `/set-schedule` endpoint that accepts a schedule and a URL -as form data and persists the cron job with `shuttle_persist` between runs. - -Internally, `CrontabService` implements a custom service with -[`shuttle_runtime::Service`](https://docs.shuttle.rs/examples/custom-service), -usage of [`shuttle_persist`](https://docs.shuttle.rs/resources/shuttle-persist), -and sets up an `axum::Server` that sends jobs to a `CronRunner`. - -# Usage -Run `cargo shuttle run` to spin up the service locally. - -Fire a request to the `set-schedule` URL specifying a new cron job. Use `request.sh` -for a quick example or use the below snippet: - -``` -curl -v http://localhost:8000/set-schedule\ - -H "Content-Type: application/x-www-form-urlencoded"\ - -d "schedule='*/2 * * * * *'&url='example.com'" -``` diff --git a/crontab-api/Cargo.toml b/custom/request-scheduler/Cargo.toml similarity index 76% rename from crontab-api/Cargo.toml rename to custom/request-scheduler/Cargo.toml index ed499726..58fdcbcc 100644 --- a/crontab-api/Cargo.toml +++ b/custom/request-scheduler/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "crontab-api" +name = "request-scheduler" version = "0.1.0" edition = "2021" publish = false @@ -12,7 +12,6 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-crontab = { version = "0.15.0", path = "../../services/shuttle-crontab" } shuttle-persist = "0.16.0" shuttle-runtime = "0.16.0" tokio = "1.28.0" diff --git a/custom/request-scheduler/README.md b/custom/request-scheduler/README.md new file mode 100644 index 00000000..c66fd782 --- /dev/null +++ b/custom/request-scheduler/README.md @@ -0,0 +1,25 @@ +# request-scheduler + +A service that calls URLs at specified cron-style intervals. + +The service exposes a `/set-schedule` endpoint that accepts a schedule and a URL +as form data and persists a job tuple `(schedule, url)` with `shuttle_persist` +between runs, e.g. will pick up existing jobs after being restarted. + +Internally, `CrontabService` implements a custom service with +[`shuttle_runtime::Service`](https://docs.shuttle.rs/examples/custom-service), +uses [`shuttle_persist`](https://docs.shuttle.rs/resources/shuttle-persist), +and sets up an [`axum::Server`](https://github.com/tokio-rs/axum) that sends +jobs to a `CronRunner`. + +# Usage +Run `cargo shuttle run` to spin up the service locally. + +Fire a POST request to the `set-schedule` URL to create a new cron job. Use +`request.sh` for a quick example or use the below snippet: + +``` +curl -v http://localhost:8000/set-schedule\ + -H "Content-Type: application/x-www-form-urlencoded"\ + -d "schedule='*/2 * * * * *'&url='example.com'" +``` diff --git a/crontab-api/request.sh b/custom/request-scheduler/request.sh similarity index 100% rename from crontab-api/request.sh rename to custom/request-scheduler/request.sh diff --git a/crontab-api/src/error.rs b/custom/request-scheduler/src/error.rs similarity index 100% rename from crontab-api/src/error.rs rename to custom/request-scheduler/src/error.rs diff --git a/crontab-api/src/lib.rs b/custom/request-scheduler/src/lib.rs similarity index 100% rename from crontab-api/src/lib.rs rename to custom/request-scheduler/src/lib.rs diff --git a/crontab-api/src/main.rs b/custom/request-scheduler/src/main.rs similarity index 78% rename from crontab-api/src/main.rs rename to custom/request-scheduler/src/main.rs index 37fa47a5..7c8f47d3 100644 --- a/crontab-api/src/main.rs +++ b/custom/request-scheduler/src/main.rs @@ -1,7 +1,7 @@ use axum::{response::IntoResponse, routing::get, Router}; use shuttle_persist::{Persist, PersistInstance}; -use crontab_api::{CrontabService, ShuttleCrontab}; +use request_scheduler::{CrontabService, ShuttleCrontab}; async fn hello_crontab() -> impl IntoResponse { "Hello there, try making a POST request to '/crontab/set' to create a new job.".to_string() @@ -13,8 +13,11 @@ async fn trigger_me() -> impl IntoResponse { #[shuttle_runtime::main] async fn crontab(#[Persist] persist: PersistInstance) -> ShuttleCrontab { + // A userland router, so to speak. `CrontabService` has its own router + // defined in `router.rs`. let router = Router::new() .route("/", get(hello_crontab)) .route("/trigger-me", get(trigger_me)); + CrontabService::new(persist, router) } diff --git a/crontab-api/src/router.rs b/custom/request-scheduler/src/router.rs similarity index 100% rename from crontab-api/src/router.rs rename to custom/request-scheduler/src/router.rs From 4e43e381589222df24b55c5f0449a3fc936809dc Mon Sep 17 00:00:00 2001 From: morlinbrot Date: Mon, 15 May 2023 10:31:22 +0200 Subject: [PATCH 058/239] Update documentation --- custom/request-scheduler/README.md | 2 +- custom/request-scheduler/src/main.rs | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/custom/request-scheduler/README.md b/custom/request-scheduler/README.md index c66fd782..6aa918c1 100644 --- a/custom/request-scheduler/README.md +++ b/custom/request-scheduler/README.md @@ -19,7 +19,7 @@ Fire a POST request to the `set-schedule` URL to create a new cron job. Use `request.sh` for a quick example or use the below snippet: ``` -curl -v http://localhost:8000/set-schedule\ +curl -v http://localhost:8000/crontab/set\ -H "Content-Type: application/x-www-form-urlencoded"\ -d "schedule='*/2 * * * * *'&url='example.com'" ``` diff --git a/custom/request-scheduler/src/main.rs b/custom/request-scheduler/src/main.rs index 7c8f47d3..7ff2893c 100644 --- a/custom/request-scheduler/src/main.rs +++ b/custom/request-scheduler/src/main.rs @@ -13,11 +13,13 @@ async fn trigger_me() -> impl IntoResponse { #[shuttle_runtime::main] async fn crontab(#[Persist] persist: PersistInstance) -> ShuttleCrontab { - // A userland router, so to speak. `CrontabService` has its own router + // A userland router, so to speak. Will be the primary router mounted at "/", + // while the `CrontabService` has its own router mounted at "/crontab", as // defined in `router.rs`. - let router = Router::new() + // See lib.rs for more documentation. + let user_router = Router::new() .route("/", get(hello_crontab)) .route("/trigger-me", get(trigger_me)); - CrontabService::new(persist, router) + CrontabService::new(persist, user_router) } From 579ef1c2f3457c6cf033af859fb276ce7743a122 Mon Sep 17 00:00:00 2001 From: morlinbrot Date: Mon, 15 May 2023 10:34:34 +0200 Subject: [PATCH 059/239] Delete old crontab example --- crontab/Cargo.toml | 16 ------------ crontab/README.md | 6 ----- crontab/src/main.rs | 59 --------------------------------------------- 3 files changed, 81 deletions(-) delete mode 100644 crontab/Cargo.toml delete mode 100644 crontab/README.md delete mode 100644 crontab/src/main.rs diff --git a/crontab/Cargo.toml b/crontab/Cargo.toml deleted file mode 100644 index 2275580e..00000000 --- a/crontab/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "crontab" -version = "0.1.0" -edition = "2021" -publish = false - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -async-trait = "0.1.68" -chrono = "0.4.24" -cron = "0.12.0" -shuttle-runtime = "0.15.0" -shuttle-service = "0.15.0" -tokio = "1.28.0" -tracing = "0.1.37" diff --git a/crontab/README.md b/crontab/README.md deleted file mode 100644 index 85aecc64..00000000 --- a/crontab/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# crontab service example - -A service that runs a job at the specified cron intervals. - -This example demonstrates how to implement `shuttle_runtime::Service` for your own type to set up a custom service without any web framework. - diff --git a/crontab/src/main.rs b/crontab/src/main.rs deleted file mode 100644 index 2445ea49..00000000 --- a/crontab/src/main.rs +++ /dev/null @@ -1,59 +0,0 @@ -use chrono::Utc; -use std::{future::Future, str::FromStr}; -use tokio::time::sleep; -use tracing::info; - -use cron::Schedule; -use shuttle_runtime::{async_trait, Service}; - -// "Run every 2 seconds" -const SCHEDULE: &str = "*/2 * * * * *"; - -// The function that will be run. -async fn my_job() { - let now = chrono::offset::Utc::now(); - info!("It is {}", now.format("%Y-%m-%d %H:%M:%S")); -} - -pub struct CronService { - schedule: Schedule, - job: fn() -> F, -} - -impl CronService { - async fn start(&self) { - while let Some(next_run) = self.schedule.upcoming(Utc).next() { - let next_run_in = next_run - .signed_duration_since(chrono::offset::Utc::now()) - .to_std() - .unwrap(); - sleep(next_run_in).await; - (self.job)().await; - } - } -} - -#[async_trait] -impl Service for CronService -where - F: Future + Send + Sync + 'static, -{ - async fn bind( - mut self, - _addr: std::net::SocketAddr, - ) -> Result<(), shuttle_service::error::Error> { - self.start().await; - - Ok(()) - } -} - -#[shuttle_runtime::main] -async fn init( -) -> Result + Send + 'static>, shuttle_service::Error> { - let schedule = Schedule::from_str(SCHEDULE).unwrap(); - Ok(CronService { - schedule, - job: my_job, - }) -} From 5881b392f08c848ebd468e8cc56c2b496f46d424 Mon Sep 17 00:00:00 2001 From: morlinbrot Date: Mon, 15 May 2023 10:38:28 +0200 Subject: [PATCH 060/239] Clean up --- custom/request-scheduler/README.md | 10 +++++----- custom/request-scheduler/src/lib.rs | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/custom/request-scheduler/README.md b/custom/request-scheduler/README.md index 6aa918c1..b43b27b8 100644 --- a/custom/request-scheduler/README.md +++ b/custom/request-scheduler/README.md @@ -2,9 +2,9 @@ A service that calls URLs at specified cron-style intervals. -The service exposes a `/set-schedule` endpoint that accepts a schedule and a URL -as form data and persists a job tuple `(schedule, url)` with `shuttle_persist` -between runs, e.g. will pick up existing jobs after being restarted. +The service exposes a `/crontab/set` endpoint that accepts a schedule and a URL +as form data and persists jobs with `shuttle_persist` between runs, e.g. it will +pick up existing jobs after being restarted. Internally, `CrontabService` implements a custom service with [`shuttle_runtime::Service`](https://docs.shuttle.rs/examples/custom-service), @@ -16,10 +16,10 @@ jobs to a `CronRunner`. Run `cargo shuttle run` to spin up the service locally. Fire a POST request to the `set-schedule` URL to create a new cron job. Use -`request.sh` for a quick example or use the below snippet: +the provided `request.sh` for a quick example or the below snippet: ``` curl -v http://localhost:8000/crontab/set\ -H "Content-Type: application/x-www-form-urlencoded"\ - -d "schedule='*/2 * * * * *'&url='example.com'" + -d "schedule='*/2 * * * * *'&url='http://localhost:8000/trigger-me'" ``` diff --git a/custom/request-scheduler/src/lib.rs b/custom/request-scheduler/src/lib.rs index a124c141..19a66afc 100644 --- a/custom/request-scheduler/src/lib.rs +++ b/custom/request-scheduler/src/lib.rs @@ -22,6 +22,7 @@ //! persists the cron job with `shuttle_persist` between runs. //! //! Call the endpoint with something like the following to set up a +//! //!``` //!curl -v http://localhost:8000/crontab/set\ //! -H "Content-Type: application/x-www-form-urlencoded"\ From a4d5b8e457496f7394d3679bbec4c71699ebb893 Mon Sep 17 00:00:00 2001 From: Joshua Mo <102877324+joshua-mo-143@users.noreply.github.com> Date: Fri, 19 May 2023 07:07:23 +0100 Subject: [PATCH 061/239] feat: saas example (#50) Co-authored-by: Joshua Mo --- fullstack-templates/saas/.eslintrc.json | 3 + fullstack-templates/saas/.gitignore | 35 + fullstack-templates/saas/Mainpage.png | Bin 0 -> 85319 bytes fullstack-templates/saas/README.md | 45 + fullstack-templates/saas/backend/.gitignore | 6 + fullstack-templates/saas/backend/Cargo.toml | 28 + .../migrations/20230415200225_schema.sql | 53 + fullstack-templates/saas/backend/src/auth.rs | 131 + .../saas/backend/src/customers.rs | 144 + .../saas/backend/src/dashboard.rs | 82 + fullstack-templates/saas/backend/src/deals.rs | 137 + fullstack-templates/saas/backend/src/mail.rs | 43 + fullstack-templates/saas/backend/src/main.rs | 95 + .../saas/backend/src/payments.rs | 96 + .../saas/backend/src/router.rs | 74 + fullstack-templates/saas/next.config.js | 12 + fullstack-templates/saas/package-lock.json | 4459 +++++++++++++++++ fullstack-templates/saas/package.json | 38 + fullstack-templates/saas/postcss.config.js | 6 + fullstack-templates/saas/public/favicon.ico | Bin 0 -> 25931 bytes fullstack-templates/saas/public/next.svg | 1 + fullstack-templates/saas/public/vercel.svg | 1 + .../saas/src/components/AuthedLayout.tsx | 27 + .../src/components/CustomerSingleModal.tsx | 86 + .../src/components/DealSingleModal copy.tsx | 77 + .../saas/src/components/Layout.tsx | 32 + .../saas/src/components/Metrics.tsx | 24 + .../saas/src/components/Navigation.tsx | 22 + .../saas/src/components/RecentSales.tsx | 40 + .../saas/src/components/SalesChart.tsx | 59 + .../saas/src/components/Sidebar.tsx | 7 + .../saas/src/components/TopClients.tsx | 34 + .../saas/src/components/navbar.tsx | 104 + fullstack-templates/saas/src/pages/_app.tsx | 9 + .../saas/src/pages/_document.tsx | 13 + .../src/pages/dashboard/customers/[id].tsx | 105 + .../src/pages/dashboard/customers/create.tsx | 192 + .../src/pages/dashboard/customers/edit.tsx | 85 + .../src/pages/dashboard/customers/index.tsx | 140 + .../saas/src/pages/dashboard/deals/create.tsx | 167 + .../saas/src/pages/dashboard/deals/edit.tsx | 85 + .../saas/src/pages/dashboard/deals/index.tsx | 149 + .../saas/src/pages/dashboard/index.tsx | 79 + .../dashboard/upgrade/checkout/failed.tsx | 16 + .../dashboard/upgrade/checkout/index.tsx | 248 + .../dashboard/upgrade/checkout/success.tsx | 16 + .../src/pages/dashboard/upgrade/index.tsx | 89 + fullstack-templates/saas/src/pages/forgot.tsx | 86 + fullstack-templates/saas/src/pages/index.tsx | 61 + fullstack-templates/saas/src/pages/login.tsx | 199 + .../saas/src/pages/pricing.tsx | 57 + .../saas/src/pages/register.tsx | 284 ++ .../saas/src/styles/globals.css | 10 + fullstack-templates/saas/src/zustandStore.ts | 23 + fullstack-templates/saas/tailwind.config.js | 13 + fullstack-templates/saas/tsconfig.json | 23 + 56 files changed, 8150 insertions(+) create mode 100644 fullstack-templates/saas/.eslintrc.json create mode 100644 fullstack-templates/saas/.gitignore create mode 100644 fullstack-templates/saas/Mainpage.png create mode 100644 fullstack-templates/saas/README.md create mode 100644 fullstack-templates/saas/backend/.gitignore create mode 100644 fullstack-templates/saas/backend/Cargo.toml create mode 100644 fullstack-templates/saas/backend/migrations/20230415200225_schema.sql create mode 100644 fullstack-templates/saas/backend/src/auth.rs create mode 100644 fullstack-templates/saas/backend/src/customers.rs create mode 100644 fullstack-templates/saas/backend/src/dashboard.rs create mode 100644 fullstack-templates/saas/backend/src/deals.rs create mode 100644 fullstack-templates/saas/backend/src/mail.rs create mode 100644 fullstack-templates/saas/backend/src/main.rs create mode 100644 fullstack-templates/saas/backend/src/payments.rs create mode 100644 fullstack-templates/saas/backend/src/router.rs create mode 100644 fullstack-templates/saas/next.config.js create mode 100644 fullstack-templates/saas/package-lock.json create mode 100644 fullstack-templates/saas/package.json create mode 100644 fullstack-templates/saas/postcss.config.js create mode 100644 fullstack-templates/saas/public/favicon.ico create mode 100644 fullstack-templates/saas/public/next.svg create mode 100644 fullstack-templates/saas/public/vercel.svg create mode 100644 fullstack-templates/saas/src/components/AuthedLayout.tsx create mode 100644 fullstack-templates/saas/src/components/CustomerSingleModal.tsx create mode 100644 fullstack-templates/saas/src/components/DealSingleModal copy.tsx create mode 100644 fullstack-templates/saas/src/components/Layout.tsx create mode 100644 fullstack-templates/saas/src/components/Metrics.tsx create mode 100644 fullstack-templates/saas/src/components/Navigation.tsx create mode 100644 fullstack-templates/saas/src/components/RecentSales.tsx create mode 100644 fullstack-templates/saas/src/components/SalesChart.tsx create mode 100644 fullstack-templates/saas/src/components/Sidebar.tsx create mode 100644 fullstack-templates/saas/src/components/TopClients.tsx create mode 100644 fullstack-templates/saas/src/components/navbar.tsx create mode 100644 fullstack-templates/saas/src/pages/_app.tsx create mode 100644 fullstack-templates/saas/src/pages/_document.tsx create mode 100644 fullstack-templates/saas/src/pages/dashboard/customers/[id].tsx create mode 100644 fullstack-templates/saas/src/pages/dashboard/customers/create.tsx create mode 100644 fullstack-templates/saas/src/pages/dashboard/customers/edit.tsx create mode 100644 fullstack-templates/saas/src/pages/dashboard/customers/index.tsx create mode 100644 fullstack-templates/saas/src/pages/dashboard/deals/create.tsx create mode 100644 fullstack-templates/saas/src/pages/dashboard/deals/edit.tsx create mode 100644 fullstack-templates/saas/src/pages/dashboard/deals/index.tsx create mode 100644 fullstack-templates/saas/src/pages/dashboard/index.tsx create mode 100644 fullstack-templates/saas/src/pages/dashboard/upgrade/checkout/failed.tsx create mode 100644 fullstack-templates/saas/src/pages/dashboard/upgrade/checkout/index.tsx create mode 100644 fullstack-templates/saas/src/pages/dashboard/upgrade/checkout/success.tsx create mode 100644 fullstack-templates/saas/src/pages/dashboard/upgrade/index.tsx create mode 100644 fullstack-templates/saas/src/pages/forgot.tsx create mode 100644 fullstack-templates/saas/src/pages/index.tsx create mode 100644 fullstack-templates/saas/src/pages/login.tsx create mode 100644 fullstack-templates/saas/src/pages/pricing.tsx create mode 100644 fullstack-templates/saas/src/pages/register.tsx create mode 100644 fullstack-templates/saas/src/styles/globals.css create mode 100644 fullstack-templates/saas/src/zustandStore.ts create mode 100644 fullstack-templates/saas/tailwind.config.js create mode 100644 fullstack-templates/saas/tsconfig.json diff --git a/fullstack-templates/saas/.eslintrc.json b/fullstack-templates/saas/.eslintrc.json new file mode 100644 index 00000000..15b1ed91 --- /dev/null +++ b/fullstack-templates/saas/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "next" +} diff --git a/fullstack-templates/saas/.gitignore b/fullstack-templates/saas/.gitignore new file mode 100644 index 00000000..8f322f0d --- /dev/null +++ b/fullstack-templates/saas/.gitignore @@ -0,0 +1,35 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/fullstack-templates/saas/Mainpage.png b/fullstack-templates/saas/Mainpage.png new file mode 100644 index 0000000000000000000000000000000000000000..027b26a4b9b6422835321d41590e0886048d7476 GIT binary patch literal 85319 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≀$ex?>3 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

+gxzzMjhBATuT@eWD3bMCXGh*4a_rkLM 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 literal 0 HcmV?d00001 diff --git a/fullstack-templates/saas/README.md b/fullstack-templates/saas/README.md new file mode 100644 index 00000000..2c735c33 --- /dev/null +++ b/fullstack-templates/saas/README.md @@ -0,0 +1,45 @@ +## Shuttle SaaS Example +### Introduction +This repo is meant to serve as a SaaS template with a Next.js Typescript frontend and a Rust backend. The design of the template internally is based on a sales-oriented Customer Relationship Management (CRM) tool where users will be able to view their customers, sales records as well as some analytics. + +### Features +- Take subscription payments with Stripe +- Email session-based login +- Mailgun (email subscription, welcome email etc) +- Pre-configured frontend routes for easy transition +- Examples of how to implement simple dashboard analytics + +### Pre-requisites + +* Rust + +* Node.js/NPM. + +* Typescript. + +* [cargo-shuttle](https://www.shuttle.rs) + +### Instructions for Usage + +* Fork or clone the repo, then navigate to the folder where you cloned the repo: + +``` + git clone https://github.com/joshua-mo-143/shuttle-saas-example.git + cd shuttle-saas-example +``` + +* Run `npm i` to install the dependencies on the frontend. + +* Set your secrets in the Secrets.toml file at the `Cargo.toml` level of your backend folder (any that are unset will default to "None" to stop the web service from automatically crashing but some services may not work!) + +* Run `npm run dev` and go to [http://localhost:8000](http://localhost:8000) once the app has built and you should see the following: + +![Main page for Next.js + Shuttle Saas Template](./Mainpage.png) + +### Troubleshooting + +* If you change the migrations after running locally or deploying, you will need to go into the database itself and delete the tables. You can do this easily with something like [psql](https://www.postgresql.org/docs/current/app-psql.html) or [pgAdmin](https://www.pgadmin.org/). + +* If connecting to external services like Stripe doesn't work, try checking your Secrets.toml file. + +* Shuttle connects by default to port 8000 - if you're currently already using something at port 8000, you can add the `--port ` to the `cargo shuttle run` command to change this. \ No newline at end of file diff --git a/fullstack-templates/saas/backend/.gitignore b/fullstack-templates/saas/backend/.gitignore new file mode 100644 index 00000000..421b0be5 --- /dev/null +++ b/fullstack-templates/saas/backend/.gitignore @@ -0,0 +1,6 @@ +target/ +Shuttle.toml +Secrets.toml +Secrets.dev.toml +test_sub.sh +public/ \ No newline at end of file diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml new file mode 100644 index 00000000..bad1434c --- /dev/null +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "api" +version = "0.1.0" +edition = "2021" +publish = false +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +async-stripe = { version = "0.21.0", features = ["runtime-tokio-hyper"] } +axum = "0.6.15" +axum-extra = { version = "0.7.3", features = ["cookie-private"] } +axum-macros = "0.3.7" +bcrypt = "0.14.0" +http = "0.2.9" +lettre = "0.10.4" +rand = "0.8.5" +reqwest = "0.11.16" +serde = { version = "1.0.160", features = ["derive"] } +shuttle-axum = "0.16.0" +shuttle-runtime = "0.16.0" +shuttle-secrets = "0.16.0" +shuttle-shared-db = { version = "0.16.0", features = ["postgres"] } +shuttle-static-folder = "0.16.0" +sqlx = { version = "0.6.3", features = ["runtime-tokio-native-tls", "postgres", "time"] } +time = { version = "0.3.20", features = ["serde"] } +tokio = "1.27.0" +tower = "0.4.13" +tower-http = { version = "0.4.0", features = ["cors", "fs"] } diff --git a/fullstack-templates/saas/backend/migrations/20230415200225_schema.sql b/fullstack-templates/saas/backend/migrations/20230415200225_schema.sql new file mode 100644 index 00000000..f4727434 --- /dev/null +++ b/fullstack-templates/saas/backend/migrations/20230415200225_schema.sql @@ -0,0 +1,53 @@ +CREATE TABLE IF NOT EXISTS users ( + id SERIAL PRIMARY KEY, + name VARCHAR(100) NOT NULL, + email VARCHAR(255) NOT NULL, + password VARCHAR NOT NULL, + created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + ROLE VARCHAR NOT NULL DEFAULT 'user' +); + +CREATE TABLE IF NOT EXISTS sessions ( + id SERIAL PRIMARY KEY, + session_id VARCHAR NOT NULL UNIQUE, + user_id int NOT NULL UNIQUE, + expires TIMESTAMP WITH TIME ZONE, + CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(id) +); + +CREATE TABLE IF NOT EXISTS customers ( + id SERIAL PRIMARY KEY, + firstName VARCHAR NOT NULL, + lastName VARCHAR NOT NULL, + email VARCHAR NOT NULL, + phone VARCHAR(14) NOT NULL, + priority SMALLINT NOT NULL CHECK (priority >= 1 AND priority <= 5), + owner_id int NOT NULL, + is_archived BOOLEAN DEFAULT FALSE, + created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT FK_customer FOREIGN KEY(owner_id) REFERENCES users(id) +); + +CREATE TABLE IF NOT EXISTS deals ( + id SERIAL PRIMARY KEY, + estimate_worth INT, + actual_worth INT, + status VARCHAR NOT NULL, + closed VARCHAR NOT NULL, + created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + last_updated TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + customer_id int NOT NULL, + owner_id int NOT NULL, + CONSTRAINT FK_deal FOREIGN KEY(owner_id) REFERENCES users(id), + CONSTRAINT FK_owner FOREIGN KEY(owner_id) REFERENCES users(id), + is_archived BOOLEAN DEFAULT FALSE +); + +CREATE TABLE IF NOT EXISTS apikeys ( + id SERIAL PRIMARY KEY, + api_key VARCHAR NOT NULL, + owner_id int, + created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + last_used TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT FK_customer FOREIGN KEY (owner_id) REFERENCES users(id) +); \ No newline at end of file diff --git a/fullstack-templates/saas/backend/src/auth.rs b/fullstack-templates/saas/backend/src/auth.rs new file mode 100644 index 00000000..231fc82d --- /dev/null +++ b/fullstack-templates/saas/backend/src/auth.rs @@ -0,0 +1,131 @@ +use axum::middleware::Next; +use axum::{ + extract::State, + http::{Request, StatusCode}, + response::{IntoResponse, Response}, + Json, +}; +use axum_extra::extract::cookie::{Cookie, PrivateCookieJar, SameSite}; +use serde::Deserialize; +use sqlx::Row; +use time::Duration; + +use crate::AppState; + +#[derive(Deserialize)] +pub struct RegisterDetails { + name: String, + email: String, + password: String, +} + +#[derive(Deserialize)] +pub struct LoginDetails { + email: String, + password: String, +} + +pub async fn register( + State(state): State, + Json(newuser): Json, +) -> impl IntoResponse { + let hashed_password = bcrypt::hash(newuser.password, 10).unwrap(); + + let query = sqlx::query("INSERT INTO users (name, email, password) values ($1, $2, $3)") + .bind(newuser.name) + .bind(newuser.email) + .bind(hashed_password) + .execute(&state.postgres); + + match query.await { + Ok(_) => (StatusCode::CREATED, "Account created!".to_string()).into_response(), + Err(e) => ( + StatusCode::BAD_REQUEST, + format!("Something went wrong: {e}"), + ) + .into_response(), + } +} + +pub async fn login( + State(state): State, + jar: PrivateCookieJar, + Json(login): Json, +) -> Result<(PrivateCookieJar, StatusCode), StatusCode> { + let query = sqlx::query("SELECT * FROM users WHERE email = $1") + .bind(&login.email) + .fetch_one(&state.postgres); + + match query.await { + Ok(res) => { + if bcrypt::verify(login.password, res.get("password")).is_err() { + return Err(StatusCode::BAD_REQUEST); + } + let session_id = rand::random::().to_string(); + + sqlx::query("INSERT INTO sessions (session_id, user_id) VALUES ($1, $2) ON CONFLICT (user_id) DO UPDATE SET session_id = EXCLUDED.session_id") + .bind(&session_id) + .bind(res.get::("id")) + .execute(&state.postgres) + .await + .expect("Couldn't insert session :("); + + let cookie = Cookie::build("foo", session_id) + .secure(true) + .same_site(SameSite::Strict) + .http_only(true) + .path("/") + .max_age(Duration::WEEK) + .finish(); + + Ok((jar.add(cookie), StatusCode::OK)) + } + + Err(_) => Err(StatusCode::BAD_REQUEST), + } +} + +pub async fn logout( + State(state): State, + jar: PrivateCookieJar, +) -> Result { + let Some(cookie) = jar.get("sessionid").map(|cookie| cookie.value().to_owned()) else { + return Ok(jar) + }; + + let query = sqlx::query("DELETE FROM sessions WHERE session_id = $1") + .bind(cookie) + .execute(&state.postgres); + + match query.await { + Ok(_) => Ok(jar.remove(Cookie::named("foo"))), + Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR), + } +} + +pub async fn validate_session( + jar: PrivateCookieJar, + State(state): State, + request: Request, + next: Next, +) -> (PrivateCookieJar, Response) { + let Some(cookie) = jar.get("foo").map(|cookie| cookie.value().to_owned()) else { + + println!("Couldn't find a cookie in the jar"); + return (jar,(StatusCode::FORBIDDEN, "Forbidden!".to_string()).into_response()) + }; + + let find_session = + sqlx::query("SELECT * FROM sessions WHERE session_id = $1 AND expires > CURRENT_TIMESTAMP") + .bind(cookie) + .execute(&state.postgres) + .await; + + match find_session { + Ok(_) => (jar, next.run(request).await), + Err(_) => ( + jar, + (StatusCode::FORBIDDEN, "Forbidden!".to_string()).into_response(), + ), + } +} diff --git a/fullstack-templates/saas/backend/src/customers.rs b/fullstack-templates/saas/backend/src/customers.rs new file mode 100644 index 00000000..4ca03c1d --- /dev/null +++ b/fullstack-templates/saas/backend/src/customers.rs @@ -0,0 +1,144 @@ +use axum::response::IntoResponse; +use axum::{ + extract::{Path, State}, + http::StatusCode, + Json, +}; +use serde::{Deserialize, Serialize}; + +use crate::AppState; + +#[derive(Deserialize, sqlx::FromRow, Serialize)] +pub struct Customer { + pub id: i32, + pub firstname: String, + pub lastname: String, + pub email: String, + pub phone: String, + pub priority: i16, +} + +#[derive(Deserialize, sqlx::FromRow, Serialize)] +pub struct CustomerNames { + pub id: i32, + pub customer_name: String, +} + +#[derive(Deserialize)] +pub struct UserRequest { + pub email: String, +} + +#[derive(Deserialize)] +pub struct ChangeRequest { + pub columnname: String, + pub new_value: String, + pub email: String, +} + +#[derive(Serialize, Deserialize)] +#[allow(non_snake_case)] +pub struct NewCustomer { + pub firstName: String, + pub lastName: String, + pub email: String, + pub phone: String, + pub priority: i32, + pub userEmail: String, +} + +pub async fn get_all_customers( + State(state): State, + Json(req): Json, +) -> Result>, impl IntoResponse> { + match sqlx::query_as::<_, Customer>("SELECT id, firstName, lastName, email, phone, priority FROM customers WHERE owner_id = (SELECT id FROM users WHERE email = $1)") + .bind(req.email) + .fetch_all(&state.postgres) + .await { + Ok(res) => Ok(Json(res)), + Err(err) => Err((StatusCode::INTERNAL_SERVER_ERROR, err.to_string()).into_response()) + } +} + +pub async fn get_one_customer( + State(state): State, + Path(id): Path, + Json(req): Json, +) -> Result, impl IntoResponse> { + let id = id.trim().parse::().unwrap(); + + match sqlx::query_as::<_, Customer>("SELECT id, firstname, lastname, email, phone, priority FROM customers WHERE owner_id = (SELECT id FROM users WHERE email = $1) AND id = $2") + .bind(req.email) + .bind(id) + .fetch_one(&state.postgres) + .await { + Ok(res) => Ok(Json(res)), + Err(err) => Err((StatusCode::INTERNAL_SERVER_ERROR, err.to_string()).into_response()) + } +} + +pub async fn create_customer( + State(state): State, + Json(req): Json, +) -> Result { + match sqlx::query("INSERT INTO CUSTOMERS (firstname, lastname, email, phone, priority, owner_id) VALUES ($1, $2, $3, $4, $5, (SELECT id FROM users WHERE email = $6))") + .bind(req.firstName) + .bind(req.lastName) + .bind(req.email) + .bind(req.phone) + .bind(req.priority) + .bind(req.userEmail) + .execute(&state.postgres) + .await { + Ok(_) => Ok(StatusCode::OK), + Err(err) => Err((StatusCode::INTERNAL_SERVER_ERROR, err.to_string()).into_response()) + } +} + +pub async fn edit_customer( + State(state): State, + Path(id): Path, + Json(req): Json, +) -> Result { + let Ok(_) = sqlx::query("UPDATE customers SET $1 = $2 WHERE owner_id = (SELECT id FROM users WHERE email = $3) AND id = $4") + .bind(req.columnname) + .bind(req.new_value) + .bind(req.email) + .bind(id.parse::().unwrap()) + .fetch_one(&state.postgres) + .await else { + return Err(StatusCode::INTERNAL_SERVER_ERROR) + }; + + Ok(StatusCode::OK) +} + +pub async fn destroy_customer( + State(state): State, + Path(id): Path, + Json(req): Json, +) -> Result { + let id = id.trim().parse::().unwrap(); + + match sqlx::query("DELETE FROM customers WHERE owner_id = (SELECT id FROM users WHERE email = $1) AND id = $2") + .bind(req.email) + .bind(id) + .execute(&state.postgres) + .await { + Ok(_) => Ok(StatusCode::OK), + Err(err) => Err((StatusCode::INTERNAL_SERVER_ERROR, err.to_string()).into_response()) + } +} + +pub async fn get_customer_names( + State(state): State, + Json(req): Json, +) -> Result>, impl IntoResponse> { + match sqlx::query_as::<_, CustomerNames>("SELECT id, CONCAT(firstName, ' ', lastName) AS customer_name FROM customers WHERE owner_id = (SELECT id FROM users WHERE email = $1)") + .bind(req.email) + .fetch_all(&state.postgres) + .await { + Ok(res) => Ok(Json(res)), + Err(err) => Err((StatusCode::INTERNAL_SERVER_ERROR, err.to_string())) + } +} diff --git a/fullstack-templates/saas/backend/src/dashboard.rs b/fullstack-templates/saas/backend/src/dashboard.rs new file mode 100644 index 00000000..5430334f --- /dev/null +++ b/fullstack-templates/saas/backend/src/dashboard.rs @@ -0,0 +1,82 @@ +use axum::{extract::State, http::StatusCode, response::IntoResponse, Json}; +use serde::{Deserialize, Serialize}; +// use time::Date; + +use crate::AppState; + +#[derive(Deserialize, Serialize)] +pub struct DashboardData { + sales_deals_info: SalesDealsInfo, + sales_per_day_info: Vec, +} + +#[derive(Deserialize, Serialize, sqlx::FromRow)] +pub struct SalesDealsInfo { + open: i64, + ready: i64, + awaitingresponse: i64, + closed: i64, + total_amt_closed: Option, +} + +#[derive(Deserialize, Serialize, sqlx::FromRow)] +pub struct SalesPerDayInfo { + date: String, + sales_total: i64, +} + +#[derive(Deserialize, Serialize, sqlx::FromRow)] +pub struct CustomerInfo { + status: String, + recordcount: i32, +} + +#[derive(Deserialize)] +pub struct UserRequest { + pub email: String, +} + +pub async fn get_dashboard_data( + State(state): State, + Json(req): Json, +) -> Result, impl IntoResponse> { + let sales_deals_info = match sqlx::query_as::<_, SalesDealsInfo>( + "SELECT + COUNT(*) FILTER (WHERE status = 'open') AS open, + COUNT(*) FILTER (WHERE status = 'ready') AS ready, + COUNT(*) FILTER (WHERE status = 'awaitingresponse') AS awaitingresponse, + COUNT(*) FILTER (WHERE status = 'closed') AS closed, + SUM(estimate_worth) FILTER (where status = 'closed') AS total_amt_closed + FROM deals + WHERE owner_id = (SELECT id FROM users WHERE email = $1)", + ) + .bind(&req.email.to_string()) + .fetch_one(&state.postgres) + .await + { + Ok(res) => res, + Err(err) => return Err((StatusCode::INTERNAL_SERVER_ERROR, err.to_string())), + }; + + let sales_per_day_info = match sqlx::query_as::<_, SalesPerDayInfo>( + "SELECT + TO_CHAR(DATE(deals.last_updated), 'yyyy-mm-dd') AS date, + SUM(estimate_worth) AS sales_total + FROM deals + WHERE status = 'closed' + GROUP BY deals.last_updated + ", + ) + .bind(req.email) + .fetch_all(&state.postgres) + .await + { + Ok(res) => res, + Err(err) => return Err((StatusCode::INTERNAL_SERVER_ERROR, err.to_string())), + }; + + Ok(Json(DashboardData { + sales_deals_info, + sales_per_day_info, + })) +} diff --git a/fullstack-templates/saas/backend/src/deals.rs b/fullstack-templates/saas/backend/src/deals.rs new file mode 100644 index 00000000..79d21ec8 --- /dev/null +++ b/fullstack-templates/saas/backend/src/deals.rs @@ -0,0 +1,137 @@ +use axum::{ + extract::{Path, State}, + http::StatusCode, + response::IntoResponse, + Json, +}; +use serde::{Deserialize, Serialize}; + +use crate::AppState; + +#[derive(Deserialize, Serialize, sqlx::FromRow)] +pub struct Deal { + pub id: i32, + pub estimate_worth: i32, + pub status: String, + pub closed: String, + pub customer_name: String, +} + +#[derive(Deserialize, Serialize, sqlx::FromRow)] +pub struct DealDetailed { + pub id: i32, + pub estimate_worth: i32, + pub actual_worth: Option, + pub status: String, + pub closed: String, + pub customer_id: String, +} + +#[derive(Deserialize)] +pub struct UserRequest { + pub email: String, +} + +#[derive(Deserialize)] +pub struct NewDeal { + pub estimatedworth: i32, + pub cust_id: i32, + pub useremail: String, +} + +#[derive(Deserialize)] +pub struct ChangeRequest { + pub new_value: String, + pub email: String, +} + +pub async fn get_all_deals( + State(state): State, + Json(req): Json, +) -> Result>, impl IntoResponse> { + match sqlx::query_as::<_, Deal>("SELECT + d.id, + d.estimate_worth, + d.status, + d.closed, + (select concat(c.firstname, ' ', c.lastname) from customers WHERE id = d.customer_id) as customer_name + FROM deals d LEFT JOIN customers c ON d.customer_id = c.id WHERE c.owner_id = (SELECT id FROM users WHERE email = $1)") + .bind(req.email) + .fetch_all(&state.postgres) + .await { + Ok(res) => Ok(Json(res)), + Err(err) => Err((StatusCode::INTERNAL_SERVER_ERROR, err.to_string())) + + } +} + +pub async fn get_one_deal( + State(state): State, + Path(id): Path, + Json(req): Json, +) -> Result, StatusCode> { + match sqlx::query_as::<_, DealDetailed>( + "SELECT + d.id, + d.estimate_worth, + d.status, + d.closed, + (select concat(c.firstname, ' ', c.lastname) from customers WHERE id = d.customer_id) as customer_name + FROM deals d LEFT JOIN customers c ON d.customer_id = c.id WHERE c.owner_id = (SELECT id FROM users WHERE email = $1) AND d.id = $2" + ) + .bind(req.email) + .bind(id) + .fetch_one(&state.postgres) + .await { + Ok(res) => Ok(Json(res)), + Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR) + } +} + +pub async fn create_deal( + State(state): State, + Json(req): Json, +) -> Result { + let Ok(_) = sqlx::query("INSERT INTO DEALS (status, closed, customer_id, owner_id, estimate_worth) VALUES ('open', 'closed', $1, (SELECT id FROM users WHERE email = $2), $3)") + .bind(req.cust_id) + .bind(req.useremail) + .bind(req.estimatedworth) + .execute(&state.postgres) + .await else { + return Err(StatusCode::INTERNAL_SERVER_ERROR) + }; + + Ok(StatusCode::OK) +} + +pub async fn edit_deal( + State(state): State, + Path(id): Path, + Json(req): Json, +) -> Result { + match sqlx::query("UPDATE deals SET status = $1, last_updated = NOW() WHERE owner_id = (SELECT id FROM users WHERE email = $2) AND id = $3") + .bind(req.new_value) + .bind(req.email) + .bind(id) + .execute(&state.postgres) + .await { + Ok(_) => Ok(StatusCode::OK), + Err(err) => Err((StatusCode::INTERNAL_SERVER_ERROR, err.to_string())) + } +} + +pub async fn destroy_deal( + State(state): State, + Path(id): Path, + Json(req): Json, +) -> Result { + let Ok(_) = sqlx::query("DELETE FROM deals WHERE owner_id = (SELECT user_id FROM users WHERE email = $1) AND id = $2") + .bind(req.email) + .bind(id) + .execute(&state.postgres) + .await else { + return Err(StatusCode::INTERNAL_SERVER_ERROR) + }; + + Ok(StatusCode::OK) +} diff --git a/fullstack-templates/saas/backend/src/mail.rs b/fullstack-templates/saas/backend/src/mail.rs new file mode 100644 index 00000000..c8207d7a --- /dev/null +++ b/fullstack-templates/saas/backend/src/mail.rs @@ -0,0 +1,43 @@ +use axum::{extract::State, http::StatusCode, Json}; +use reqwest::Client; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +use crate::AppState; + +#[derive(Deserialize, Serialize)] +pub struct EmailRequest { + email: String, +} + +pub async fn subscribe( + State(state): State, + Json(req): Json, +) -> Result { + let ctx = Client::new(); + + let api_endpoint = format!( + "https://api.mailgun.net/v3/lists/mail@{}/members", + &state.mailgun_url + ); + + let params = sub_params(req.email); + let post = ctx + .post(api_endpoint) + .basic_auth("api", Some(&state.mailgun_key)) + .form(¶ms); + + match post.send().await { + Ok(_) => Ok(StatusCode::OK), + Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR), + } +} + +fn sub_params(recipient: String) -> HashMap<&'static str, String> { + let mut params = HashMap::new(); + + params.insert("address", recipient); + params.insert("subscribed", "True".to_string()); + + params +} diff --git a/fullstack-templates/saas/backend/src/main.rs b/fullstack-templates/saas/backend/src/main.rs new file mode 100644 index 00000000..fc28b0eb --- /dev/null +++ b/fullstack-templates/saas/backend/src/main.rs @@ -0,0 +1,95 @@ +use axum::body::{boxed, Body}; +use axum::extract::FromRef; +use axum::http::{Response, StatusCode}; +use axum::routing::get; +use axum::Router; +use axum_extra::extract::cookie::Key; +use sqlx::PgPool; +use std::path::PathBuf; +use tower::ServiceExt; +use tower_http::services::ServeDir; + +mod auth; +mod customers; +mod dashboard; +mod deals; +mod mail; +mod payments; +mod router; + +use router::create_api_router; + +#[derive(Clone)] +pub struct AppState { + pub postgres: PgPool, + pub stripe_key: String, + pub mailgun_key: String, + pub mailgun_url: String, + pub domain: String, + pub key: Key, +} + +impl FromRef for Key { + fn from_ref(state: &AppState) -> Self { + state.key.clone() + } +} + +#[shuttle_runtime::main] +async fn axum( + #[shuttle_shared_db::Postgres] postgres: PgPool, + #[shuttle_secrets::Secrets] secrets: shuttle_secrets::SecretStore, + #[shuttle_static_folder::StaticFolder(folder = "public")] public: PathBuf, +) -> shuttle_axum::ShuttleAxum { + sqlx::migrate!() + .run(&postgres) + .await + .expect("Had some errors running migrations :("); + + let (stripe_key, mailgun_key, mailgun_url, domain) = grab_secrets(secrets); + + let state = AppState { + postgres, + stripe_key, + mailgun_key, + mailgun_url, + domain, + key: Key::generate(), + }; + + let api_router = create_api_router(state); + + let router = Router::new() + .nest("/api", api_router) + .fallback_service(get(|req| async move { + match ServeDir::new(public).oneshot(req).await { + Ok(res) => res.map(boxed), + Err(err) => Response::builder() + .status(StatusCode::INTERNAL_SERVER_ERROR) + .body(boxed(Body::from(format!("error: {err}")))) + .expect("error response"), + } + })); + + Ok(router.into()) +} + +fn grab_secrets(secrets: shuttle_secrets::SecretStore) -> (String, String, String, String) { + let stripe_key = secrets + .get("STRIPE_KEY") + .unwrap_or_else(|| "None".to_string()); + + let mailgun_key = secrets + .get("MAILGUN_KEY") + .unwrap_or_else(|| "None".to_string()); + + let mailgun_url = secrets + .get("MAILGUN_URL") + .unwrap_or_else(|| "None".to_string()); + + let domain = secrets + .get("DOMAIN_URL") + .unwrap_or_else(|| "None".to_string()); + + (stripe_key, mailgun_key, mailgun_url, domain) +} diff --git a/fullstack-templates/saas/backend/src/payments.rs b/fullstack-templates/saas/backend/src/payments.rs new file mode 100644 index 00000000..85fa17de --- /dev/null +++ b/fullstack-templates/saas/backend/src/payments.rs @@ -0,0 +1,96 @@ +use axum::{extract::State, http::StatusCode, Json}; +use serde::{Deserialize, Serialize}; +use stripe::{ + AttachPaymentMethod, CardDetailsParams, CreateCustomer, CreatePaymentMethod, + CreatePaymentMethodCardUnion, CreateSubscription, CreateSubscriptionItems, Customer, + CustomerId, PaymentMethod, PaymentMethodTypeFilter, Subscription, +}; + +use crate::AppState; + +#[derive(Deserialize, Serialize)] +pub struct PaymentInfo { + name: String, + email: String, + card: String, + expyear: i32, + expmonth: i32, + cvc: String, +} + +pub async fn create_checkout( + State(state): State, + Json(req): Json, +) -> Result { + let ctx = stripe::Client::new(&state.stripe_key); + + let customer = Customer::create( + &ctx, + CreateCustomer { + name: Some(&req.name), + email: Some(&req.email), + ..Default::default() + }, + ) + .await + .expect("Had an error creating customer!"); + + println!("Made a customer"); + + let payment_method = { + let pm = PaymentMethod::create( + &ctx, + CreatePaymentMethod { + type_: Some(PaymentMethodTypeFilter::Card), + card: Some(CreatePaymentMethodCardUnion::CardDetailsParams( + CardDetailsParams { + number: req.card, + exp_year: req.expyear, + exp_month: req.expmonth, + cvc: Some(req.cvc), + }, + )), + ..Default::default() + }, + ) + .await + .expect("Had an error creating payment method!"); + + println!("Made a payment method"); + + PaymentMethod::attach( + &ctx, + &pm.id, + AttachPaymentMethod { + customer: customer.id.clone(), + }, + ) + .await + .expect("Had an error attaching the payment method!"); + + println!("Attached a payment method"); + + pm + }; + + let mut params = create_checkout_params(customer.id); + + params.default_payment_method = Some(&payment_method.id); + + let Ok(_) = Subscription::create(&ctx, params).await else { + return Err(StatusCode::INTERNAL_SERVER_ERROR) + }; + + Ok(StatusCode::OK) +} + +fn create_checkout_params(customer_id: CustomerId) -> CreateSubscription<'static> { + let mut params = CreateSubscription::new(customer_id); + params.items = Some(vec![CreateSubscriptionItems { + price: Some("price_1Mxby1I1KxxteAOMLAMeWgQD".to_string()), + ..Default::default() + }]); + params.expand = &["items", "items.data.price.product", "schedule"]; + + params +} diff --git a/fullstack-templates/saas/backend/src/router.rs b/fullstack-templates/saas/backend/src/router.rs new file mode 100644 index 00000000..97043469 --- /dev/null +++ b/fullstack-templates/saas/backend/src/router.rs @@ -0,0 +1,74 @@ +use crate::AppState; +use axum::{ + http::{self}, + middleware::{self}, + routing::{get, post}, + Router, +}; +use http::header::{ACCEPT, AUTHORIZATION, ORIGIN}; +use http::HeaderValue; +use http::Method; +use tower_http::cors::CorsLayer; + +use crate::auth::{login, logout, register, validate_session}; +use crate::customers::{ + create_customer, destroy_customer, edit_customer, get_all_customers, get_customer_names, + get_one_customer, +}; +use crate::dashboard::get_dashboard_data; +use crate::deals::{create_deal, destroy_deal, edit_deal, get_all_deals, get_one_deal}; +use crate::mail::subscribe; +use crate::payments::create_checkout; + +pub fn create_api_router(state: AppState) -> Router { + let cors = CorsLayer::new() + .allow_credentials(true) + .allow_methods(vec![Method::GET, Method::POST, Method::PUT, Method::DELETE]) + .allow_headers(vec![ORIGIN, AUTHORIZATION, ACCEPT]) + .allow_origin(state.domain.parse::().unwrap()); + + let payments_router = Router::new().route("/pay", post(create_checkout)); + + let customers_router = Router::new() + .route("/", post(get_all_customers)) + .route("/names", post(get_customer_names)) + .route( + "/:id", + post(get_one_customer) + .put(edit_customer) + .delete(destroy_customer), + ) + .route("/create", post(create_customer)); + + let deals_router = Router::new() + .route("/", post(get_all_deals)) + .route( + "/:id", + post(get_one_deal).put(edit_deal).delete(destroy_deal), + ) + .route("/create", post(create_deal)); + + let auth_router = Router::new() + .route("/register", post(register)) + .route("/login", post(login)) + .route("/logout", get(logout)); + + Router::new() + .nest("/customers", customers_router) + .nest("/deals", deals_router) + .nest("/payments", payments_router) + .route("/dashboard", post(get_dashboard_data)) + .layer(middleware::from_fn_with_state( + state.clone(), + validate_session, + )) + .nest("/auth", auth_router) + .route("/subscribe", post(subscribe)) + .route("/health", get(hello_world)) + .with_state(state) + .layer(cors) +} + +pub async fn hello_world() -> &'static str { + "Hello world!" +} diff --git a/fullstack-templates/saas/next.config.js b/fullstack-templates/saas/next.config.js new file mode 100644 index 00000000..7951173e --- /dev/null +++ b/fullstack-templates/saas/next.config.js @@ -0,0 +1,12 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: true, + output: "export", + trailingSlash: true, + distDir: "./backend/public", + images: { + unoptimized: true, + }, +} + +module.exports = nextConfig diff --git a/fullstack-templates/saas/package-lock.json b/fullstack-templates/saas/package-lock.json new file mode 100644 index 00000000..5e734fb4 --- /dev/null +++ b/fullstack-templates/saas/package-lock.json @@ -0,0 +1,4459 @@ +{ + "name": "rustcrm", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "rustcrm", + "version": "0.1.0", + "dependencies": { + "@faker-js/faker": "^7.6.0", + "@fortawesome/free-solid-svg-icons": "^6.4.0", + "@fortawesome/react-fontawesome": "github:fortawesome/react-fontawesome", + "@types/node": "18.15.11", + "@types/react": "18.0.35", + "@types/react-dom": "18.0.11", + "autoprefixer": "10.4.14", + "chart.js": "^4.3.0", + "concurrently": "^8.0.1", + "next": "13.3.0", + "postcss": "8.4.21", + "react": "18.2.0", + "react-chartjs-2": "^5.2.0", + "react-dom": "18.2.0", + "tailwindcss": "3.3.1", + "typescript": "5.0.4", + "zustand": "^4.3.7" + }, + "devDependencies": { + "eslint": "8.38.0", + "eslint-config-next": "13.3.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", + "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.0.tgz", + "integrity": "sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", + "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.5.1", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.38.0.tgz", + "integrity": "sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@faker-js/faker": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-7.6.0.tgz", + "integrity": "sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw==", + "engines": { + "node": ">=14.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz", + "integrity": "sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ==", + "hasInstallScript": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.0.tgz", + "integrity": "sha512-Bertv8xOiVELz5raB2FlXDPKt+m94MQ3JgDfsVbrqNpLU9+UE2E18GKjLKw+d3XbeYPqg1pzyQKGsrzbw+pPaw==", + "hasInstallScript": true, + "peer": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.4.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz", + "integrity": "sha512-kutPeRGWm8V5dltFP1zGjQOEAzaLZj4StdQhWVZnfGFCvAPVvHh8qk5bRrU4KXnRRRNni5tKQI9PBAdI6MP8nQ==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.4.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/react-fontawesome": { + "version": "0.2.0", + "resolved": "git+ssh://git@github.com/fortawesome/react-fontawesome.git#976c1adc59934b34e52b11c03dda4bd69831a6df", + "license": "MIT", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "react": ">=16.3" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "node_modules/@kurkle/color": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" + }, + "node_modules/@next/env": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.3.0.tgz", + "integrity": "sha512-AjppRV4uG3No7L1plinoTQETH+j2F10TEnrMfzbTUYwze5sBUPveeeBAPZPm8OkJZ1epq9OyYKhZrvbD6/9HCQ==" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.3.0.tgz", + "integrity": "sha512-wuGN5qSEjSgcq9fVkH0Y/qIPFjnZtW3ZPwfjJOn7l/rrf6y8J24h/lo61kwqunTyzZJm/ETGfGVU9PUs8cnzEA==", + "dev": true, + "dependencies": { + "glob": "7.1.7" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.3.0.tgz", + "integrity": "sha512-DmIQCNq6JtccLPPBzf0dgh2vzMWt5wjxbP71pCi5EWpWYE3MsP6FcRXi4MlAmFNDQOfcFXR2r7kBeG1LpZUh1w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.3.0.tgz", + "integrity": "sha512-oQoqFa88OGgwnYlnAGHVct618FRI/749se0N3S8t9Bzdv5CRbscnO0RcX901+YnNK4Q6yeiizfgO3b7kogtsZg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.3.0.tgz", + "integrity": "sha512-Wzz2p/WqAJUqTVoLo6H18WMeAXo3i+9DkPDae4oQG8LMloJ3if4NEZTnOnTUlro6cq+S/W4pTGa97nWTrOjbGw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.3.0.tgz", + "integrity": "sha512-xPVrIQOQo9WXJYgmoTlMnAD/HlR/1e1ZIWGbwIzEirXBVBqMARUulBEIKdC19zuvoJ477qZJgBDCKtKEykCpyQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.3.0.tgz", + "integrity": "sha512-jOFlpGuPD7W2tuXVJP4wt9a3cpNxWAPcloq5EfMJRiXsBBOjLVFZA7boXYxEBzSVgUiVVr1V9T0HFM7pULJ1qA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.3.0.tgz", + "integrity": "sha512-2OwKlzaBgmuet9XYHc3KwsEilzb04F540rlRXkAcjMHL7eCxB7uZIGtsVvKOnQLvC/elrUegwSw1+5f7WmfyOw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.3.0.tgz", + "integrity": "sha512-OeHiA6YEvndxT46g+rzFK/MQTfftKxJmzslERMu9LDdC6Kez0bdrgEYed5eXFK2Z1viKZJCGRlhd06rBusyztA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.3.0.tgz", + "integrity": "sha512-4aB7K9mcVK1lYEzpOpqWrXHEZympU3oK65fnNcY1Qc4HLJFLJj8AViuqQd4jjjPNuV4sl8jAwTz3gN5VNGWB7w==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.3.0.tgz", + "integrity": "sha512-Reer6rkLLcoOvB0dd66+Y7WrWVFH7sEEkF/4bJCIfsSKnTStTYaHtwIJAwbqnt9I392Tqvku0KkoqZOryWV9LQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgr/utils": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.3.1.tgz", + "integrity": "sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "is-glob": "^4.0.3", + "open": "^8.4.0", + "picocolors": "^1.0.0", + "tiny-glob": "^0.2.9", + "tslib": "^2.4.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", + "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==", + "dev": true + }, + "node_modules/@swc/helpers": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", + "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.15.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", + "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + }, + "node_modules/@types/react": { + "version": "18.0.35", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.35.tgz", + "integrity": "sha512-6Laome31HpetaIUGFWl1VQ3mdSImwxtFZ39rh059a1MNnKGqBpC88J6NJ8n/Is3Qx7CefDGLgf/KhN/sYCf7ag==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.0.11", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz", + "integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.0.tgz", + "integrity": "sha512-qK9TZ70eJtjojSUMrrEwA9ZDQ4N0e/AuoOIgXuNBorXYcBDk397D2r5MIe1B3cok/oCtdNC5j+lUUpVB+Dpb+w==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.59.0", + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/typescript-estree": "5.59.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.0.tgz", + "integrity": "sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/visitor-keys": "5.59.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", + "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.0.tgz", + "integrity": "sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/visitor-keys": "5.59.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", + "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", + "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.1.3" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", + "dev": true + }, + "node_modules/autoprefixer": { + "version": "10.4.14", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", + "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + ], + "dependencies": { + "browserslist": "^4.21.5", + "caniuse-lite": "^1.0.30001464", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", + "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001478", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001478.tgz", + "integrity": "sha512-gMhDyXGItTHipJj2ApIvR+iVB5hd0KP3svMWWXDvZOmjzJJassGLMfxRkQCSYgGd2gtdL/ReeiyvMSFD1Ss6Mw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chart.js": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.3.0.tgz", + "integrity": "sha512-ynG0E79xGfMaV2xAHdbhwiPLczxnNNnasrmPEXriXsPJGjmhOBYzFVEsB65w2qMDz+CaBJJuJD0inE/ab/h36g==", + "dependencies": { + "@kurkle/color": "^0.3.0" + }, + "engines": { + "pnpm": ">=7" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concurrently": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.0.1.tgz", + "integrity": "sha512-Sh8bGQMEL0TAmAm2meAXMjcASHZa7V0xXQVDBLknCPa9TPtkY9yYs+0cnGGgfdkW0SV1Mlg+hVGfXcoI8d3MJA==", + "dependencies": { + "chalk": "^4.1.2", + "date-fns": "^2.29.3", + "lodash": "^4.17.21", + "rxjs": "^7.8.0", + "shell-quote": "^1.8.0", + "spawn-command": "0.0.2-1", + "supports-color": "^8.1.1", + "tree-kill": "^1.2.2", + "yargs": "^17.7.1" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": "^14.13.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-equal": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", + "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-get-iterator": "^1.1.2", + "get-intrinsic": "^1.1.3", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dev": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.365", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.365.tgz", + "integrity": "sha512-FRHZO+1tUNO4TOPXmlxetkoaIY8uwHzd1kKopK/Gx2SKn1L47wJXWD44wxP5CGRyyP98z/c8e1eBzJrgPeiBOg==" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/enhanced-resolve": { + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", + "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/es-abstract": { + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", + "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.0", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.38.0.tgz", + "integrity": "sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.2", + "@eslint/js": "8.38.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.4.0", + "espree": "^9.5.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-next": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.3.0.tgz", + "integrity": "sha512-6YEwmFBX0VjBd3ODGW9df0Is0FLaRFdMN8eAahQG9CN6LjQ28J8AFr19ngxqMSg7Qv6Uca/3VeeBosJh1bzu0w==", + "dev": true, + "dependencies": { + "@next/eslint-plugin-next": "13.3.0", + "@rushstack/eslint-patch": "^1.1.3", + "@typescript-eslint/parser": "^5.42.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.31.7", + "eslint-plugin-react-hooks": "^4.5.0" + }, + "peerDependencies": { + "eslint": "^7.23.0 || ^8.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", + "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.11.0", + "resolve": "^1.22.1" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.5.tgz", + "integrity": "sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "get-tsconfig": "^4.5.0", + "globby": "^13.1.3", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3", + "synckit": "^0.8.5" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*" + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/globby": { + "version": "13.1.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.4.tgz", + "integrity": "sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==", + "dev": true, + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.11", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.27.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", + "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.1", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.7.4", + "has": "^1.0.3", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.6", + "resolve": "^1.22.1", + "semver": "^6.3.0", + "tsconfig-paths": "^3.14.1" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", + "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.20.7", + "aria-query": "^5.1.3", + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "ast-types-flow": "^0.0.7", + "axe-core": "^4.6.2", + "axobject-query": "^3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "has": "^1.0.3", + "jsx-ast-utils": "^3.3.3", + "language-tags": "=1.0.5", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.32.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", + "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "array.prototype.tosorted": "^1.1.1", + "doctrine": "^2.1.0", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "object.hasown": "^1.1.2", + "object.values": "^1.1.6", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.4", + "semver": "^6.3.0", + "string.prototype.matchall": "^4.0.8" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", + "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", + "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", + "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", + "dev": true, + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.5.0.tgz", + "integrity": "sha512-MjhiaIWCJ1sAU4pIQ5i5OfOuHHxVo1oYeNsWTON7jxYkod8pHocXeh+SSbmu5OZZZK73B6cbJ2XADzXehLyovQ==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globalyzer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", + "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==", + "dev": true + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", + "dev": true + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", + "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jiti": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.18.2.tgz", + "integrity": "sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-sdsl": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", + "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", + "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.5", + "object.assign": "^4.1.3" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", + "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", + "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", + "dev": true, + "dependencies": { + "language-subtag-registry": "~0.3.2" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/next": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/next/-/next-13.3.0.tgz", + "integrity": "sha512-OVTw8MpIPa12+DCUkPqRGPS3thlJPcwae2ZL4xti3iBff27goH024xy4q2lhlsdoYiKOi8Kz6uJoLW/GXwgfOA==", + "dependencies": { + "@next/env": "13.3.0", + "@swc/helpers": "0.4.14", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001406", + "postcss": "8.4.14", + "styled-jsx": "5.1.1" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=14.6.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "13.3.0", + "@next/swc-darwin-x64": "13.3.0", + "@next/swc-linux-arm64-gnu": "13.3.0", + "@next/swc-linux-arm64-musl": "13.3.0", + "@next/swc-linux-x64-gnu": "13.3.0", + "@next/swc-linux-x64-musl": "13.3.0", + "@next/swc-win32-arm64-msvc": "13.3.0", + "@next/swc-win32-ia32-msvc": "13.3.0", + "@next/swc-win32-x64-msvc": "13.3.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "fibers": ">= 3.1.0", + "node-sass": "^6.0.0 || ^7.0.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/node-releases": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", + "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", + "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.hasown": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", + "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", + "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", + "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-nested": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz", + "integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", + "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-chartjs-2": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.2.0.tgz", + "integrity": "sha512-98iN5aguJyVSxp5U3CblRLH67J8gkfyGNbiK3c+l1QI/G4irHMPQw44aEPmjVag+YKTyQ260NcF82GTQ3bdscA==", + "peerDependencies": { + "chart.js": "^4.1.1", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.3.tgz", + "integrity": "sha512-P8ur/gp/AmbEzjr729bZnLjXK5Z+4P0zhIJgBgzqRih7hL7BOukHGtSTA3ACMY467GRFz3duQsi0bDZdR7DKdw==", + "dependencies": { + "is-core-module": "^2.12.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spawn-command": { + "version": "0.0.2-1", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", + "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==" + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", + "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.3", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/sucrase": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.32.0.tgz", + "integrity": "sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "7.1.6", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/synckit": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", + "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", + "dev": true, + "dependencies": { + "@pkgr/utils": "^2.3.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/tailwindcss": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.1.tgz", + "integrity": "sha512-Vkiouc41d4CEq0ujXl6oiGFQ7bA3WEhUZdTgXAhtKxSy49OmKs8rEfQmupsfF0IGW8fv2iQkp1EVUuapCFrZ9g==", + "dependencies": { + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "color-name": "^1.1.4", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.12", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.17.2", + "lilconfig": "^2.0.6", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.0.9", + "postcss-import": "^14.1.0", + "postcss-js": "^4.0.0", + "postcss-load-config": "^3.1.4", + "postcss-nested": "6.0.0", + "postcss-selector-parser": "^6.0.11", + "postcss-value-parser": "^4.2.0", + "quick-lru": "^5.1.1", + "resolve": "^1.22.1", + "sucrase": "^3.29.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/tailwindcss/node_modules/postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dependencies": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tiny-glob": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", + "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", + "dev": true, + "dependencies": { + "globalyzer": "0.1.0", + "globrex": "^0.1.2" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" + }, + "node_modules/tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zustand": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.3.7.tgz", + "integrity": "sha512-dY8ERwB9Nd21ellgkBZFhudER8KVlelZm8388B5nDAXhO/+FZDhYMuRnqDgu5SYyRgz/iaf8RKnbUs/cHfOGlQ==", + "dependencies": { + "use-sync-external-store": "1.2.0" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "immer": ">=9.0", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } + } + } +} diff --git a/fullstack-templates/saas/package.json b/fullstack-templates/saas/package.json new file mode 100644 index 00000000..641b3dc4 --- /dev/null +++ b/fullstack-templates/saas/package.json @@ -0,0 +1,38 @@ +{ + "name": "rustcrm", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "npm run build && concurrently --names 'next, shuttle' --kill-others 'next dev' 'cargo shuttle run --working-directory ./backend/'", + "build": "next build && cargo build --manifest-path ./backend/Cargo.toml", + "shuttle-login": "cargo shuttle login --working-directory ./backend/", + "full": "cargo shuttle run --working-directory backend --port 8001", + "start": "cargo shuttle project start --working-directory ./backend/", + "stop": "cargo shuttle project stop --working-directory ./backend/", + "deploy": "npm run build && cargo shuttle deploy --working-directory ./backend/ --allow-dirty", + "lint": "next lint" + }, + "dependencies": { + "@faker-js/faker": "^7.6.0", + "@fortawesome/free-solid-svg-icons": "^6.4.0", + "@fortawesome/react-fontawesome": "github:fortawesome/react-fontawesome", + "@types/node": "18.15.11", + "@types/react": "18.0.35", + "@types/react-dom": "18.0.11", + "autoprefixer": "10.4.14", + "chart.js": "^4.3.0", + "concurrently": "^8.0.1", + "next": "13.3.0", + "postcss": "8.4.21", + "react": "18.2.0", + "react-chartjs-2": "^5.2.0", + "react-dom": "18.2.0", + "tailwindcss": "3.3.1", + "typescript": "5.0.4", + "zustand": "^4.3.7" + }, + "devDependencies": { + "eslint": "8.38.0", + "eslint-config-next": "13.3.0" + } +} diff --git a/fullstack-templates/saas/postcss.config.js b/fullstack-templates/saas/postcss.config.js new file mode 100644 index 00000000..33ad091d --- /dev/null +++ b/fullstack-templates/saas/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/fullstack-templates/saas/public/favicon.ico b/fullstack-templates/saas/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..718d6fea4835ec2d246af9800eddb7ffb276240c GIT binary patch literal 25931 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 LrJugUA?W`A8`#=m literal 0 HcmV?d00001 diff --git a/fullstack-templates/saas/public/next.svg b/fullstack-templates/saas/public/next.svg new file mode 100644 index 00000000..5174b28c --- /dev/null +++ b/fullstack-templates/saas/public/next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/fullstack-templates/saas/public/vercel.svg b/fullstack-templates/saas/public/vercel.svg new file mode 100644 index 00000000..d2f84222 --- /dev/null +++ b/fullstack-templates/saas/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/fullstack-templates/saas/src/components/AuthedLayout.tsx b/fullstack-templates/saas/src/components/AuthedLayout.tsx new file mode 100644 index 00000000..f01e936e --- /dev/null +++ b/fullstack-templates/saas/src/components/AuthedLayout.tsx @@ -0,0 +1,27 @@ +import Navbar from './navbar'; +import React from 'react'; +import Head from 'next/head'; +import { accountStore } from '@/zustandStore'; +import { useRouter } from 'next/router'; + +type Props = { + children: React.ReactNode | React.ReactNode[]; +}; + +export default function Layout({ children }: Props) { + let router = useRouter(); + let { email } = accountStore(); + + React.useEffect(() => { + if (router.pathname.includes(`${window.location.host}/dashboard`) && email == '') { + router.push('/login'); + } + }, [email, router, router.pathname]); + + return ( +

+ + {children} +
+ ); +} diff --git a/fullstack-templates/saas/src/components/CustomerSingleModal.tsx b/fullstack-templates/saas/src/components/CustomerSingleModal.tsx new file mode 100644 index 00000000..bfba560e --- /dev/null +++ b/fullstack-templates/saas/src/components/CustomerSingleModal.tsx @@ -0,0 +1,86 @@ +import Layout from '@/components/Layout'; +import React from 'react'; +import { useRouter } from 'next/router'; +import { accountStore } from '@/zustandStore'; +import Link from 'next/link'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faMultiply } from '@fortawesome/free-solid-svg-icons'; + +interface Customer { + id: number; + firstname: string; + lastname: string; + email: string; + phone: string; +} + +type Props = { + id: number; + data: Customer[]; + vis: boolean; + setVis: React.Dispatch>; +}; + +export default function CustomerSingle({ data, id, vis, setVis }: Props) { + const { email } = accountStore(); + + let router = useRouter(); + + const handleDelete = async (e: React.SyntheticEvent) => { + e.preventDefault(); + const url = `//${window.location.host}/api/customers/${id}`; + + try { + const res = await fetch(url, { + mode: 'cors', + method: 'DELETE', + headers: new Headers({ + 'Content-Type': 'application/json', + }), + body: JSON.stringify({ + email: email, + }), + }); + + if (res.ok) { + router.reload(); + } + } catch (e: any) { + console.log(`Error: ${e}`); + } + }; + + if (!vis) return null; + + const customer = data.find((a) => a.id == id); + + if (!customer) return

Customer does not exist :(

; + + return ( +
+
+
+

Customer details

+ + +
+
+

+ Name: {customer.firstname} {customer.lastname} +

+

Email: {customer.email}

+

Phone: {customer.phone}

+
+ +
+
+ ); +} diff --git a/fullstack-templates/saas/src/components/DealSingleModal copy.tsx b/fullstack-templates/saas/src/components/DealSingleModal copy.tsx new file mode 100644 index 00000000..3f9a3e6a --- /dev/null +++ b/fullstack-templates/saas/src/components/DealSingleModal copy.tsx @@ -0,0 +1,77 @@ +import Layout from "@/components/Layout" +import React from "react" +import { useRouter } from 'next/router' +import {accountStore} from "@/zustandStore" +import Link from 'next/link' + +interface Customer { + id: number, + firstname: string, + lastname: string, + email: string, + phone: string +} + +type Props = { + id: number, + data: Customer[], + vis: boolean, + setVis: React.Dispatch> +} + +export default function CustomerSingle({data, id, vis, setVis}: Props) { + + const {email} = accountStore(); + + let router = useRouter(); + + const handleDelete = async (e: React.SyntheticEvent) => { + e.preventDefault() + const url = `//${window.location.host}/api/customers/${id}` + + try { + +const res = await fetch(url, { + mode: 'cors', + method: 'DELETE', + headers: new Headers({ + "Content-Type": "application/json" + }), + body: JSON.stringify({ + email: email + }) + }); + + if (res.ok) { + router.reload() + } + } catch (e: any) { + console.log(`Error: ${e}`) + } + + } + + return ( + <> + {vis ? +
+
+ {data ? + data.filter(a => a.id == id).map((item) => ( +
+

{item.firstname} {item.lastname}

+

Email: {item.email}

+

Phone: {item.phone}

+ +
)) + : +

Customer does not exist :(

} + +
+
:null } + + ) +} + + + diff --git a/fullstack-templates/saas/src/components/Layout.tsx b/fullstack-templates/saas/src/components/Layout.tsx new file mode 100644 index 00000000..f5da8c0c --- /dev/null +++ b/fullstack-templates/saas/src/components/Layout.tsx @@ -0,0 +1,32 @@ +import Navbar from './navbar'; +import React from 'react'; +import Head from 'next/head'; +import { accountStore } from '@/zustandStore'; + +type Props = { + children: React.ReactNode | React.ReactNode[]; +}; + +export default function Layout({ children }: Props) { + let { email } = accountStore(); + + return ( + <> + + Shuttle SaaS + +
+ +
+ {children} +
+
+ + ); +} diff --git a/fullstack-templates/saas/src/components/Metrics.tsx b/fullstack-templates/saas/src/components/Metrics.tsx new file mode 100644 index 00000000..6423536b --- /dev/null +++ b/fullstack-templates/saas/src/components/Metrics.tsx @@ -0,0 +1,24 @@ +import { faker } from '@faker-js/faker'; + +export default function Metrics() { + return ( +
+
+

{faker.finance.amount()}

+

Leads

+
+
+

{faker.finance.amount()}

+

Open Sales Deals

+
+
+

£{faker.finance.amount()}

+

Closed this week:

+
+
+

£{faker.finance.amount()}

+

Closed this month:

+
+
+ ); +} diff --git a/fullstack-templates/saas/src/components/Navigation.tsx b/fullstack-templates/saas/src/components/Navigation.tsx new file mode 100644 index 00000000..a335fc40 --- /dev/null +++ b/fullstack-templates/saas/src/components/Navigation.tsx @@ -0,0 +1,22 @@ +import Link from 'next/link'; +import React from 'react'; + +function Navigation() { + return ( + + ); +} + +export default Navigation; diff --git a/fullstack-templates/saas/src/components/RecentSales.tsx b/fullstack-templates/saas/src/components/RecentSales.tsx new file mode 100644 index 00000000..1f33b003 --- /dev/null +++ b/fullstack-templates/saas/src/components/RecentSales.tsx @@ -0,0 +1,40 @@ +import { faker } from '@faker-js/faker'; + +export default function RecentSales() { + return ( +
+

Recent Sales

+ + + + + + + + + + {new Array(7).fill(0).map((_, i) => ( + + + + + ))} + +
+ Customer + + Amount Invoiced +
+
+
+

+ {faker.name.firstName()} {faker.name.lastName()} +

+
+
+
+

£{faker.finance.amount()}

+
+
+ ); +} diff --git a/fullstack-templates/saas/src/components/SalesChart.tsx b/fullstack-templates/saas/src/components/SalesChart.tsx new file mode 100644 index 00000000..e8d2d89f --- /dev/null +++ b/fullstack-templates/saas/src/components/SalesChart.tsx @@ -0,0 +1,59 @@ +import { Line } from 'react-chartjs-2'; +import { + Chart as ChartJS, + CategoryScale, + LinearScale, + PointElement, + LineElement, + Title, + Tooltip, + Legend, +} from 'chart.js'; + +function SalesChart() { + ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend); + + const options = { + responsive: true, + maintainAspectRatio: false, + scales: { + y: { + min: 0, + stepSize: 100, + max: 500, + ticks: { + stepSize: 100, + }, + }, + }, + plugins: { + title: { + display: false, + }, + }, + }; + + const labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July']; + + const chartdata = { + labels, + datasets: [ + { + label: 'Sales - Last 7 Months', + data: [100, 300, 200, 100, 200, 400, 300], + borderColor: '#EF924C', + backgroundColor: '#EF924C', + color: '#EF924C', + tension: 0.3, + }, + ], + }; + + return ( +
+ +
+ ); +} + +export default SalesChart; diff --git a/fullstack-templates/saas/src/components/Sidebar.tsx b/fullstack-templates/saas/src/components/Sidebar.tsx new file mode 100644 index 00000000..95929830 --- /dev/null +++ b/fullstack-templates/saas/src/components/Sidebar.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +function Sidebar() { + return
Sidebar
; +} + +export default Sidebar; diff --git a/fullstack-templates/saas/src/components/TopClients.tsx b/fullstack-templates/saas/src/components/TopClients.tsx new file mode 100644 index 00000000..f35d56c1 --- /dev/null +++ b/fullstack-templates/saas/src/components/TopClients.tsx @@ -0,0 +1,34 @@ +import { faker } from '@faker-js/faker'; +import Image from 'next/image'; + +export default function TopClients() { + return ( +
+

Top Clients

+
+ {new Array(7).fill(0).map((_, i) => ( +
+
+ Avatar + +

+ + {faker.name.firstName()} {faker.name.lastName()} + + {faker.internet.email()} +

+
+ +

£{faker.finance.amount()}

+
+ ))} +
+
+ ); +} diff --git a/fullstack-templates/saas/src/components/navbar.tsx b/fullstack-templates/saas/src/components/navbar.tsx new file mode 100644 index 00000000..d1b9b635 --- /dev/null +++ b/fullstack-templates/saas/src/components/navbar.tsx @@ -0,0 +1,104 @@ +import React, { useState } from 'react'; +import Link from 'next/link'; +import { accountStore } from '@/zustandStore'; +import { useRouter } from 'next/router'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { + faBars, + faCoins, + faGauge, + faHandshake, + faRightFromBracket, + faRocket, + faUserSecret, + faUsers, +} from '@fortawesome/free-solid-svg-icons'; +import Navigation from './Navigation'; + +export default function Navbar() { + const { email, changeEmail } = accountStore(); + const router = useRouter(); + const [open, setOpen] = useState(false); + + const handleLogout = async () => { + const url = `//${window.location.host}/api/auth/logout`; + + const res = await fetch(url); + + if (res.ok) { + changeEmail(''); + router.push('/'); + } + }; + + if (email === '') return ; + + return ( + <> + + + ); +} diff --git a/fullstack-templates/saas/src/pages/_app.tsx b/fullstack-templates/saas/src/pages/_app.tsx new file mode 100644 index 00000000..ea0fec47 --- /dev/null +++ b/fullstack-templates/saas/src/pages/_app.tsx @@ -0,0 +1,9 @@ +import '@/styles/globals.css'; +import type { AppProps } from 'next/app'; +import { config } from '@fortawesome/fontawesome-svg-core'; +import '@fortawesome/fontawesome-svg-core/styles.css'; +config.autoAddCss = false; + +export default function App({ Component, pageProps }: AppProps) { + return ; +} diff --git a/fullstack-templates/saas/src/pages/_document.tsx b/fullstack-templates/saas/src/pages/_document.tsx new file mode 100644 index 00000000..54e8bf3e --- /dev/null +++ b/fullstack-templates/saas/src/pages/_document.tsx @@ -0,0 +1,13 @@ +import { Html, Head, Main, NextScript } from 'next/document' + +export default function Document() { + return ( + + + +
+ + + + ) +} diff --git a/fullstack-templates/saas/src/pages/dashboard/customers/[id].tsx b/fullstack-templates/saas/src/pages/dashboard/customers/[id].tsx new file mode 100644 index 00000000..99abcfb6 --- /dev/null +++ b/fullstack-templates/saas/src/pages/dashboard/customers/[id].tsx @@ -0,0 +1,105 @@ +import Layout from "@/components/Layout" +import React from "react" +import { useRouter } from 'next/router' +import {accountStore} from "@/zustandStore" +import Link from 'next/link' + +interface Customer { + id: number, + firstname: string, + lastname: string, + email: string, + phone: string +} + +export default function CustomerSingle() { + + const [data, setData] = React.useState(); + const {email} = accountStore(); + + let router = useRouter(); + const {id} = router.query; + + const handleDelete = async (e: React.SyntheticEvent) => { + e.preventDefault() + const url = `//${window.location.host}/api/customers/${id}` + + try { + +const res = await fetch(url, { + mode: 'cors', + method: 'DELETE', + headers: new Headers({ + "Content-Type": "application/json" + }), + body: JSON.stringify({ + email: email + }) + }); + + if (res.ok) { + router.push("/dashboard/customers"); + } + } catch (e: any) { + console.log(`Error: ${e}`) + } + + } + +React.useEffect(() => { + const fetchData = async () => { + + const url = `//${window.location.host}/api/customers/${id}` + + try { + const res = await fetch(url, + { + method: "POST", + mode: "cors", + headers: new Headers({ + "Content-Type": "application/json" + }), + + body: JSON.stringify({ + email: email + }) + }, + ); + + if (res.status == 403) { + return router.push("/login"); + } + + const data: Customer = await res.json() + + setData(data); + + } catch (e: any) { + console.log(`Error: ${e}`); + } + }; + fetchData() + }, [email, router, id]); + + + return ( + +
+ {data ? +
+

{data.firstname} {data.lastname}

+

Email: {data.email}

+

Phone: {data.phone}

+ +
+ : +

User does not exist :(

} + +
+ +
+ ) +} + + + diff --git a/fullstack-templates/saas/src/pages/dashboard/customers/create.tsx b/fullstack-templates/saas/src/pages/dashboard/customers/create.tsx new file mode 100644 index 00000000..81d5e714 --- /dev/null +++ b/fullstack-templates/saas/src/pages/dashboard/customers/create.tsx @@ -0,0 +1,192 @@ +import Layout from '../../../components/Layout'; +import React from 'react'; +import { useRouter } from 'next/router'; +import { accountStore } from '@/zustandStore'; + +export default function CreateCustomer() { + const [firstName, setFirstName] = React.useState(''); + const [lastName, setLastName] = React.useState(''); + const [custEmail, setCustEmail] = React.useState(''); + const [phone, setPhone] = React.useState(''); + const [priority, setPriority] = React.useState('1'); + + const { email } = accountStore(); + + let router = useRouter(); + + const handleSubmit = async (e: React.SyntheticEvent) => { + e.preventDefault(); + + const url = `//${window.location.host}/api/customers/create`; + + try { + let res = await fetch(url, { + method: 'POST', + mode: 'cors', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + firstName: firstName, + lastName: lastName, + email: custEmail, + phone: phone, + priority: Number(priority), + userEmail: email, + }), + }); + + if (res.ok) { + router.push('/dashboard/customers'); + } + } catch (e: any) { + console.log(`Error: ${e}`); + } + }; + + return ( + <> + +
+
+

New Customer

+
+ + + + + + +
+ +
+
+
+
+
+ + ); +} diff --git a/fullstack-templates/saas/src/pages/dashboard/customers/edit.tsx b/fullstack-templates/saas/src/pages/dashboard/customers/edit.tsx new file mode 100644 index 00000000..7a07b5ac --- /dev/null +++ b/fullstack-templates/saas/src/pages/dashboard/customers/edit.tsx @@ -0,0 +1,85 @@ +import Layout from "../../../components/Layout" +import React from "react" +import {useRouter} from 'next/router' + +export default function CreateCustomer() { + + const [firstName, setFirstName] = React.useState(""); + const [lastName, setLastName] = React.useState(""); + const [email, setEmail] = React.useState(""); + const [phone, setPhone] = React.useState(""); + const [priority, setPriority] = React.useState(""); + +let router = useRouter(); + + + const handleSubmit = async (e: React.SyntheticEvent) => { + e.preventDefault() + + const url = `//${window.location.host}/api/auth/register` + + try { + let res = await fetch(url, + { + method: "POST", + mode: "cors", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + firstName: firstName, + lastName: lastName, + email: email, + phone: phone, + priority: Number(priority) + }), + }) + + if (res.ok) { + router.push("/dashboard/customers"); + } + + } catch(e: any) { + console.log(`Error: ${e}`) + } + } + + return ( + <> + +
+

Create Customer

+ + + + + + +
+
+ + ) +} + + diff --git a/fullstack-templates/saas/src/pages/dashboard/customers/index.tsx b/fullstack-templates/saas/src/pages/dashboard/customers/index.tsx new file mode 100644 index 00000000..597a5284 --- /dev/null +++ b/fullstack-templates/saas/src/pages/dashboard/customers/index.tsx @@ -0,0 +1,140 @@ +import Layout from '../../../components/Layout'; +import React from 'react'; +import { useRouter } from 'next/router'; +import { accountStore } from '../../../zustandStore'; +import Link from 'next/link'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faPlus, faTrash } from '@fortawesome/free-solid-svg-icons'; + +interface Customer { + id: number; + firstname: string; + lastname: string; + email: string; + phone: string; +} + +export default function CustomerIndex() { + const [data, setData] = React.useState([]); + const { email } = accountStore(); + + let router = useRouter(); + + React.useEffect(() => { + const fetchData = async () => { + const url = `//${window.location.host}/api/customers`; + + try { + const res = await fetch(url, { + method: 'POST', + mode: 'cors', + headers: new Headers({ + 'Content-Type': 'application/json', + }), + + body: JSON.stringify({ + email: email, + }), + }); + + if (res.status == 403) { + return router.push('/login'); + } + + const data = await res.json(); + + setData(data); + } catch (e: any) { + console.log(`Error: ${e}`); + } + }; + fetchData(); + }, [email, router]); + + const handleDelete = async (customerId: number) => { + const url = `//${window.location.host}/api/customers/${customerId}`; + + try { + const res = await fetch(url, { + mode: 'cors', + method: 'DELETE', + headers: new Headers({ + 'Content-Type': 'application/json', + }), + body: JSON.stringify({ + email: email, + }), + }); + + if (res.ok) { + router.reload(); + } + } catch (e: any) { + console.log(`Error: ${e}`); + } + }; + + return ( + +
+
+

Customers

+
+ + + + + + + + + + + {data.map((cust) => ( + + + + + + + ))} + +
+ Customer + + Email + + Phone Number + + More Info +
+
+
+

+ {cust.firstname} {cust.lastname} +

+
+
+
+

{cust.email}

+
+

{cust.phone}

+
+ +
+ + Add Customer + +
+
+ ); +} diff --git a/fullstack-templates/saas/src/pages/dashboard/deals/create.tsx b/fullstack-templates/saas/src/pages/dashboard/deals/create.tsx new file mode 100644 index 00000000..c89aab80 --- /dev/null +++ b/fullstack-templates/saas/src/pages/dashboard/deals/create.tsx @@ -0,0 +1,167 @@ +import Layout from '../../../components/Layout'; +import React from 'react'; +import { useRouter } from 'next/router'; +import { accountStore } from '@/zustandStore'; + +type Custname = { + id: number; + customer_name: string; +}; + +export default function CreateDeal() { + const [estimate, setEstimate] = React.useState(''); + const [custId, setCustId] = React.useState(''); + const [custnames, setCustnames] = React.useState([]); + const { email } = accountStore(); + + let router = useRouter(); + + const handleSubmit = async (e: React.SyntheticEvent) => { + e.preventDefault(); + const url = `//${window.location.host}/api/deals/create`; + + try { + const res = await fetch(url, { + method: 'POST', + mode: 'cors', + headers: new Headers({ + 'Content-Type': 'application/json', + }), + + body: JSON.stringify({ + estimatedworth: parseInt(estimate), + cust_id: parseInt(custId), + useremail: email, + }), + }); + + if (res.status == 403) { + return router.push('/login'); + } + + router.push('/dashboard/deals'); + } catch (e: any) { + console.log(`Error: ${e}`); + } + }; + + React.useEffect(() => { + const fetchData = async () => { + const url = `//${window.location.host}/api/customers/names`; + + try { + const res = await fetch(url, { + method: 'POST', + mode: 'cors', + headers: new Headers({ + 'Content-Type': 'application/json', + }), + + body: JSON.stringify({ + email: email, + }), + }); + + if (res.status == 403) { + return router.push('/login'); + } + + const data = await res.json(); + + setCustnames(data); + } catch (e: any) { + console.log(`Error: ${e}`); + } + }; + fetchData(); + }, [email, router]); + + return ( + <> + +
+
+

New Deal

+
+ + + +
+
+
+
+ + ); +} diff --git a/fullstack-templates/saas/src/pages/dashboard/deals/edit.tsx b/fullstack-templates/saas/src/pages/dashboard/deals/edit.tsx new file mode 100644 index 00000000..7a07b5ac --- /dev/null +++ b/fullstack-templates/saas/src/pages/dashboard/deals/edit.tsx @@ -0,0 +1,85 @@ +import Layout from "../../../components/Layout" +import React from "react" +import {useRouter} from 'next/router' + +export default function CreateCustomer() { + + const [firstName, setFirstName] = React.useState(""); + const [lastName, setLastName] = React.useState(""); + const [email, setEmail] = React.useState(""); + const [phone, setPhone] = React.useState(""); + const [priority, setPriority] = React.useState(""); + +let router = useRouter(); + + + const handleSubmit = async (e: React.SyntheticEvent) => { + e.preventDefault() + + const url = `//${window.location.host}/api/auth/register` + + try { + let res = await fetch(url, + { + method: "POST", + mode: "cors", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + firstName: firstName, + lastName: lastName, + email: email, + phone: phone, + priority: Number(priority) + }), + }) + + if (res.ok) { + router.push("/dashboard/customers"); + } + + } catch(e: any) { + console.log(`Error: ${e}`) + } + } + + return ( + <> + +
+

Create Customer

+ + + + + + +
+
+ + ) +} + + diff --git a/fullstack-templates/saas/src/pages/dashboard/deals/index.tsx b/fullstack-templates/saas/src/pages/dashboard/deals/index.tsx new file mode 100644 index 00000000..4510ef47 --- /dev/null +++ b/fullstack-templates/saas/src/pages/dashboard/deals/index.tsx @@ -0,0 +1,149 @@ +import Layout from '../../../components/Layout'; +import React from 'react'; +import { useRouter } from 'next/router'; +import { accountStore } from '../../../zustandStore'; +import Link from 'next/link'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faPlus } from '@fortawesome/free-solid-svg-icons'; + +interface Deal { + id: number; + estimate_worth: number; + actual_worth: number; + status: string; + closed: string; + customer_id: number; + customer_name: String; +} + +export default function DealIndex() { + const [data, setData] = React.useState([]); + const { email } = accountStore(); + + let router = useRouter(); + + const handleStatus = async (e: React.SyntheticEvent) => { + e.preventDefault(); + + let element = e.target as HTMLSelectElement; + + let id = element.getAttribute('data-id'); + let status = element.value; + + const url = `//${window.location.host}/api/deals/${id}`; + + try { + const res = await fetch(url, { + method: 'PUT', + mode: 'cors', + headers: new Headers({ + 'Content-Type': 'application/json', + }), + body: JSON.stringify({ + new_value: status, + email: email, + }), + }); + + if (res.ok) { + element.value = status; + } + } catch (e: any) { + console.log(e.message); + } + }; + + React.useEffect(() => { + const fetchData = async () => { + const url = `//${window.location.host}/api/deals`; + + try { + const res = await fetch(url, { + method: 'POST', + mode: 'cors', + headers: new Headers({ + 'Content-Type': 'application/json', + }), + + body: JSON.stringify({ + email: email, + }), + }); + + if (res.status == 403) { + return router.push('/login'); + } + + const data = await res.json(); + + setData(data); + } catch (e: any) { + console.log(`Error: ${e}`); + } + }; + fetchData(); + }, [email, router]); + + return ( + +
+
+

Deals

+
+ + + + + + + + + + + + {data.map((deal) => ( + + + + + + + ))} + +
+ Customer + + Invoice Amount + + Status +
+
+
+

{deal.customer_name}

+
+
+
+

£{deal.estimate_worth}.00

+
+ +
+ + Create Deal + +
+
+ ); +} diff --git a/fullstack-templates/saas/src/pages/dashboard/index.tsx b/fullstack-templates/saas/src/pages/dashboard/index.tsx new file mode 100644 index 00000000..a2d4f877 --- /dev/null +++ b/fullstack-templates/saas/src/pages/dashboard/index.tsx @@ -0,0 +1,79 @@ +import Layout from '../../components/Layout'; +import React from 'react'; +import { useRouter } from 'next/router'; +import { accountStore } from '@/zustandStore'; +import SalesChart from '@/components/SalesChart'; +import RecentSales from '@/components/RecentSales'; +import TopClients from '@/components/TopClients'; + +interface dashboardData { + sales_deals_info: salesDealsInfo; + sales_per_day_info: salesPerDayInfo; +} + +interface salesDealsInfo { + open: number; + ready: number; + awaitingresponse: number; + closed: number; + total_amt_closed: number; +} + +interface salesPerDayInfo { + date: String; + sales_total: number; +} + +export default function Dashboard() { + const [data, setData] = React.useState(); + const { email } = accountStore(); + const router = useRouter(); + + React.useEffect(() => { + const fetchData = async () => { + const url = `//${window.location.host}/api/dashboard`; + + try { + const res = await fetch(url, { + method: 'POST', + mode: 'cors', + headers: new Headers({ + 'Content-Type': 'application/json', + }), + + body: JSON.stringify({ + email: email, + }), + }); + + if (res.status == 403) { + return router.push('/login'); + } + + const data = await res.json(); + + setData(data); + } catch (e: any) { + console.log(`Error: ${e}`); + } + }; + fetchData(); + }, [email, router]); + + if (!data) return

It looks like something went wrong when retrieving data :(

; + + return ( + +
+
+ + +
+ + +
+
+
+
+ ); +} diff --git a/fullstack-templates/saas/src/pages/dashboard/upgrade/checkout/failed.tsx b/fullstack-templates/saas/src/pages/dashboard/upgrade/checkout/failed.tsx new file mode 100644 index 00000000..a8b19dd9 --- /dev/null +++ b/fullstack-templates/saas/src/pages/dashboard/upgrade/checkout/failed.tsx @@ -0,0 +1,16 @@ +import Layout from "@/components/Layout" +import React from "react" +import {useRouter} from 'next/router' + +export default function PaymentSuccess() { + + return ( + <> + +

Payment has failed :(

+
+ + ) +} + + diff --git a/fullstack-templates/saas/src/pages/dashboard/upgrade/checkout/index.tsx b/fullstack-templates/saas/src/pages/dashboard/upgrade/checkout/index.tsx new file mode 100644 index 00000000..3d5fc051 --- /dev/null +++ b/fullstack-templates/saas/src/pages/dashboard/upgrade/checkout/index.tsx @@ -0,0 +1,248 @@ +import Layout from '@/components/Layout'; +import React from 'react'; +import { useRouter } from 'next/router'; + +export default function CreateCustomer() { + const [name, setName] = React.useState(''); + const [email, setEmail] = React.useState(''); + const [card, setCard] = React.useState(''); + const [year, setYear] = React.useState(''); + const [month, setMonth] = React.useState(''); + const [cvc, setCvc] = React.useState(''); + + let router = useRouter(); + + const handleSubmit = async (e: React.SyntheticEvent) => { + e.preventDefault(); + + const url = `//${window.location.host}/api/payments/pay`; + + try { + let res = await fetch(url, { + method: 'POST', + mode: 'cors', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + name: name, + email: email, + card: card, + expyear: parseInt(year), + expmonth: parseInt(month), + cvc: cvc, + }), + }); + + if (res.ok) { + router.push('/dashboard/upgrade/checkout/success'); + } + } catch (e: any) { + console.log(`Error: ${e}`); + } + }; + + return ( + +
+
+

Checkout

+ +
+ + setName((e.target as HTMLInputElement).value)} + placeholder="Enter your full name" + /> + + setEmail((e.target as HTMLInputElement).value)} + placeholder="Enter your email" + /> + + setCard((e.target as HTMLInputElement).value)} + placeholder="Enter your card number" + /> + + + + + + + + + setCvc((e.target as HTMLInputElement).value)} + placeholder="Enter your card CVC" + /> + +
+ +
+
+
+
+
+ ); +} diff --git a/fullstack-templates/saas/src/pages/dashboard/upgrade/checkout/success.tsx b/fullstack-templates/saas/src/pages/dashboard/upgrade/checkout/success.tsx new file mode 100644 index 00000000..9ffdd710 --- /dev/null +++ b/fullstack-templates/saas/src/pages/dashboard/upgrade/checkout/success.tsx @@ -0,0 +1,16 @@ +import Layout from "@/components/Layout" +import React from "react" +import {useRouter} from 'next/router' + +export default function PaymentSuccess() { + + return ( + <> + +

Payment was successful!

+
+ + ) +} + + diff --git a/fullstack-templates/saas/src/pages/dashboard/upgrade/index.tsx b/fullstack-templates/saas/src/pages/dashboard/upgrade/index.tsx new file mode 100644 index 00000000..14d0b57b --- /dev/null +++ b/fullstack-templates/saas/src/pages/dashboard/upgrade/index.tsx @@ -0,0 +1,89 @@ +import Layout from '@/components/Layout'; +import Link from 'next/link'; + +export default function Home() { + return ( + <> + +
+

Pricing

+ +
+
+
+
+
+

+ Casual +

+
+
+ Free +
+
    +
  • Up to 5 projects
  • +
  • Up to 10 collaborators
  • +
  • 2Gb of storage
  • +
+ + Your plan +
+ +
+
+

+ Professional +

+
+
+ $24.90 + /month +
+
    +
  • Up to 10 projects
  • +
  • Up to 20 collaborators
  • +
  • 10Gb of storage
  • +
  • Real-time collaborations
  • +
+ + + Upgrade + +
+ +
+
+

+ Expert +

+
+
+ $49.90 + /month +
+
    +
  • Unlimited projects
  • +
  • Unlimited collaborators
  • +
  • Unlimited storage
  • +
  • Real-time collaborations
  • +
  • 24x7 Support
  • +
+ + + Upgrade + +
+
+
+
+
+
+ + ); +} diff --git a/fullstack-templates/saas/src/pages/forgot.tsx b/fullstack-templates/saas/src/pages/forgot.tsx new file mode 100644 index 00000000..a2d4844b --- /dev/null +++ b/fullstack-templates/saas/src/pages/forgot.tsx @@ -0,0 +1,86 @@ +import Layout from "@/components/Layout" +import React from "react" +import { useRouter } from 'next/router' + +export default function CreateCustomer() { + + const [firstName, setFirstName] = React.useState(""); + const [lastName, setLastName] = React.useState(""); + const [email, setEmail] = React.useState(""); + const [phone, setPhone] = React.useState(""); + const [priority, setPriority] = React.useState(""); + + let router = useRouter(); + + + const handleSubmit = async (e: React.SyntheticEvent) => { + e.preventDefault() + + const url = `//${window.location.host}/api/auth/register` + + try { + let res = await fetch(url, + { + method: "POST", + mode: "cors", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + firstName: firstName, + lastName: lastName, + email: email, + phone: phone, + priority: Number(priority) + }), + }) + + if (res.ok) { + router.push("/dashboard/customers"); + } + + } catch (e: any) { + console.log(`Error: ${e}`) + } + } + + return ( + <> + +
+

Create Customer

+ + + + + + +
+
+ + ) +} + + + diff --git a/fullstack-templates/saas/src/pages/index.tsx b/fullstack-templates/saas/src/pages/index.tsx new file mode 100644 index 00000000..d97fd83c --- /dev/null +++ b/fullstack-templates/saas/src/pages/index.tsx @@ -0,0 +1,61 @@ +import Layout from '../components/Layout'; +import React from 'react'; + +const cards = [ + { + title: 'Deployed from Shuttle', + description: 'Deployed via Shuttle, a Rust-native cloud dev platform.', + href: 'https://www.shuttle.rs', + }, + { + title: 'Learn About Rust', + description: 'Rust is a brilliant language for writing memory-safe, efficient software.', + href: 'https://doc.rust-lang.org/book/', + }, + { + title: 'Learn About Next.js', + description: 'Next.js is a React-based meta-framework at the forefront of JavaScript.', + href: 'https://nextjs.org/', + }, + { + title: 'Join the community', + description: 'Join a thriving community with like-minded Rustaceans and web developers.', + href: 'https://discord.com/invite/shuttle', + }, +]; + +export default function Home() { + return ( + <> + +
+

+ Welcome to Next.js + Rust SaaS Template +

+ +
+ +

+ Powered by{' '} + + 🚀 Shuttle + +

+
+ + + ); +} diff --git a/fullstack-templates/saas/src/pages/login.tsx b/fullstack-templates/saas/src/pages/login.tsx new file mode 100644 index 00000000..1f74b94c --- /dev/null +++ b/fullstack-templates/saas/src/pages/login.tsx @@ -0,0 +1,199 @@ +import Layout from '../components/Layout'; +import React from 'react'; +import { useRouter } from 'next/router'; +import { accountStore } from '../zustandStore'; +import Link from 'next/link'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faAt, faEye, faEyeSlash, faLock } from '@fortawesome/free-solid-svg-icons'; + +export default function Home() { + const [loginEmail, setLoginEmail] = React.useState(''); + const [pw, setPw] = React.useState(''); + const [pwVis, setPwVis] = React.useState(false); + + const { email, changeEmail } = accountStore(); + + let router = useRouter(); + + const handleSubmit = async (e: React.SyntheticEvent) => { + e.preventDefault(); + + const url = `//${window.location.host}/api/auth/login`; + + try { + let res = await fetch(url, { + method: 'POST', + mode: 'cors', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + email: loginEmail, + password: pw, + }), + }); + + if (res.ok) { + changeEmail(loginEmail); + router.push('/dashboard'); + } else { + console.log('Incorrect login details.'); + } + } catch (e: any) { + console.log(`Error: ${e}`); + } + }; + + const togglePassword = (e: React.SyntheticEvent) => { + e.preventDefault(); + + setPwVis(!pwVis); + }; + + return ( + <> + +
+
+

Welcome Back

+
+ +
+ + setLoginEmail((e.target as HTMLInputElement).value)} + placeholder="Enter your email" + /> +
+ + +
+ + + setPw((e.target as HTMLInputElement).value)} + placeholder="Enter your password" + /> + +
+ +
+ +
+
+
+
+ + Don't have an account? + + Register now + + +
+
+
+ + ); +} diff --git a/fullstack-templates/saas/src/pages/pricing.tsx b/fullstack-templates/saas/src/pages/pricing.tsx new file mode 100644 index 00000000..53ad929c --- /dev/null +++ b/fullstack-templates/saas/src/pages/pricing.tsx @@ -0,0 +1,57 @@ +import Layout from "@/components/Layout" +import Link from 'next/link' + +export default function Home() { + return ( + <> + +
+

Pricing

+
+
+ +

Basic

+
    +
  • Lorem ipsum
  • +
  • Lorem ipsum
  • +
  • Lorem ipsum
  • +
  • Lorem ipsum
  • +
  • Lorem ipsum
  • +
+ Get Started +
+
+ +

Premium

+
    +
  • Everything in Basic!
  • +
  • Lorem ipsum
  • +
  • Lorem ipsum
  • +
  • Lorem ipsum
  • +
  • Lorem ipsum
  • +
  • Lorem ipsum
  • +
+ Get Started +
+ +
+ +

Corporate

+
    +
  • Everything in Premium!
  • +
  • Lorem ipsum
  • +
  • Lorem ipsum
  • +
  • Lorem ipsum
  • +
  • Lorem ipsum
  • +
  • Lorem ipsum
  • +
+ Get Started +
+ +
+
+ +
+ + ) +} diff --git a/fullstack-templates/saas/src/pages/register.tsx b/fullstack-templates/saas/src/pages/register.tsx new file mode 100644 index 00000000..acf8be8f --- /dev/null +++ b/fullstack-templates/saas/src/pages/register.tsx @@ -0,0 +1,284 @@ +import Layout from '../components/Layout'; +import React from 'react'; +import { useRouter } from 'next/router'; +import Link from 'next/link'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { + faAt, + faEye, + faEyeSlash, + faFaceFrownOpen, + faLock, + faMailBulk, + faPassport, + faUser, + faUserAlt, + faUserCircle, + faUserDoctor, +} from '@fortawesome/free-solid-svg-icons'; + +export default function Register() { + const [name, setName] = React.useState(''); + const [email, setEmail] = React.useState(''); + const [pw, setPw] = React.useState(''); + const [pwConfirm, setPwConfirm] = React.useState(''); + const [pwVis, setPwVis] = React.useState(false); + + let router = useRouter(); + + const handleSubmit = async (e: React.SyntheticEvent) => { + e.preventDefault(); + + const url = `//${window.location.host}/api/auth/register`; + + try { + await fetch(url, { + method: 'POST', + mode: 'cors', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + name: name, + email: email, + password: pw, + }), + }); + + router.push('/login'); + } catch (e: any) { + console.log(`Error: ${e}`); + } + }; + + const togglePassword = (e: React.SyntheticEvent) => { + e.preventDefault(); + + setPwVis(!pwVis); + }; + + return ( + +
+
+

Register

+ +
+ +
+ + setName((e.target as HTMLInputElement).value)} + placeholder="Enter your name" + /> +
+ + +
+ + setEmail((e.target as HTMLInputElement).value)} + placeholder="Enter your email" + /> +
+ + +
+ + setPw((e.target as HTMLInputElement).value)} + placeholder="Enter your password" + /> + +
+ + +
+ + setPwConfirm((e.target as HTMLInputElement).value)} + placeholder="Confirm your password" + /> + +
+ +
+ +
+
+
+
+ + You have an account? + + Login here + + +
+
+
+ ); +} diff --git a/fullstack-templates/saas/src/styles/globals.css b/fullstack-templates/saas/src/styles/globals.css new file mode 100644 index 00000000..b20985b4 --- /dev/null +++ b/fullstack-templates/saas/src/styles/globals.css @@ -0,0 +1,10 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap'); + +@tailwind base; +@tailwind components; +@tailwind utilities; + +html { + font-family: 'Poppins', sans-serif; + background-color: #172554; +} \ No newline at end of file diff --git a/fullstack-templates/saas/src/zustandStore.ts b/fullstack-templates/saas/src/zustandStore.ts new file mode 100644 index 00000000..81f68d73 --- /dev/null +++ b/fullstack-templates/saas/src/zustandStore.ts @@ -0,0 +1,23 @@ +import { create } from 'zustand' +import {persist, createJSONStorage} from 'zustand/middleware' + +interface AcctState { + name: string, + changeName: (to: string) => void, + email: string, + changeEmail: (to: string) => void, +} + +export const accountStore = create()(persist((set, get) => ({ + name: "", + changeName: (to) => set({name: to}), + email: "", + changeEmail: (to) => set({email: to}), + }), + + {name: 'user', + storage: createJSONStorage(() => sessionStorage), +} + +) +) \ No newline at end of file diff --git a/fullstack-templates/saas/tailwind.config.js b/fullstack-templates/saas/tailwind.config.js new file mode 100644 index 00000000..63ceab57 --- /dev/null +++ b/fullstack-templates/saas/tailwind.config.js @@ -0,0 +1,13 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + './src/pages/**/*.{js,ts,jsx,tsx}', + './src/components/**/*.{js,ts,jsx,tsx}', + './src/app/**/*.{js,ts,jsx,tsx}', + ], + theme: { + extend: { + }, + }, + plugins: [], +} diff --git a/fullstack-templates/saas/tsconfig.json b/fullstack-templates/saas/tsconfig.json new file mode 100644 index 00000000..61c19abd --- /dev/null +++ b/fullstack-templates/saas/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"] +} From 0fe92a1612f778a5ad7b729f6f9cb115479c1d7a Mon Sep 17 00:00:00 2001 From: Joshua Mo <102877324+joshua-mo-143@users.noreply.github.com> Date: Fri, 19 May 2023 14:29:31 +0100 Subject: [PATCH 062/239] fix: make Stripe payment price a secret instead of hardcoding (#51) Co-authored-by: Joshua Mo --- fullstack-templates/saas/backend/src/main.rs | 8 +++++++- fullstack-templates/saas/backend/src/payments.rs | 6 +++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/fullstack-templates/saas/backend/src/main.rs b/fullstack-templates/saas/backend/src/main.rs index fc28b0eb..4e2dcdc0 100644 --- a/fullstack-templates/saas/backend/src/main.rs +++ b/fullstack-templates/saas/backend/src/main.rs @@ -23,6 +23,7 @@ use router::create_api_router; pub struct AppState { pub postgres: PgPool, pub stripe_key: String, + pub stripe_sub_price: String, pub mailgun_key: String, pub mailgun_url: String, pub domain: String, @@ -51,6 +52,7 @@ async fn axum( let state = AppState { postgres, stripe_key, + stripe_sub_price, mailgun_key, mailgun_url, domain, @@ -79,6 +81,10 @@ fn grab_secrets(secrets: shuttle_secrets::SecretStore) -> (String, String, Strin .get("STRIPE_KEY") .unwrap_or_else(|| "None".to_string()); + let stripe_sub_price = secrets + .get("STRIPE_SUB_PRICE") + .unwrap_or_else(|| "None".to_string()); + let mailgun_key = secrets .get("MAILGUN_KEY") .unwrap_or_else(|| "None".to_string()); @@ -91,5 +97,5 @@ fn grab_secrets(secrets: shuttle_secrets::SecretStore) -> (String, String, Strin .get("DOMAIN_URL") .unwrap_or_else(|| "None".to_string()); - (stripe_key, mailgun_key, mailgun_url, domain) + (stripe_key, stripe_sub_price, mailgun_key, mailgun_url, domain) } diff --git a/fullstack-templates/saas/backend/src/payments.rs b/fullstack-templates/saas/backend/src/payments.rs index 85fa17de..ec5de90d 100644 --- a/fullstack-templates/saas/backend/src/payments.rs +++ b/fullstack-templates/saas/backend/src/payments.rs @@ -73,7 +73,7 @@ pub async fn create_checkout( pm }; - let mut params = create_checkout_params(customer.id); + let mut params = create_checkout_params(customer.id, state.stripe_sub_price); params.default_payment_method = Some(&payment_method.id); @@ -84,10 +84,10 @@ pub async fn create_checkout( Ok(StatusCode::OK) } -fn create_checkout_params(customer_id: CustomerId) -> CreateSubscription<'static> { +fn create_checkout_params(customer_id: CustomerId, price: String) -> CreateSubscription<'static> { let mut params = CreateSubscription::new(customer_id); params.items = Some(vec![CreateSubscriptionItems { - price: Some("price_1Mxby1I1KxxteAOMLAMeWgQD".to_string()), + price: Some(price), ..Default::default() }]); params.expand = &["items", "items.data.price.product", "schedule"]; From 9ade4b105ecaae23a0378b8c2c88ef5fbb18554a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Mon, 22 May 2023 11:00:57 +0200 Subject: [PATCH 063/239] chore: v0.17.0 (#49) * chore: v0.17.0 * custom/request-scheduler: update to 0.17.0 * saas: updated deps versions --------- Co-authored-by: Iulian Barbu --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 6 +++--- axum/hello-world/Cargo.toml | 4 ++-- axum/static-files/Cargo.toml | 6 +++--- axum/static-next-server/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 6 +++--- custom/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 10 +++++----- next/hello-world/Cargo.toml | 2 +- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/dyn_template_hbs/Cargo.toml | 6 +++--- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 31 files changed, 82 insertions(+), 82 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index ea296a0e..fc94d578 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } +shuttle-actix-web = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } tokio = { version = "1.26.0" } diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 9b657a91..285962b0 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } +shuttle-actix-web = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } serde = "1.0.148" -shuttle-shared-db = { version = "0.16.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.17.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 0890d70d..a1a488dd 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,8 +13,8 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } -shuttle-static-folder = "0.16.0" +shuttle-actix-web = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } +shuttle-static-folder = "0.17.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 7ed2f03a..3aecfae8 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } +shuttle-axum = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } tokio = { version = "1.26.0" } diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 297c8ee9..57921561 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } -shuttle-static-folder = "0.16.0" +shuttle-axum = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } +shuttle-static-folder = "0.17.0" tokio = { version = "1.26.0" } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 3e9eb810..88c9c010 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } -shuttle-static-folder = "0.16.0" +shuttle-axum = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } +shuttle-static-folder = "0.17.0" tokio = { version = "1.26.0" } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 04992a12..ff7ba15a 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,8 +11,8 @@ hyper = { version = "0.14.23", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-axum = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } -shuttle-static-folder = "0.16.0" +shuttle-axum = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } +shuttle-static-folder = "0.17.0" tokio = { version = "1.26.0" } tower-http = { version = "0.3.0", features = ["fs"] } diff --git a/custom/request-scheduler/Cargo.toml b/custom/request-scheduler/Cargo.toml index 58fdcbcc..983ee4c0 100644 --- a/custom/request-scheduler/Cargo.toml +++ b/custom/request-scheduler/Cargo.toml @@ -12,6 +12,6 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.16.0" -shuttle-runtime = "0.16.0" +shuttle-persist = "0.17.0" +shuttle-runtime = "0.17.0" tokio = "1.28.0" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index bad1434c..89c37c68 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,11 +16,11 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.16.0" -shuttle-runtime = "0.16.0" -shuttle-secrets = "0.16.0" -shuttle-shared-db = { version = "0.16.0", features = ["postgres"] } -shuttle-static-folder = "0.16.0" +shuttle-axum = "0.17.0" +shuttle-runtime = "0.17.0" +shuttle-secrets = "0.17.0" +shuttle-shared-db = { version = "0.17.0", features = ["postgres"] } +shuttle-static-folder = "0.17.0" sqlx = { version = "0.6.3", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index cf57762f..f4e3dba6 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -8,6 +8,6 @@ crate-type = [ "cdylib" ] [dependencies] # TODO: bump to 0.9 before merge -shuttle-next = "0.16.0" +shuttle-next = "0.17.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index f086ac0e..cc1565a0 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } +shuttle-poem = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } tokio = { version = "1.26.0" } diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 12acb4ae..c3f179ea 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = { version = "0.16.0" } -shuttle-shared-db = { version = "0.16.0", features = ["mongodb"] } -shuttle-runtime = { version = "0.16.0" } +shuttle-poem = { version = "0.17.0" } +shuttle-shared-db = { version = "0.17.0", features = ["mongodb"] } +shuttle-runtime = { version = "0.17.0" } serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = { version = "1.26.0" } diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 758f4dae..aa54a916 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } -shuttle-shared-db = { version = "0.16.0", features = ["postgres"] } +shuttle-poem = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } +shuttle-shared-db = { version = "0.17.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 4bf3ba71..25bfb24b 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } -shuttle-secrets = "0.16.0" +shuttle-poise = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } +shuttle-secrets = "0.17.0" tracing = "0.1.37" tokio = { version = "1.26.0" } diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index 0d7bc2da..c302a3a6 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } +shuttle-rocket = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } tokio = { version = "1.26.0" } diff --git a/rocket/dyn_template_hbs/Cargo.toml b/rocket/dyn_template_hbs/Cargo.toml index 861c1c7f..1eb5dafd 100644 --- a/rocket/dyn_template_hbs/Cargo.toml +++ b/rocket/dyn_template_hbs/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } -shuttle-static-folder = "0.16.0" +shuttle-rocket = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } +shuttle-static-folder = "0.17.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = { version = "1.26.0" } diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 4092f7ac..7e0ccee9 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } +shuttle-rocket = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } tokio = { version = "1.26.0" } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 8630ec8e..8119573f 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.16.0" -shuttle-rocket = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } +shuttle-persist = "0.17.0" +shuttle-rocket = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } tokio = { version = "1.26.0" } diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 67822146..9e3fc648 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.16.0", features = ["postgres"] } -shuttle-rocket = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } +shuttle-shared-db = { version = "0.17.0", features = ["postgres"] } +shuttle-rocket = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 688f12e7..e935960c 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } -shuttle-secrets = "0.16.0" +shuttle-rocket = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } +shuttle-secrets = "0.17.0" tokio = { version = "1.26.0" } diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 2b5ba91d..630f05f5 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } +shuttle-rocket = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } serde = "1.0.148" -shuttle-shared-db = { version = "0.16.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.17.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 2f81def3..78cb83c2 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } +shuttle-rocket = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } tokio = { version = "1.26.0" } diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 8f4e7ad5..17a30f97 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } +shuttle-salvo = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } tokio = { version = "1.26.0" } diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index fe7fb7be..624fa917 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } +shuttle-serenity = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.16.0" +shuttle-secrets = "0.17.0" tokio = { version = "1.26.0" } tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 057b6e2d..e0cc8144 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.16.0" -shuttle-serenity = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } -shuttle-shared-db = { version = "0.16.0", features = ["postgres"] } +shuttle-secrets = "0.17.0" +shuttle-serenity = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } +shuttle-shared-db = { version = "0.17.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 83bb5e48..2bbccf38 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } +shuttle-thruster = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = { version = "1.26.0" } diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 68e0dd79..6dbe9779 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.16.0", features = ["postgres"] } -shuttle-thruster = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } +shuttle-aws-rds = { version = "0.17.0", features = ["postgres"] } +shuttle-thruster = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = { version = "1.26.0" } diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 565be4af..395412ac 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = { version = "0.16.0" } -shuttle-runtime = { version = "0.16.0" } +shuttle-tide = { version = "0.17.0" } +shuttle-runtime = { version = "0.17.0" } tokio = { version = "1.26.0" } tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index 9b274e8d..1990e3e0 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.16.0", features = ["postgres"] } -shuttle-runtime = { version = "0.16.0" } -shuttle-tide = { version = "0.16.0" } +shuttle-aws-rds = { version = "0.17.0", features = ["postgres"] } +shuttle-runtime = { version = "0.17.0" } +shuttle-tide = { version = "0.17.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 2ce12195..3289d4db 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = { version = "0.16.0" } -shuttle-tower = { version = "0.16.0" } +shuttle-runtime = { version = "0.17.0" } +shuttle-tower = { version = "0.17.0" } tower = { version = "0.4.13", features = ["full"] } tokio = { version = "1.26.0" } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 1750c157..b79e19aa 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = { version = "0.16.0" } -shuttle-warp = { version = "0.16.0" } +shuttle-runtime = { version = "0.17.0" } +shuttle-warp = { version = "0.17.0" } tokio = { version = "1.26.0" } warp = "0.3.3" From 724f0653a219a5ba5a396856d5ffb3bec2d97d25 Mon Sep 17 00:00:00 2001 From: Ofer Affias Date: Wed, 31 May 2023 10:17:33 +0300 Subject: [PATCH 064/239] fix call to grab_secrets (#53) --- fullstack-templates/saas/backend/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fullstack-templates/saas/backend/src/main.rs b/fullstack-templates/saas/backend/src/main.rs index 4e2dcdc0..3d4b22d3 100644 --- a/fullstack-templates/saas/backend/src/main.rs +++ b/fullstack-templates/saas/backend/src/main.rs @@ -47,7 +47,7 @@ async fn axum( .await .expect("Had some errors running migrations :("); - let (stripe_key, mailgun_key, mailgun_url, domain) = grab_secrets(secrets); + let (stripe_key, stripe_sub_price, mailgun_key, mailgun_url, domain) = grab_secrets(secrets); let state = AppState { postgres, @@ -76,7 +76,7 @@ async fn axum( Ok(router.into()) } -fn grab_secrets(secrets: shuttle_secrets::SecretStore) -> (String, String, String, String) { +fn grab_secrets(secrets: shuttle_secrets::SecretStore) -> (String, String, String, String, String) { let stripe_key = secrets .get("STRIPE_KEY") .unwrap_or_else(|| "None".to_string()); From dc9d1ffb0bec5076315067333c19528461deb629 Mon Sep 17 00:00:00 2001 From: Zisulin Morbrot <22527555+morlinbrot@users.noreply.github.com> Date: Mon, 5 Jun 2023 10:20:00 +0200 Subject: [PATCH 065/239] feat: Add an axum/with-state example using updated generic AxumService (#52) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Add an axum/with-state example using updated generic AxumService * chore: Remove local dependencies * chore: bump to v0.18 --------- Co-authored-by: Oddbjørn Grødem <29732646+oddgrd@users.noreply.github.com> --- axum/with-state/Cargo.toml | 10 ++++++++++ axum/with-state/src/main.rs | 23 +++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 axum/with-state/Cargo.toml create mode 100644 axum/with-state/src/main.rs diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml new file mode 100644 index 00000000..2baff2fc --- /dev/null +++ b/axum/with-state/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "with-state" +version = "0.1.0" +edition = "2021" + +[dependencies] +axum = "0.6.10" +shuttle-axum = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } +tokio = { version = "1.26.0" } diff --git a/axum/with-state/src/main.rs b/axum/with-state/src/main.rs new file mode 100644 index 00000000..58b284ff --- /dev/null +++ b/axum/with-state/src/main.rs @@ -0,0 +1,23 @@ +use std::sync::Arc; + +use axum::{extract::State, response::IntoResponse, routing::get, Router}; + +async fn hello_world(State(state): State>) -> impl IntoResponse { + state.msg +} + +#[derive(Clone)] +struct AppState { + msg: &'static str, +} + +#[shuttle_runtime::main] +async fn axum() -> shuttle_axum::ShuttleAxum { + let state = Arc::new(AppState { + msg: "Hello, world!", + }); + + let router = Router::new().route("/", get(hello_world)).with_state(state); + + Ok(router.into()) +} From 2a7ce1fd3373335563b2c829b491dcaa19793d3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Mon, 5 Jun 2023 10:21:03 +0200 Subject: [PATCH 066/239] chore: v0.18.0 (#56) --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 6 +++--- axum/hello-world/Cargo.toml | 4 ++-- axum/static-files/Cargo.toml | 6 +++--- axum/static-next-server/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 6 +++--- custom/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 10 +++++----- next/hello-world/Cargo.toml | 2 +- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/dyn_template_hbs/Cargo.toml | 6 +++--- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 31 files changed, 82 insertions(+), 82 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index fc94d578..947ace2c 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } +shuttle-actix-web = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } tokio = { version = "1.26.0" } diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 285962b0..7c378f9e 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } +shuttle-actix-web = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } serde = "1.0.148" -shuttle-shared-db = { version = "0.17.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.18.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index a1a488dd..b07f660b 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,8 +13,8 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } -shuttle-static-folder = "0.17.0" +shuttle-actix-web = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } +shuttle-static-folder = "0.18.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 3aecfae8..46226119 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } +shuttle-axum = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } tokio = { version = "1.26.0" } diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 57921561..ef80e5d1 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } -shuttle-static-folder = "0.17.0" +shuttle-axum = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } +shuttle-static-folder = "0.18.0" tokio = { version = "1.26.0" } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 88c9c010..d5c08326 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } -shuttle-static-folder = "0.17.0" +shuttle-axum = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } +shuttle-static-folder = "0.18.0" tokio = { version = "1.26.0" } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index ff7ba15a..194508b3 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,8 +11,8 @@ hyper = { version = "0.14.23", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-axum = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } -shuttle-static-folder = "0.17.0" +shuttle-axum = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } +shuttle-static-folder = "0.18.0" tokio = { version = "1.26.0" } tower-http = { version = "0.3.0", features = ["fs"] } diff --git a/custom/request-scheduler/Cargo.toml b/custom/request-scheduler/Cargo.toml index 983ee4c0..b6f443e9 100644 --- a/custom/request-scheduler/Cargo.toml +++ b/custom/request-scheduler/Cargo.toml @@ -12,6 +12,6 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.17.0" -shuttle-runtime = "0.17.0" +shuttle-persist = "0.18.0" +shuttle-runtime = "0.18.0" tokio = "1.28.0" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 89c37c68..231d0b86 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,11 +16,11 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.17.0" -shuttle-runtime = "0.17.0" -shuttle-secrets = "0.17.0" -shuttle-shared-db = { version = "0.17.0", features = ["postgres"] } -shuttle-static-folder = "0.17.0" +shuttle-axum = "0.18.0" +shuttle-runtime = "0.18.0" +shuttle-secrets = "0.18.0" +shuttle-shared-db = { version = "0.18.0", features = ["postgres"] } +shuttle-static-folder = "0.18.0" sqlx = { version = "0.6.3", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index f4e3dba6..d137c3d9 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -8,6 +8,6 @@ crate-type = [ "cdylib" ] [dependencies] # TODO: bump to 0.9 before merge -shuttle-next = "0.17.0" +shuttle-next = "0.18.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index cc1565a0..d4cd124e 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } +shuttle-poem = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } tokio = { version = "1.26.0" } diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index c3f179ea..ac513869 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = { version = "0.17.0" } -shuttle-shared-db = { version = "0.17.0", features = ["mongodb"] } -shuttle-runtime = { version = "0.17.0" } +shuttle-poem = { version = "0.18.0" } +shuttle-shared-db = { version = "0.18.0", features = ["mongodb"] } +shuttle-runtime = { version = "0.18.0" } serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = { version = "1.26.0" } diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index aa54a916..ca7929bb 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } -shuttle-shared-db = { version = "0.17.0", features = ["postgres"] } +shuttle-poem = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } +shuttle-shared-db = { version = "0.18.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 25bfb24b..a33ad600 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } -shuttle-secrets = "0.17.0" +shuttle-poise = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } +shuttle-secrets = "0.18.0" tracing = "0.1.37" tokio = { version = "1.26.0" } diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index c302a3a6..d105a877 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } +shuttle-rocket = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } tokio = { version = "1.26.0" } diff --git a/rocket/dyn_template_hbs/Cargo.toml b/rocket/dyn_template_hbs/Cargo.toml index 1eb5dafd..0821ab48 100644 --- a/rocket/dyn_template_hbs/Cargo.toml +++ b/rocket/dyn_template_hbs/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } -shuttle-static-folder = "0.17.0" +shuttle-rocket = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } +shuttle-static-folder = "0.18.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = { version = "1.26.0" } diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 7e0ccee9..a5dbb540 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } +shuttle-rocket = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } tokio = { version = "1.26.0" } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 8119573f..599955d0 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.17.0" -shuttle-rocket = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } +shuttle-persist = "0.18.0" +shuttle-rocket = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } tokio = { version = "1.26.0" } diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 9e3fc648..964468e6 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.17.0", features = ["postgres"] } -shuttle-rocket = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } +shuttle-shared-db = { version = "0.18.0", features = ["postgres"] } +shuttle-rocket = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index e935960c..329d34a4 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } -shuttle-secrets = "0.17.0" +shuttle-rocket = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } +shuttle-secrets = "0.18.0" tokio = { version = "1.26.0" } diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 630f05f5..fa0ae662 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } +shuttle-rocket = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } serde = "1.0.148" -shuttle-shared-db = { version = "0.17.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.18.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 78cb83c2..a1ae9e29 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } +shuttle-rocket = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } tokio = { version = "1.26.0" } diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 17a30f97..72cc80cf 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } +shuttle-salvo = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } tokio = { version = "1.26.0" } diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 624fa917..35ccab0a 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } +shuttle-serenity = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.17.0" +shuttle-secrets = "0.18.0" tokio = { version = "1.26.0" } tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index e0cc8144..c3f47ab7 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.17.0" -shuttle-serenity = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } -shuttle-shared-db = { version = "0.17.0", features = ["postgres"] } +shuttle-secrets = "0.18.0" +shuttle-serenity = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } +shuttle-shared-db = { version = "0.18.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 2bbccf38..14dcba73 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } +shuttle-thruster = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = { version = "1.26.0" } diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 6dbe9779..d8d0bf50 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.17.0", features = ["postgres"] } -shuttle-thruster = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } +shuttle-aws-rds = { version = "0.18.0", features = ["postgres"] } +shuttle-thruster = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = { version = "1.26.0" } diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 395412ac..638b946e 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = { version = "0.17.0" } -shuttle-runtime = { version = "0.17.0" } +shuttle-tide = { version = "0.18.0" } +shuttle-runtime = { version = "0.18.0" } tokio = { version = "1.26.0" } tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index 1990e3e0..7803fa84 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.17.0", features = ["postgres"] } -shuttle-runtime = { version = "0.17.0" } -shuttle-tide = { version = "0.17.0" } +shuttle-aws-rds = { version = "0.18.0", features = ["postgres"] } +shuttle-runtime = { version = "0.18.0" } +shuttle-tide = { version = "0.18.0" } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = { version = "1.26.0" } tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 3289d4db..e7abccff 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = { version = "0.17.0" } -shuttle-tower = { version = "0.17.0" } +shuttle-runtime = { version = "0.18.0" } +shuttle-tower = { version = "0.18.0" } tower = { version = "0.4.13", features = ["full"] } tokio = { version = "1.26.0" } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index b79e19aa..7f03f937 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = { version = "0.17.0" } -shuttle-warp = { version = "0.17.0" } +shuttle-runtime = { version = "0.18.0" } +shuttle-warp = { version = "0.18.0" } tokio = { version = "1.26.0" } warp = "0.3.3" From 09895b1beb689b4def47048e74fb2735eed8870f Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 7 Jun 2023 08:17:57 +0200 Subject: [PATCH 067/239] feat: template for empty custom service (#59) --- custom/none/Cargo.toml | 9 +++++++++ custom/none/src/main.rs | 16 ++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 custom/none/Cargo.toml create mode 100644 custom/none/src/main.rs diff --git a/custom/none/Cargo.toml b/custom/none/Cargo.toml new file mode 100644 index 00000000..5b66da3e --- /dev/null +++ b/custom/none/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "none" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +shuttle-runtime = "0.18.0" +tokio = "1" diff --git a/custom/none/src/main.rs b/custom/none/src/main.rs new file mode 100644 index 00000000..cf7c68da --- /dev/null +++ b/custom/none/src/main.rs @@ -0,0 +1,16 @@ +#[shuttle_runtime::main] +async fn shuttle_main() -> Result { + Ok(MyService {}) +} + +// Customize this struct with things from `shuttle_main` needed in `bind`, +// such as secrets or database connections +struct MyService {} + +#[shuttle_runtime::async_trait] +impl shuttle_runtime::Service for MyService { + async fn bind(self, _addr: std::net::SocketAddr) -> Result<(), shuttle_runtime::Error> { + // Start your service and bind to the socket address + Ok(()) + } +} From 85f4cb2888657dde926ad70af485c011b3bd9dbb Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 7 Jun 2023 09:49:18 +0200 Subject: [PATCH 068/239] fix: remove unnecessary version tags (#58) --- actix-web/hello-world/Cargo.toml | 6 +++--- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 6 +++--- axum/static-next-server/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 6 +++--- axum/with-state/Cargo.toml | 6 +++--- next/hello-world/Cargo.toml | 1 - poem/hello-world/Cargo.toml | 6 +++--- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 6 +++--- rocket/dyn_template_hbs/Cargo.toml | 6 +++--- rocket/hello-world/Cargo.toml | 6 +++--- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 6 +++--- salvo/hello-world/Cargo.toml | 6 +++--- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 6 +++--- thruster/hello-world/Cargo.toml | 6 +++--- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 6 +++--- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 6 +++--- warp/hello-world/Cargo.toml | 6 +++--- 30 files changed, 86 insertions(+), 87 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 947ace2c..a852fac1 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } -tokio = { version = "1.26.0" } +shuttle-actix-web = "0.18.0" +shuttle-runtime = "0.18.0" +tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 7c378f9e..7aaa62d1 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } +shuttle-actix-web = "0.18.0" +shuttle-runtime = "0.18.0" serde = "1.0.148" shuttle-shared-db = { version = "0.18.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } -tokio = { version = "1.26.0" } +tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index b07f660b..e1bc09df 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,8 +13,8 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } +shuttle-actix-web = "0.18.0" +shuttle-runtime = "0.18.0" shuttle-static-folder = "0.18.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 46226119..51291288 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } -tokio = { version = "1.26.0" } +shuttle-axum = "0.18.0" +shuttle-runtime = "0.18.0" +tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index ef80e5d1..79f9f5b2 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } +shuttle-axum = "0.18.0" +shuttle-runtime = "0.18.0" shuttle-static-folder = "0.18.0" -tokio = { version = "1.26.0" } +tokio = "1.26.0" diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index d5c08326..ffc51515 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } +shuttle-axum = "0.18.0" +shuttle-runtime = "0.18.0" shuttle-static-folder = "0.18.0" -tokio = { version = "1.26.0" } +tokio = "1.26.0" diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 194508b3..f5eb7697 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,8 +11,8 @@ hyper = { version = "0.14.23", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-axum = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } +shuttle-axum = "0.18.0" +shuttle-runtime = "0.18.0" shuttle-static-folder = "0.18.0" -tokio = { version = "1.26.0" } +tokio = "1.26.0" tower-http = { version = "0.3.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index 2baff2fc..99eb6c92 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } -tokio = { version = "1.26.0" } +shuttle-axum = "0.18.0" +shuttle-runtime = "0.18.0" +tokio = "1.26.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index d137c3d9..2421eff3 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -# TODO: bump to 0.9 before merge shuttle-next = "0.18.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index d4cd124e..c2fe7048 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } -tokio = { version = "1.26.0" } +shuttle-poem = "0.18.0" +shuttle-runtime = "0.18.0" +tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index ac513869..2f10c73d 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = { version = "0.18.0" } +shuttle-poem = "0.18.0" shuttle-shared-db = { version = "0.18.0", features = ["mongodb"] } -shuttle-runtime = { version = "0.18.0" } +shuttle-runtime = "0.18.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -tokio = { version = "1.26.0" } +tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index ca7929bb..acac54b6 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } +shuttle-poem = "0.18.0" +shuttle-runtime = "0.18.0" shuttle-shared-db = { version = "0.18.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } -tokio = { version = "1.26.0" } +tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index a33ad600..d8d292e4 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } +shuttle-poise = "0.18.0" +shuttle-runtime = "0.18.0" shuttle-secrets = "0.18.0" tracing = "0.1.37" -tokio = { version = "1.26.0" } +tokio = "1.26.0" diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index d105a877..d088f5a7 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } -tokio = { version = "1.26.0" } +shuttle-rocket = "0.18.0" +shuttle-runtime = "0.18.0" +tokio = "1.26.0" diff --git a/rocket/dyn_template_hbs/Cargo.toml b/rocket/dyn_template_hbs/Cargo.toml index 0821ab48..b4e4d4be 100644 --- a/rocket/dyn_template_hbs/Cargo.toml +++ b/rocket/dyn_template_hbs/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } +shuttle-rocket = "0.18.0" +shuttle-runtime = "0.18.0" shuttle-static-folder = "0.18.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } -tokio = { version = "1.26.0" } +tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index a5dbb540..c5033dcf 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } -tokio = { version = "1.26.0" } +shuttle-rocket = "0.18.0" +shuttle-runtime = "0.18.0" +tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 599955d0..1d3597d7 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } shuttle-persist = "0.18.0" -shuttle-rocket = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } -tokio = { version = "1.26.0" } +shuttle-rocket = "0.18.0" +shuttle-runtime = "0.18.0" +tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 964468e6..315e79df 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" shuttle-shared-db = { version = "0.18.0", features = ["postgres"] } -shuttle-rocket = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } +shuttle-rocket = "0.18.0" +shuttle-runtime = "0.18.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } -tokio = { version = "1.26.0" } +tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 329d34a4..f669f89d 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } +shuttle-rocket = "0.18.0" +shuttle-runtime = "0.18.0" shuttle-secrets = "0.18.0" -tokio = { version = "1.26.0" } +tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index fa0ae662..c749436d 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } +shuttle-rocket = "0.18.0" +shuttle-runtime = "0.18.0" serde = "1.0.148" shuttle-shared-db = { version = "0.18.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } -tokio = { version = "1.26.0" } +tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index a1ae9e29..c6cb745b 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } -tokio = { version = "1.26.0" } +shuttle-rocket = "0.18.0" +shuttle-runtime = "0.18.0" +tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 72cc80cf..b7cdf62d 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } -tokio = { version = "1.26.0" } +shuttle-salvo = "0.18.0" +shuttle-runtime = "0.18.0" +tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 35ccab0a..970be6e5 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } +shuttle-serenity = "0.18.0" +shuttle-runtime = "0.18.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } shuttle-secrets = "0.18.0" -tokio = { version = "1.26.0" } +tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index c3f47ab7..aad65a2a 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -8,9 +8,9 @@ anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } shuttle-secrets = "0.18.0" -shuttle-serenity = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } +shuttle-serenity = "0.18.0" +shuttle-runtime = "0.18.0" shuttle-shared-db = { version = "0.18.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } -tokio = { version = "1.26.0" } +tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 14dcba73..b0815a0e 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } +shuttle-thruster = "0.18.0" +shuttle-runtime = "0.18.0" thruster = { version = "1.3.0", features = ["hyper_server"] } -tokio = { version = "1.26.0" } +tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index d8d0bf50..1e3baf63 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -8,8 +8,8 @@ hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" shuttle-aws-rds = { version = "0.18.0", features = ["postgres"] } -shuttle-thruster = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } +shuttle-thruster = "0.18.0" +shuttle-runtime = "0.18.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } -tokio = { version = "1.26.0" } +tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 638b946e..4bc76165 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = { version = "0.18.0" } -shuttle-runtime = { version = "0.18.0" } -tokio = { version = "1.26.0" } +shuttle-tide = "0.18.0" +shuttle-runtime = "0.18.0" +tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index 7803fa84..7f571015 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } shuttle-aws-rds = { version = "0.18.0", features = ["postgres"] } -shuttle-runtime = { version = "0.18.0" } -shuttle-tide = { version = "0.18.0" } +shuttle-runtime = "0.18.0" +shuttle-tide = "0.18.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } -tokio = { version = "1.26.0" } +tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index e7abccff..73f26444 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = { version = "0.18.0" } -shuttle-tower = { version = "0.18.0" } +shuttle-runtime = "0.18.0" +shuttle-tower = "0.18.0" tower = { version = "0.4.13", features = ["full"] } -tokio = { version = "1.26.0" } +tokio = "1.26.0" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 7f03f937..ee67d6d6 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = { version = "0.18.0" } -shuttle-warp = { version = "0.18.0" } -tokio = { version = "1.26.0" } +shuttle-runtime = "0.18.0" +shuttle-warp = "0.18.0" +tokio = "1.26.0" warp = "0.3.3" From d7b5ab8f3b156e015b2347099c940027a84319e0 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Thu, 15 Jun 2023 09:55:58 +0200 Subject: [PATCH 069/239] Update & simplify axum examples, bump versions (#60) --- axum/hello-world/Cargo.toml | 4 ++-- axum/static-files/Cargo.toml | 6 +++--- axum/static-files/src/main.rs | 6 +++--- axum/websocket/Cargo.toml | 16 ++++++++-------- axum/websocket/src/main.rs | 11 ++--------- rocket/workspace/hello-world/src/main.rs | 2 +- 6 files changed, 19 insertions(+), 26 deletions(-) diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 51291288..90824e62 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = "0.6.10" +axum = "0.6.18" shuttle-axum = "0.18.0" shuttle-runtime = "0.18.0" -tokio = "1.26.0" +tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 79f9f5b2..a572f9b4 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" publish = false [dependencies] -axum = "0.6.10" -axum-extra = { version = "0.4.2", features = ["spa"] } +axum = "0.6.18" shuttle-axum = "0.18.0" shuttle-runtime = "0.18.0" shuttle-static-folder = "0.18.0" -tokio = "1.26.0" +tokio = "1.28.2" +tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-files/src/main.rs b/axum/static-files/src/main.rs index 65a504e4..8e81df59 100644 --- a/axum/static-files/src/main.rs +++ b/axum/static-files/src/main.rs @@ -1,7 +1,7 @@ use std::path::PathBuf; use axum::{routing::get, Router}; -use axum_extra::routing::SpaRouter; +use tower_http::services::ServeDir; async fn hello_world() -> &'static str { "Hello, world!" @@ -14,8 +14,8 @@ async fn axum( #[shuttle_static_folder::StaticFolder(folder = "assets")] static_folder: PathBuf, ) -> shuttle_axum::ShuttleAxum { let router = Router::new() - .route("/hello", get(hello_world)) - .merge(SpaRouter::new("/assets", static_folder).index_file("index.html")); + .route("/", get(hello_world)) + .nest_service("/assets", ServeDir::new(static_folder)); Ok(router.into()) } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index f5eb7697..b4617cf3 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -4,15 +4,15 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = { version = "0.6.10", features = ["ws"] } -chrono = { version = "0.4.23", features = ["serde"] } -futures = "0.3.25" -hyper = { version = "0.14.23", features = ["client", "http2"] } +axum = { version = "0.6.18", features = ["ws"] } +chrono = { version = "0.4.26", features = ["serde"] } +futures = "0.3.28" +hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" -serde = { version = "1.0.148", features = ["derive"] } -serde_json = "1.0.89" +serde = { version = "1.0.163", features = ["derive"] } +serde_json = "1.0.96" shuttle-axum = "0.18.0" shuttle-runtime = "0.18.0" shuttle-static-folder = "0.18.0" -tokio = "1.26.0" -tower-http = { version = "0.3.0", features = ["fs"] } +tokio = "1.28.2" +tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/websocket/src/main.rs b/axum/websocket/src/main.rs index 913a2aa7..b8b7a3bb 100644 --- a/axum/websocket/src/main.rs +++ b/axum/websocket/src/main.rs @@ -5,9 +5,8 @@ use axum::{ ws::{Message, WebSocket}, WebSocketUpgrade, }, - http::StatusCode, response::IntoResponse, - routing::{get, get_service}, + routing::get, Extension, Router, }; use chrono::{DateTime, Utc}; @@ -74,20 +73,14 @@ async fn axum(#[shuttle_static_folder::StaticFolder] static_folder: PathBuf) -> } }); - let serve_dir = get_service(ServeDir::new(static_folder)).handle_error(handle_error); - let router = Router::new() .route("/websocket", get(websocket_handler)) - .fallback_service(serve_dir) + .nest_service("/", ServeDir::new(static_folder)) .layer(Extension(state)); Ok(router.into()) } -async fn handle_error(_err: std::io::Error) -> impl IntoResponse { - (StatusCode::INTERNAL_SERVER_ERROR, "Something went wrong...") -} - async fn websocket_handler( ws: WebSocketUpgrade, Extension(state): Extension>>, diff --git a/rocket/workspace/hello-world/src/main.rs b/rocket/workspace/hello-world/src/main.rs index 61399340..2a722f6b 100644 --- a/rocket/workspace/hello-world/src/main.rs +++ b/rocket/workspace/hello-world/src/main.rs @@ -8,7 +8,7 @@ fn index() -> &'static str { #[shuttle_runtime::main] async fn rocket() -> shuttle_rocket::ShuttleRocket { - let rocket = rocket::build().mount("/hello", routes![index]); + let rocket = rocket::build().mount("/", routes![index]); Ok(rocket.into()) } From d6eaf17a8c9f9bbdc65fd85576fa0a0624a21544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Tue, 20 Jun 2023 12:27:45 +0200 Subject: [PATCH 070/239] chore: v0.19.0 (#63) --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 6 +++--- axum/hello-world/Cargo.toml | 4 ++-- axum/static-files/Cargo.toml | 6 +++--- axum/static-next-server/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 6 +++--- axum/with-state/Cargo.toml | 4 ++-- custom/none/Cargo.toml | 2 +- custom/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 10 +++++----- next/hello-world/Cargo.toml | 2 +- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/dyn_template_hbs/Cargo.toml | 6 +++--- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 33 files changed, 85 insertions(+), 85 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index a852fac1..0b7bdb4c 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.18.0" -shuttle-runtime = "0.18.0" +shuttle-actix-web = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 7aaa62d1..56c347fe 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.18.0" -shuttle-runtime = "0.18.0" +shuttle-actix-web = "0.19.0" +shuttle-runtime = "0.19.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.18.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index e1bc09df..3be79850 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,8 +13,8 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.18.0" -shuttle-runtime = "0.18.0" -shuttle-static-folder = "0.18.0" +shuttle-actix-web = "0.19.0" +shuttle-runtime = "0.19.0" +shuttle-static-folder = "0.19.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 90824e62..97f4873a 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.18.0" -shuttle-runtime = "0.18.0" +shuttle-axum = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index a572f9b4..0c4270fa 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.18.0" -shuttle-runtime = "0.18.0" -shuttle-static-folder = "0.18.0" +shuttle-axum = "0.19.0" +shuttle-runtime = "0.19.0" +shuttle-static-folder = "0.19.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index ffc51515..be504a8a 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.18.0" -shuttle-runtime = "0.18.0" -shuttle-static-folder = "0.18.0" +shuttle-axum = "0.19.0" +shuttle-runtime = "0.19.0" +shuttle-static-folder = "0.19.0" tokio = "1.26.0" diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index b4617cf3..d283c49b 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,8 +11,8 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.18.0" -shuttle-runtime = "0.18.0" -shuttle-static-folder = "0.18.0" +shuttle-axum = "0.19.0" +shuttle-runtime = "0.19.0" +shuttle-static-folder = "0.19.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index 99eb6c92..02b3c7cf 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.18.0" -shuttle-runtime = "0.18.0" +shuttle-axum = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.26.0" diff --git a/custom/none/Cargo.toml b/custom/none/Cargo.toml index 5b66da3e..04ee3396 100644 --- a/custom/none/Cargo.toml +++ b/custom/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.18.0" +shuttle-runtime = "0.19.0" tokio = "1" diff --git a/custom/request-scheduler/Cargo.toml b/custom/request-scheduler/Cargo.toml index b6f443e9..f57e84ff 100644 --- a/custom/request-scheduler/Cargo.toml +++ b/custom/request-scheduler/Cargo.toml @@ -12,6 +12,6 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.18.0" -shuttle-runtime = "0.18.0" +shuttle-persist = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.28.0" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 231d0b86..53aa1022 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,11 +16,11 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.18.0" -shuttle-runtime = "0.18.0" -shuttle-secrets = "0.18.0" -shuttle-shared-db = { version = "0.18.0", features = ["postgres"] } -shuttle-static-folder = "0.18.0" +shuttle-axum = "0.19.0" +shuttle-runtime = "0.19.0" +shuttle-secrets = "0.19.0" +shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } +shuttle-static-folder = "0.19.0" sqlx = { version = "0.6.3", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index 2421eff3..e2357e0f 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.18.0" +shuttle-next = "0.19.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index c2fe7048..b0d1fb3a 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.18.0" -shuttle-runtime = "0.18.0" +shuttle-poem = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 2f10c73d..749d84bb 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.18.0" -shuttle-shared-db = { version = "0.18.0", features = ["mongodb"] } -shuttle-runtime = "0.18.0" +shuttle-poem = "0.19.0" +shuttle-shared-db = { version = "0.19.0", features = ["mongodb"] } +shuttle-runtime = "0.19.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index acac54b6..ece70889 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.18.0" -shuttle-runtime = "0.18.0" -shuttle-shared-db = { version = "0.18.0", features = ["postgres"] } +shuttle-poem = "0.19.0" +shuttle-runtime = "0.19.0" +shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index d8d292e4..3bf311f3 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.18.0" -shuttle-runtime = "0.18.0" -shuttle-secrets = "0.18.0" +shuttle-poise = "0.19.0" +shuttle-runtime = "0.19.0" +shuttle-secrets = "0.19.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index d088f5a7..7d3900f0 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.18.0" -shuttle-runtime = "0.18.0" +shuttle-rocket = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.26.0" diff --git a/rocket/dyn_template_hbs/Cargo.toml b/rocket/dyn_template_hbs/Cargo.toml index b4e4d4be..22435a08 100644 --- a/rocket/dyn_template_hbs/Cargo.toml +++ b/rocket/dyn_template_hbs/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.18.0" -shuttle-runtime = "0.18.0" -shuttle-static-folder = "0.18.0" +shuttle-rocket = "0.19.0" +shuttle-runtime = "0.19.0" +shuttle-static-folder = "0.19.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index c5033dcf..ba48e8a2 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.18.0" -shuttle-runtime = "0.18.0" +shuttle-rocket = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 1d3597d7..7ebd4393 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.18.0" -shuttle-rocket = "0.18.0" -shuttle-runtime = "0.18.0" +shuttle-persist = "0.19.0" +shuttle-rocket = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 315e79df..bae604a8 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.18.0", features = ["postgres"] } -shuttle-rocket = "0.18.0" -shuttle-runtime = "0.18.0" +shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } +shuttle-rocket = "0.19.0" +shuttle-runtime = "0.19.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index f669f89d..e0d81a69 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = "0.18.0" -shuttle-runtime = "0.18.0" -shuttle-secrets = "0.18.0" +shuttle-rocket = "0.19.0" +shuttle-runtime = "0.19.0" +shuttle-secrets = "0.19.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index c749436d..e9a6169d 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = "0.18.0" -shuttle-runtime = "0.18.0" +shuttle-rocket = "0.19.0" +shuttle-runtime = "0.19.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.18.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index c6cb745b..abc1cae1 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.18.0" -shuttle-runtime = "0.18.0" +shuttle-rocket = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index b7cdf62d..0e626b4f 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.18.0" -shuttle-runtime = "0.18.0" +shuttle-salvo = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 970be6e5..ea343928 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.18.0" -shuttle-runtime = "0.18.0" +shuttle-serenity = "0.19.0" +shuttle-runtime = "0.19.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.18.0" +shuttle-secrets = "0.19.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index aad65a2a..99ff60ef 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.18.0" -shuttle-serenity = "0.18.0" -shuttle-runtime = "0.18.0" -shuttle-shared-db = { version = "0.18.0", features = ["postgres"] } +shuttle-secrets = "0.19.0" +shuttle-serenity = "0.19.0" +shuttle-runtime = "0.19.0" +shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index b0815a0e..04e212db 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.18.0" -shuttle-runtime = "0.18.0" +shuttle-thruster = "0.19.0" +shuttle-runtime = "0.19.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 1e3baf63..45eb2593 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.18.0", features = ["postgres"] } -shuttle-thruster = "0.18.0" -shuttle-runtime = "0.18.0" +shuttle-aws-rds = { version = "0.19.0", features = ["postgres"] } +shuttle-thruster = "0.19.0" +shuttle-runtime = "0.19.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 4bc76165..1cccdf0c 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.18.0" -shuttle-runtime = "0.18.0" +shuttle-tide = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index 7f571015..e06664d2 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.18.0", features = ["postgres"] } -shuttle-runtime = "0.18.0" -shuttle-tide = "0.18.0" +shuttle-aws-rds = { version = "0.19.0", features = ["postgres"] } +shuttle-runtime = "0.19.0" +shuttle-tide = "0.19.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 73f26444..21c30ca9 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.18.0" -shuttle-tower = "0.18.0" +shuttle-runtime = "0.19.0" +shuttle-tower = "0.19.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index ee67d6d6..9d61d62f 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.18.0" -shuttle-warp = "0.18.0" +shuttle-runtime = "0.19.0" +shuttle-warp = "0.19.0" tokio = "1.26.0" warp = "0.3.3" From 6b9eb2f3008cf7b937e20bf966da78036a201625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Tue, 27 Jun 2023 16:53:47 +0100 Subject: [PATCH 071/239] chore: v0.20.0 (#68) --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 6 +++--- axum/hello-world/Cargo.toml | 4 ++-- axum/static-files/Cargo.toml | 6 +++--- axum/static-next-server/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 6 +++--- axum/with-state/Cargo.toml | 4 ++-- custom/none/Cargo.toml | 2 +- custom/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 10 +++++----- next/hello-world/Cargo.toml | 2 +- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/dyn_template_hbs/Cargo.toml | 6 +++--- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 33 files changed, 85 insertions(+), 85 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 0b7bdb4c..6bcf785b 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-actix-web = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 56c347fe..72e3ae54 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-actix-web = "0.20.0" +shuttle-runtime = "0.20.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 3be79850..eb4e5eff 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,8 +13,8 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.19.0" -shuttle-runtime = "0.19.0" -shuttle-static-folder = "0.19.0" +shuttle-actix-web = "0.20.0" +shuttle-runtime = "0.20.0" +shuttle-static-folder = "0.20.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 97f4873a..3525f6b7 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-axum = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 0c4270fa..ae43b14a 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.19.0" -shuttle-runtime = "0.19.0" -shuttle-static-folder = "0.19.0" +shuttle-axum = "0.20.0" +shuttle-runtime = "0.20.0" +shuttle-static-folder = "0.20.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index be504a8a..6febb8cc 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.19.0" -shuttle-runtime = "0.19.0" -shuttle-static-folder = "0.19.0" +shuttle-axum = "0.20.0" +shuttle-runtime = "0.20.0" +shuttle-static-folder = "0.20.0" tokio = "1.26.0" diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index d283c49b..d6d582d0 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,8 +11,8 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.19.0" -shuttle-runtime = "0.19.0" -shuttle-static-folder = "0.19.0" +shuttle-axum = "0.20.0" +shuttle-runtime = "0.20.0" +shuttle-static-folder = "0.20.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index 02b3c7cf..6d156152 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-axum = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.26.0" diff --git a/custom/none/Cargo.toml b/custom/none/Cargo.toml index 04ee3396..ca150084 100644 --- a/custom/none/Cargo.toml +++ b/custom/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.19.0" +shuttle-runtime = "0.20.0" tokio = "1" diff --git a/custom/request-scheduler/Cargo.toml b/custom/request-scheduler/Cargo.toml index f57e84ff..966dcb88 100644 --- a/custom/request-scheduler/Cargo.toml +++ b/custom/request-scheduler/Cargo.toml @@ -12,6 +12,6 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-persist = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.28.0" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 53aa1022..cd6514c8 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,11 +16,11 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.19.0" -shuttle-runtime = "0.19.0" -shuttle-secrets = "0.19.0" -shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } -shuttle-static-folder = "0.19.0" +shuttle-axum = "0.20.0" +shuttle-runtime = "0.20.0" +shuttle-secrets = "0.20.0" +shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } +shuttle-static-folder = "0.20.0" sqlx = { version = "0.6.3", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index e2357e0f..bcffa96d 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.19.0" +shuttle-next = "0.20.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index b0d1fb3a..7fa50546 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-poem = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 749d84bb..21998d9d 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.19.0" -shuttle-shared-db = { version = "0.19.0", features = ["mongodb"] } -shuttle-runtime = "0.19.0" +shuttle-poem = "0.20.0" +shuttle-shared-db = { version = "0.20.0", features = ["mongodb"] } +shuttle-runtime = "0.20.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index ece70889..05c1ccd2 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.19.0" -shuttle-runtime = "0.19.0" -shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } +shuttle-poem = "0.20.0" +shuttle-runtime = "0.20.0" +shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 3bf311f3..b3abd1c7 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.19.0" -shuttle-runtime = "0.19.0" -shuttle-secrets = "0.19.0" +shuttle-poise = "0.20.0" +shuttle-runtime = "0.20.0" +shuttle-secrets = "0.20.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index 7d3900f0..0f9134eb 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-rocket = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.26.0" diff --git a/rocket/dyn_template_hbs/Cargo.toml b/rocket/dyn_template_hbs/Cargo.toml index 22435a08..f6ced14d 100644 --- a/rocket/dyn_template_hbs/Cargo.toml +++ b/rocket/dyn_template_hbs/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.19.0" -shuttle-runtime = "0.19.0" -shuttle-static-folder = "0.19.0" +shuttle-rocket = "0.20.0" +shuttle-runtime = "0.20.0" +shuttle-static-folder = "0.20.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index ba48e8a2..4715f82e 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-rocket = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 7ebd4393..a2da37c8 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.19.0" -shuttle-rocket = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-persist = "0.20.0" +shuttle-rocket = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index bae604a8..9d59e9f9 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } -shuttle-rocket = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } +shuttle-rocket = "0.20.0" +shuttle-runtime = "0.20.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index e0d81a69..41bd1219 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = "0.19.0" -shuttle-runtime = "0.19.0" -shuttle-secrets = "0.19.0" +shuttle-rocket = "0.20.0" +shuttle-runtime = "0.20.0" +shuttle-secrets = "0.20.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index e9a6169d..fe67f84a 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-rocket = "0.20.0" +shuttle-runtime = "0.20.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index abc1cae1..4b526675 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-rocket = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 0e626b4f..70ca51fa 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-salvo = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index ea343928..9db0b77d 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-serenity = "0.20.0" +shuttle-runtime = "0.20.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.19.0" +shuttle-secrets = "0.20.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 99ff60ef..1e98a11f 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.19.0" -shuttle-serenity = "0.19.0" -shuttle-runtime = "0.19.0" -shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } +shuttle-secrets = "0.20.0" +shuttle-serenity = "0.20.0" +shuttle-runtime = "0.20.0" +shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 04e212db..74741282 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-thruster = "0.20.0" +shuttle-runtime = "0.20.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 45eb2593..ae64fe71 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.19.0", features = ["postgres"] } -shuttle-thruster = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-aws-rds = { version = "0.20.0", features = ["postgres"] } +shuttle-thruster = "0.20.0" +shuttle-runtime = "0.20.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 1cccdf0c..0e55e466 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-tide = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index e06664d2..d0fd1993 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.19.0", features = ["postgres"] } -shuttle-runtime = "0.19.0" -shuttle-tide = "0.19.0" +shuttle-aws-rds = { version = "0.20.0", features = ["postgres"] } +shuttle-runtime = "0.20.0" +shuttle-tide = "0.20.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 21c30ca9..a7662aef 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.19.0" -shuttle-tower = "0.19.0" +shuttle-runtime = "0.20.0" +shuttle-tower = "0.20.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 9d61d62f..6fcca267 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.19.0" -shuttle-warp = "0.19.0" +shuttle-runtime = "0.20.0" +shuttle-warp = "0.20.0" tokio = "1.26.0" warp = "0.3.3" From 34d0cb4bcfc4fe797d466ae1707228c434c530fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Tue, 27 Jun 2023 17:11:01 +0100 Subject: [PATCH 072/239] Revert "chore: v0.20.0 (#68)" (#69) This reverts commit 6b9eb2f3008cf7b937e20bf966da78036a201625. --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 6 +++--- axum/hello-world/Cargo.toml | 4 ++-- axum/static-files/Cargo.toml | 6 +++--- axum/static-next-server/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 6 +++--- axum/with-state/Cargo.toml | 4 ++-- custom/none/Cargo.toml | 2 +- custom/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 10 +++++----- next/hello-world/Cargo.toml | 2 +- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/dyn_template_hbs/Cargo.toml | 6 +++--- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 33 files changed, 85 insertions(+), 85 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 6bcf785b..0b7bdb4c 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-actix-web = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 72e3ae54..56c347fe 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-actix-web = "0.19.0" +shuttle-runtime = "0.19.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index eb4e5eff..3be79850 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,8 +13,8 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.20.0" -shuttle-runtime = "0.20.0" -shuttle-static-folder = "0.20.0" +shuttle-actix-web = "0.19.0" +shuttle-runtime = "0.19.0" +shuttle-static-folder = "0.19.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 3525f6b7..97f4873a 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-axum = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index ae43b14a..0c4270fa 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.20.0" -shuttle-runtime = "0.20.0" -shuttle-static-folder = "0.20.0" +shuttle-axum = "0.19.0" +shuttle-runtime = "0.19.0" +shuttle-static-folder = "0.19.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 6febb8cc..be504a8a 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.20.0" -shuttle-runtime = "0.20.0" -shuttle-static-folder = "0.20.0" +shuttle-axum = "0.19.0" +shuttle-runtime = "0.19.0" +shuttle-static-folder = "0.19.0" tokio = "1.26.0" diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index d6d582d0..d283c49b 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,8 +11,8 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.20.0" -shuttle-runtime = "0.20.0" -shuttle-static-folder = "0.20.0" +shuttle-axum = "0.19.0" +shuttle-runtime = "0.19.0" +shuttle-static-folder = "0.19.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index 6d156152..02b3c7cf 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-axum = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.26.0" diff --git a/custom/none/Cargo.toml b/custom/none/Cargo.toml index ca150084..04ee3396 100644 --- a/custom/none/Cargo.toml +++ b/custom/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.20.0" +shuttle-runtime = "0.19.0" tokio = "1" diff --git a/custom/request-scheduler/Cargo.toml b/custom/request-scheduler/Cargo.toml index 966dcb88..f57e84ff 100644 --- a/custom/request-scheduler/Cargo.toml +++ b/custom/request-scheduler/Cargo.toml @@ -12,6 +12,6 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-persist = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.28.0" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index cd6514c8..53aa1022 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,11 +16,11 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.20.0" -shuttle-runtime = "0.20.0" -shuttle-secrets = "0.20.0" -shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } -shuttle-static-folder = "0.20.0" +shuttle-axum = "0.19.0" +shuttle-runtime = "0.19.0" +shuttle-secrets = "0.19.0" +shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } +shuttle-static-folder = "0.19.0" sqlx = { version = "0.6.3", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index bcffa96d..e2357e0f 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.20.0" +shuttle-next = "0.19.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 7fa50546..b0d1fb3a 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-poem = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 21998d9d..749d84bb 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.20.0" -shuttle-shared-db = { version = "0.20.0", features = ["mongodb"] } -shuttle-runtime = "0.20.0" +shuttle-poem = "0.19.0" +shuttle-shared-db = { version = "0.19.0", features = ["mongodb"] } +shuttle-runtime = "0.19.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 05c1ccd2..ece70889 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.20.0" -shuttle-runtime = "0.20.0" -shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } +shuttle-poem = "0.19.0" +shuttle-runtime = "0.19.0" +shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index b3abd1c7..3bf311f3 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.20.0" -shuttle-runtime = "0.20.0" -shuttle-secrets = "0.20.0" +shuttle-poise = "0.19.0" +shuttle-runtime = "0.19.0" +shuttle-secrets = "0.19.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index 0f9134eb..7d3900f0 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-rocket = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.26.0" diff --git a/rocket/dyn_template_hbs/Cargo.toml b/rocket/dyn_template_hbs/Cargo.toml index f6ced14d..22435a08 100644 --- a/rocket/dyn_template_hbs/Cargo.toml +++ b/rocket/dyn_template_hbs/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.20.0" -shuttle-runtime = "0.20.0" -shuttle-static-folder = "0.20.0" +shuttle-rocket = "0.19.0" +shuttle-runtime = "0.19.0" +shuttle-static-folder = "0.19.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 4715f82e..ba48e8a2 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-rocket = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index a2da37c8..7ebd4393 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.20.0" -shuttle-rocket = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-persist = "0.19.0" +shuttle-rocket = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 9d59e9f9..bae604a8 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } -shuttle-rocket = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } +shuttle-rocket = "0.19.0" +shuttle-runtime = "0.19.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 41bd1219..e0d81a69 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = "0.20.0" -shuttle-runtime = "0.20.0" -shuttle-secrets = "0.20.0" +shuttle-rocket = "0.19.0" +shuttle-runtime = "0.19.0" +shuttle-secrets = "0.19.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index fe67f84a..e9a6169d 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-rocket = "0.19.0" +shuttle-runtime = "0.19.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 4b526675..abc1cae1 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-rocket = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 70ca51fa..0e626b4f 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-salvo = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 9db0b77d..ea343928 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-serenity = "0.19.0" +shuttle-runtime = "0.19.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.20.0" +shuttle-secrets = "0.19.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 1e98a11f..99ff60ef 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.20.0" -shuttle-serenity = "0.20.0" -shuttle-runtime = "0.20.0" -shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } +shuttle-secrets = "0.19.0" +shuttle-serenity = "0.19.0" +shuttle-runtime = "0.19.0" +shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 74741282..04e212db 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-thruster = "0.19.0" +shuttle-runtime = "0.19.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index ae64fe71..45eb2593 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.20.0", features = ["postgres"] } -shuttle-thruster = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-aws-rds = { version = "0.19.0", features = ["postgres"] } +shuttle-thruster = "0.19.0" +shuttle-runtime = "0.19.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 0e55e466..1cccdf0c 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-tide = "0.19.0" +shuttle-runtime = "0.19.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index d0fd1993..e06664d2 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.20.0", features = ["postgres"] } -shuttle-runtime = "0.20.0" -shuttle-tide = "0.20.0" +shuttle-aws-rds = { version = "0.19.0", features = ["postgres"] } +shuttle-runtime = "0.19.0" +shuttle-tide = "0.19.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index a7662aef..21c30ca9 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.20.0" -shuttle-tower = "0.20.0" +shuttle-runtime = "0.19.0" +shuttle-tower = "0.19.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 6fcca267..9d61d62f 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.20.0" -shuttle-warp = "0.20.0" +shuttle-runtime = "0.19.0" +shuttle-warp = "0.19.0" tokio = "1.26.0" warp = "0.3.3" From 60596a04cfba33f84268d8867edc7a8b31ba4011 Mon Sep 17 00:00:00 2001 From: Jocelyn Boullier Date: Wed, 28 Jun 2023 10:44:59 +0200 Subject: [PATCH 073/239] feat: add turso example (#67) * feat: add turso example * ref(turso): remove unecessary things from the example * feat: move files, bump and lock version --------- Co-authored-by: oddgrd <29732646+oddgrd@users.noreply.github.com> --- axum/turso/Cargo.toml | 14 ++++++++ axum/turso/Secrets.dev.toml | 3 ++ axum/turso/Secrets.toml | 1 + axum/turso/Shuttle.toml | 1 + axum/turso/src/main.rs | 65 +++++++++++++++++++++++++++++++++++++ 5 files changed, 84 insertions(+) create mode 100644 axum/turso/Cargo.toml create mode 100644 axum/turso/Secrets.dev.toml create mode 100644 axum/turso/Secrets.toml create mode 100644 axum/turso/Shuttle.toml create mode 100644 axum/turso/src/main.rs diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml new file mode 100644 index 00000000..736f6485 --- /dev/null +++ b/axum/turso/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "turso-example" +version = "0.1.0" +edition = "2021" + +[dependencies] +axum = { version = "0.6.18" } +shuttle-axum = { version = "0.20.0" } +shuttle-runtime = { version = "0.20.0" } +shuttle-turso = { version = "0.20.0" } +libsql-client = "=0.30.1" +tokio = { version = "1.26.0" } +serde = { version = "1.0.164", features = ["derive"] } +serde_json = "1.0.99" diff --git a/axum/turso/Secrets.dev.toml b/axum/turso/Secrets.dev.toml new file mode 100644 index 00000000..c1c62cc9 --- /dev/null +++ b/axum/turso/Secrets.dev.toml @@ -0,0 +1,3 @@ +# You will need this if you overwrite the `local_addr` to be a remote one and run Shuttle locally. +# It will otherwise use a local SQLite database. +TURSO_DB_TOKEN = 'your-token' diff --git a/axum/turso/Secrets.toml b/axum/turso/Secrets.toml new file mode 100644 index 00000000..0634d9dc --- /dev/null +++ b/axum/turso/Secrets.toml @@ -0,0 +1 @@ +TURSO_DB_TOKEN = 'your-token' diff --git a/axum/turso/Shuttle.toml b/axum/turso/Shuttle.toml new file mode 100644 index 00000000..3ab32fe4 --- /dev/null +++ b/axum/turso/Shuttle.toml @@ -0,0 +1 @@ +name = "turso-example" diff --git a/axum/turso/src/main.rs b/axum/turso/src/main.rs new file mode 100644 index 00000000..bcf86e25 --- /dev/null +++ b/axum/turso/src/main.rs @@ -0,0 +1,65 @@ +use std::sync::Arc; + +use axum::{extract, extract::State, response::IntoResponse, routing::get, Json, Router}; +use libsql_client::{args, Client, Row, Statement, Value}; +use serde::{Deserialize, Serialize}; + +fn row_string_field(r: &Row, index: usize) -> String { + match r.values.get(index).unwrap() { + Value::Text { value } => value.clone(), + _ => unreachable!(), + } +} + +async fn get_posts(State(client): State>) -> Json> { + let rows = client.execute("select * from example_users").await.unwrap(); + let users: Vec<_> = rows + .rows + .iter() + .map(|r| User { + uid: row_string_field(r, 0), + email: row_string_field(r, 1), + }) + .collect(); + Json(users) +} + +#[derive(Debug, Deserialize, Serialize)] +struct User { + uid: String, + email: String, +} + +async fn create_users( + State(client): State>, + extract::Json(user): extract::Json, +) -> impl IntoResponse { + client + .execute(Statement::with_args( + "insert into example_users values (?, ?)", + args!(user.uid, user.email), + )) + .await + .unwrap(); + + Json(serde_json::json!({ "ok": true })) +} + +#[shuttle_runtime::main] +async fn axum( + #[shuttle_turso::Turso(addr = "libsql://your-db.turso.io", token = "{secrets.TURSO_DB_TOKEN}")] + client: Client, +) -> shuttle_axum::ShuttleAxum { + let client = Arc::new(client); + + client + .execute("create table if not exists example_users ( uid text primary key, email text );") + .await + .unwrap(); + + let router = Router::new() + .route("/", get(get_posts).post(create_users)) + .with_state(client); + + Ok(router.into()) +} From 6e2318573f570ada1a91b3226c072514129b4722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Wed, 28 Jun 2023 09:46:15 +0100 Subject: [PATCH 074/239] Revert "Revert "chore: v0.20.0 (#68)" (#69)" (#70) This reverts commit 34d0cb4bcfc4fe797d466ae1707228c434c530fd. --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 6 +++--- axum/hello-world/Cargo.toml | 4 ++-- axum/static-files/Cargo.toml | 6 +++--- axum/static-next-server/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 6 +++--- axum/with-state/Cargo.toml | 4 ++-- custom/none/Cargo.toml | 2 +- custom/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 10 +++++----- next/hello-world/Cargo.toml | 2 +- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/dyn_template_hbs/Cargo.toml | 6 +++--- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 33 files changed, 85 insertions(+), 85 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 0b7bdb4c..6bcf785b 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-actix-web = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 56c347fe..72e3ae54 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-actix-web = "0.20.0" +shuttle-runtime = "0.20.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 3be79850..eb4e5eff 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,8 +13,8 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.19.0" -shuttle-runtime = "0.19.0" -shuttle-static-folder = "0.19.0" +shuttle-actix-web = "0.20.0" +shuttle-runtime = "0.20.0" +shuttle-static-folder = "0.20.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 97f4873a..3525f6b7 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-axum = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 0c4270fa..ae43b14a 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.19.0" -shuttle-runtime = "0.19.0" -shuttle-static-folder = "0.19.0" +shuttle-axum = "0.20.0" +shuttle-runtime = "0.20.0" +shuttle-static-folder = "0.20.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index be504a8a..6febb8cc 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.19.0" -shuttle-runtime = "0.19.0" -shuttle-static-folder = "0.19.0" +shuttle-axum = "0.20.0" +shuttle-runtime = "0.20.0" +shuttle-static-folder = "0.20.0" tokio = "1.26.0" diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index d283c49b..d6d582d0 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,8 +11,8 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.19.0" -shuttle-runtime = "0.19.0" -shuttle-static-folder = "0.19.0" +shuttle-axum = "0.20.0" +shuttle-runtime = "0.20.0" +shuttle-static-folder = "0.20.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index 02b3c7cf..6d156152 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-axum = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.26.0" diff --git a/custom/none/Cargo.toml b/custom/none/Cargo.toml index 04ee3396..ca150084 100644 --- a/custom/none/Cargo.toml +++ b/custom/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.19.0" +shuttle-runtime = "0.20.0" tokio = "1" diff --git a/custom/request-scheduler/Cargo.toml b/custom/request-scheduler/Cargo.toml index f57e84ff..966dcb88 100644 --- a/custom/request-scheduler/Cargo.toml +++ b/custom/request-scheduler/Cargo.toml @@ -12,6 +12,6 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-persist = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.28.0" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 53aa1022..cd6514c8 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,11 +16,11 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.19.0" -shuttle-runtime = "0.19.0" -shuttle-secrets = "0.19.0" -shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } -shuttle-static-folder = "0.19.0" +shuttle-axum = "0.20.0" +shuttle-runtime = "0.20.0" +shuttle-secrets = "0.20.0" +shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } +shuttle-static-folder = "0.20.0" sqlx = { version = "0.6.3", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index e2357e0f..bcffa96d 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.19.0" +shuttle-next = "0.20.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index b0d1fb3a..7fa50546 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-poem = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 749d84bb..21998d9d 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.19.0" -shuttle-shared-db = { version = "0.19.0", features = ["mongodb"] } -shuttle-runtime = "0.19.0" +shuttle-poem = "0.20.0" +shuttle-shared-db = { version = "0.20.0", features = ["mongodb"] } +shuttle-runtime = "0.20.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index ece70889..05c1ccd2 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.19.0" -shuttle-runtime = "0.19.0" -shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } +shuttle-poem = "0.20.0" +shuttle-runtime = "0.20.0" +shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 3bf311f3..b3abd1c7 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.19.0" -shuttle-runtime = "0.19.0" -shuttle-secrets = "0.19.0" +shuttle-poise = "0.20.0" +shuttle-runtime = "0.20.0" +shuttle-secrets = "0.20.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index 7d3900f0..0f9134eb 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-rocket = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.26.0" diff --git a/rocket/dyn_template_hbs/Cargo.toml b/rocket/dyn_template_hbs/Cargo.toml index 22435a08..f6ced14d 100644 --- a/rocket/dyn_template_hbs/Cargo.toml +++ b/rocket/dyn_template_hbs/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.19.0" -shuttle-runtime = "0.19.0" -shuttle-static-folder = "0.19.0" +shuttle-rocket = "0.20.0" +shuttle-runtime = "0.20.0" +shuttle-static-folder = "0.20.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index ba48e8a2..4715f82e 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-rocket = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 7ebd4393..a2da37c8 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.19.0" -shuttle-rocket = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-persist = "0.20.0" +shuttle-rocket = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index bae604a8..9d59e9f9 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } -shuttle-rocket = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } +shuttle-rocket = "0.20.0" +shuttle-runtime = "0.20.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index e0d81a69..41bd1219 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = "0.19.0" -shuttle-runtime = "0.19.0" -shuttle-secrets = "0.19.0" +shuttle-rocket = "0.20.0" +shuttle-runtime = "0.20.0" +shuttle-secrets = "0.20.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index e9a6169d..fe67f84a 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-rocket = "0.20.0" +shuttle-runtime = "0.20.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index abc1cae1..4b526675 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-rocket = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 0e626b4f..70ca51fa 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-salvo = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index ea343928..9db0b77d 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-serenity = "0.20.0" +shuttle-runtime = "0.20.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.19.0" +shuttle-secrets = "0.20.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 99ff60ef..1e98a11f 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.19.0" -shuttle-serenity = "0.19.0" -shuttle-runtime = "0.19.0" -shuttle-shared-db = { version = "0.19.0", features = ["postgres"] } +shuttle-secrets = "0.20.0" +shuttle-serenity = "0.20.0" +shuttle-runtime = "0.20.0" +shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 04e212db..74741282 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-thruster = "0.20.0" +shuttle-runtime = "0.20.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 45eb2593..ae64fe71 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.19.0", features = ["postgres"] } -shuttle-thruster = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-aws-rds = { version = "0.20.0", features = ["postgres"] } +shuttle-thruster = "0.20.0" +shuttle-runtime = "0.20.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 1cccdf0c..0e55e466 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.19.0" -shuttle-runtime = "0.19.0" +shuttle-tide = "0.20.0" +shuttle-runtime = "0.20.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index e06664d2..d0fd1993 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.19.0", features = ["postgres"] } -shuttle-runtime = "0.19.0" -shuttle-tide = "0.19.0" +shuttle-aws-rds = { version = "0.20.0", features = ["postgres"] } +shuttle-runtime = "0.20.0" +shuttle-tide = "0.20.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 21c30ca9..a7662aef 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.19.0" -shuttle-tower = "0.19.0" +shuttle-runtime = "0.20.0" +shuttle-tower = "0.20.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 9d61d62f..6fcca267 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.19.0" -shuttle-warp = "0.19.0" +shuttle-runtime = "0.20.0" +shuttle-warp = "0.20.0" tokio = "1.26.0" warp = "0.3.3" From 5b02a8920e4bc7af98cf6268d9f1bcaf3081f4c6 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 5 Jul 2023 12:24:10 +0200 Subject: [PATCH 075/239] feat: document new init command, add community examples list (#65) * feat: document new init command, add community examples list * Write out full table of examples * Custom services * Description before command, no blank rows * Rename handlebars templates example --- README.md | 106 ++++++++++++++++-- .../Cargo.toml | 0 .../README.md | 0 .../Shuttle.toml | 0 .../src/main.rs | 0 .../templates/index.html.hbs | 0 rocket/persist/README.md | 15 --- 7 files changed, 95 insertions(+), 26 deletions(-) rename rocket/{dyn_template_hbs => dyn-templates}/Cargo.toml (100%) rename rocket/{dyn_template_hbs => dyn-templates}/README.md (100%) rename rocket/{dyn_template_hbs => dyn-templates}/Shuttle.toml (100%) rename rocket/{dyn_template_hbs => dyn-templates}/src/main.rs (100%) rename rocket/{dyn_template_hbs => dyn-templates}/templates/index.html.hbs (100%) diff --git a/README.md b/README.md index 30da79b8..841eda5e 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,109 @@ -# Examples +# Shuttle Examples -Some example apps to show what you can do with shuttle. +This is a collection of some example apps that show what you can do with shuttle. -## How to deploy the examples +The examples in this repository, listed below, consists of *"Hello, world!"* examples of all officially supported web frameworks and how to combine them with Shuttle resources, but also fullstack templates and more. -To deploy the examples, check out the repository locally +There are also unofficial examples that are created and maintained by community members. +Contributions to this list are welcome. +Check out the list at the [bottom of this page](#community-examples). + +## How to clone, run and deploy an example + +To clone an example, use the init command of the [`cargo-shuttle`](https://docs.shuttle.rs/introduction/installation) binary and specify the git URL and optional subfolder: ```bash -git clone https://github.com/shuttle-hq/shuttle-examples.git +cargo shuttle init --from https://github.com/shuttle-hq/shuttle-examples --subfolder axum/hello-world ``` -navigate to an example root folder +You can also add `--name my-project-name` and the target path as arguments. Otherwise, they will be prompted for. + +The `--from` argument uses [cargo-generate](https://cargo-generate.github.io/cargo-generate/) internally, which means you can also use these forms: ```bash -cd axum/hello-world +# GitHub prefix. Change to 'gl:' or 'bb:' for GitLab or BitBucket +cargo shuttle init --from gh:username/repository +# Also GitHub +cargo shuttle init --from username/repository + +# From local folder +cargo shuttle init --from ../path/to/folder +cargo shuttle init --from /home/user/some/folder ``` -Pick a project name that is something unique - in shuttle, -projects are globally unique. Then run +Then, you can navigate into the folder where it was created, and use these commands to run the example locally, and to deploy it. ```bash -cargo shuttle project start --name=$PROJECT_NAME -cargo shuttle deploy --name=$PROJECT_NAME +# Run locally +cargo shuttle run + +# Start the Shuttle environment, make sure the project has a unique name +cargo shuttle project start +# Deploy to Shuttle +cargo shuttle deploy ``` + +## Official Examples + +This is a list of all examples maintained in this repostiory. + +**Framework** | **Name & Link** | **Description** | **Command** +--------------|-----------------|-------------|---------------- +Actix Web | [hello-world](./actix-web/hello-world/) | Hello World | `cargo shuttle init --template actix-web` +Actix Web | [postgres](./actix-web/postgres/) | TODO app with a Postgres DB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/postgres` +Actix Web | [websocket-actorless](./actix-web/websocket-actorless/) | Websocket app that checks the status of Shuttle's API | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/websocket-actorless` +Axum | [hello-world](./axum/hello-world/) | Hello World | `cargo shuttle init --template axum` +Axum | [static-files](./axum/static-files/) | Hello World page that serves static HTML and JS files | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/static-files` +Axum | [static-next-server](./axum/static-next-server/) | SPA server for serving a apps from frameworks such as Next.js | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/static-next-server` +Axum | [websocket](./axum/websocket/) | Websocket app that checks the status of Shuttle's API | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/websocket` +Axum | [with-state](./axum/with-state/) | Hello World with example of how to utilize State in Axum | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/with-state` +Axum & Next.js | [saas](./fullstack-templates/saas/) | Competent opinionated fullstack web app with pre-made routes and assets | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder fullstack-templates/saas` +Poem | [hello-world](./poem/hello-world/) | Hello World | `cargo shuttle init --template poem` +Poem | [mongodb](./poem/mongodb/) | TODO app with MongoDB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder poem/mongodb` +Poem | [postgres](./poem/postgres/) | TODO app with a Postgres DB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder poem/postgres` +Poise | [hello-world](./poise/hello-world/) | Hello World Discord bot | `cargo shuttle init --template poise` +Rocket | [authentication](./rocket/authentication/) | Use JWT to authenticate API endpoints | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/authentication` +Rocket | [dyn-templates](./rocket/dyn-templates/) | Handlebars dynamic templates | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/dyn-templates` +Rocket | [hello-world](./rocket/hello-world/) | Hello World | `cargo shuttle init --template rocket` +Rocket | [persist](./rocket/persist/) | Store weather data with Shuttle Persist | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/persist` +Rocket | [postgres](./rocket/postgres/) | TODO app with a Postgres DB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/postgres` +Rocket | [secrets](./rocket/secrets/) | Extract secrets from your Secrets.toml file | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/secrets` +Rocket | [url-shortener](./rocket/url-shortener/) | URL shortener with Postgres storage | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/url-shortener` +Rocket | [workspace](./rocket/workspace/) | A cargo workspace where one crate is a Shuttle service | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/workspace` +Salvo | [hello-world](./salvo/hello-world/) | Hello World | `cargo shuttle init --template salvo` +Serenity | [hello-world](./serenity/hello-world/) | Hello World Discord bot | `cargo shuttle init --template serenity` +Thruster | [hello-world](./thruster/hello-world/) | Hello World | `cargo shuttle init --template thruster` +Thruster | [postgres](./thruster/postgres/) | TODO app with a Postgres DB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder thruster/postgres` +Tide | [hello-world](./tide/hello-world/) | Hello World | `cargo shuttle init --template tide` +Tide | [postgres](./tide/postgres/) | TODO app with a Postgres DB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder tide/postgres` +Tower | [hello-world](./tower/hello-world/) | Hello World | `cargo shuttle init --template tower` +Warp | [hello-world](./warp/hello-world/) | Hello World | `cargo shuttle init --template warp` +*Custom Service* | [none](./custom/none/) | No framework - Custom empty service - A barebones minimal Shuttle app that does nothing | `cargo shuttle init --template none` +*Custom Service* | [request-scheduler](./custom/request-scheduler/) | A custom *Request Scheduler* service | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder request-scheduler` + +## Community Examples + +This is a collection of unofficial examples that community members have submitted. +Quality and maintenance is not guaranteed. +You can submit a Pull Request to add your example to the list. + + + +**Framework** | **Name & Link** | **Description** | **Command** +--------------|-----------------|-------------|---------------- +Axum | [Test](https://github.com/shuttle-hq/shuttle-examples) | A test example A test example A test example | `cargo shuttle init --from / --subfolder ` diff --git a/rocket/dyn_template_hbs/Cargo.toml b/rocket/dyn-templates/Cargo.toml similarity index 100% rename from rocket/dyn_template_hbs/Cargo.toml rename to rocket/dyn-templates/Cargo.toml diff --git a/rocket/dyn_template_hbs/README.md b/rocket/dyn-templates/README.md similarity index 100% rename from rocket/dyn_template_hbs/README.md rename to rocket/dyn-templates/README.md diff --git a/rocket/dyn_template_hbs/Shuttle.toml b/rocket/dyn-templates/Shuttle.toml similarity index 100% rename from rocket/dyn_template_hbs/Shuttle.toml rename to rocket/dyn-templates/Shuttle.toml diff --git a/rocket/dyn_template_hbs/src/main.rs b/rocket/dyn-templates/src/main.rs similarity index 100% rename from rocket/dyn_template_hbs/src/main.rs rename to rocket/dyn-templates/src/main.rs diff --git a/rocket/dyn_template_hbs/templates/index.html.hbs b/rocket/dyn-templates/templates/index.html.hbs similarity index 100% rename from rocket/dyn_template_hbs/templates/index.html.hbs rename to rocket/dyn-templates/templates/index.html.hbs diff --git a/rocket/persist/README.md b/rocket/persist/README.md index 7278bd0b..d9f245c7 100644 --- a/rocket/persist/README.md +++ b/rocket/persist/README.md @@ -4,21 +4,6 @@ An example app to show what you can do with shuttle. ## How to deploy the example -To deploy the examples, check out the repository locally - -```bash -git clone https://github.com/shuttle-hq/shuttle.git -``` - -navigate to the Persist root folder - -```bash -cd examples/rocket/persist -``` - -Pick a project name that is something unique - in shuttle, -projects are globally unique. Then run - ```bash cargo shuttle project start --name=$PROJECT_NAME cargo shuttle deploy --name=$PROJECT_NAME From 398ac9c9ed419a0cd7c5f8112c37402449be3f00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Mon, 10 Jul 2023 10:00:52 +0200 Subject: [PATCH 076/239] chore: v0.21.0 (#71) --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 6 +++--- axum/hello-world/Cargo.toml | 4 ++-- axum/static-files/Cargo.toml | 6 +++--- axum/static-next-server/Cargo.toml | 6 +++--- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 6 +++--- axum/with-state/Cargo.toml | 4 ++-- custom/none/Cargo.toml | 2 +- custom/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 10 +++++----- next/hello-world/Cargo.toml | 2 +- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 6 +++--- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 34 files changed, 88 insertions(+), 88 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 6bcf785b..69f5d591 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-actix-web = "0.21.0" +shuttle-runtime = "0.21.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 72e3ae54..f664b4ab 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-actix-web = "0.21.0" +shuttle-runtime = "0.21.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.21.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index eb4e5eff..4ba3482f 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,8 +13,8 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.20.0" -shuttle-runtime = "0.20.0" -shuttle-static-folder = "0.20.0" +shuttle-actix-web = "0.21.0" +shuttle-runtime = "0.21.0" +shuttle-static-folder = "0.21.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 3525f6b7..b9fc4dfd 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-axum = "0.21.0" +shuttle-runtime = "0.21.0" tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index ae43b14a..17110cbb 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.20.0" -shuttle-runtime = "0.20.0" -shuttle-static-folder = "0.20.0" +shuttle-axum = "0.21.0" +shuttle-runtime = "0.21.0" +shuttle-static-folder = "0.21.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 6febb8cc..02dac12b 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.20.0" -shuttle-runtime = "0.20.0" -shuttle-static-folder = "0.20.0" +shuttle-axum = "0.21.0" +shuttle-runtime = "0.21.0" +shuttle-static-folder = "0.21.0" tokio = "1.26.0" diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 736f6485..e4d11722 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = { version = "0.6.18" } -shuttle-axum = { version = "0.20.0" } -shuttle-runtime = { version = "0.20.0" } -shuttle-turso = { version = "0.20.0" } +shuttle-axum = { version = "0.21.0" } +shuttle-runtime = { version = "0.21.0" } +shuttle-turso = { version = "0.21.0" } libsql-client = "=0.30.1" tokio = { version = "1.26.0" } serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index d6d582d0..3596eccc 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,8 +11,8 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.20.0" -shuttle-runtime = "0.20.0" -shuttle-static-folder = "0.20.0" +shuttle-axum = "0.21.0" +shuttle-runtime = "0.21.0" +shuttle-static-folder = "0.21.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index 6d156152..f7ee2047 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-axum = "0.21.0" +shuttle-runtime = "0.21.0" tokio = "1.26.0" diff --git a/custom/none/Cargo.toml b/custom/none/Cargo.toml index ca150084..d752e627 100644 --- a/custom/none/Cargo.toml +++ b/custom/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.20.0" +shuttle-runtime = "0.21.0" tokio = "1" diff --git a/custom/request-scheduler/Cargo.toml b/custom/request-scheduler/Cargo.toml index 966dcb88..5eb7ff83 100644 --- a/custom/request-scheduler/Cargo.toml +++ b/custom/request-scheduler/Cargo.toml @@ -12,6 +12,6 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-persist = "0.21.0" +shuttle-runtime = "0.21.0" tokio = "1.28.0" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index cd6514c8..bf945d31 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,11 +16,11 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.20.0" -shuttle-runtime = "0.20.0" -shuttle-secrets = "0.20.0" -shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } -shuttle-static-folder = "0.20.0" +shuttle-axum = "0.21.0" +shuttle-runtime = "0.21.0" +shuttle-secrets = "0.21.0" +shuttle-shared-db = { version = "0.21.0", features = ["postgres"] } +shuttle-static-folder = "0.21.0" sqlx = { version = "0.6.3", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index bcffa96d..e529c55e 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.20.0" +shuttle-next = "0.21.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 7fa50546..a47e06b4 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-poem = "0.21.0" +shuttle-runtime = "0.21.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 21998d9d..fadb5039 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.20.0" -shuttle-shared-db = { version = "0.20.0", features = ["mongodb"] } -shuttle-runtime = "0.20.0" +shuttle-poem = "0.21.0" +shuttle-shared-db = { version = "0.21.0", features = ["mongodb"] } +shuttle-runtime = "0.21.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 05c1ccd2..ed78e7be 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.20.0" -shuttle-runtime = "0.20.0" -shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } +shuttle-poem = "0.21.0" +shuttle-runtime = "0.21.0" +shuttle-shared-db = { version = "0.21.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index b3abd1c7..f7c9c655 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.20.0" -shuttle-runtime = "0.20.0" -shuttle-secrets = "0.20.0" +shuttle-poise = "0.21.0" +shuttle-runtime = "0.21.0" +shuttle-secrets = "0.21.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index 0f9134eb..3c3d9280 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-rocket = "0.21.0" +shuttle-runtime = "0.21.0" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index f6ced14d..b1fd4c8f 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.20.0" -shuttle-runtime = "0.20.0" -shuttle-static-folder = "0.20.0" +shuttle-rocket = "0.21.0" +shuttle-runtime = "0.21.0" +shuttle-static-folder = "0.21.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 4715f82e..962d5029 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-rocket = "0.21.0" +shuttle-runtime = "0.21.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index a2da37c8..a7979e9f 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.20.0" -shuttle-rocket = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-persist = "0.21.0" +shuttle-rocket = "0.21.0" +shuttle-runtime = "0.21.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 9d59e9f9..508a7133 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } -shuttle-rocket = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-shared-db = { version = "0.21.0", features = ["postgres"] } +shuttle-rocket = "0.21.0" +shuttle-runtime = "0.21.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 41bd1219..61fa315d 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = "0.20.0" -shuttle-runtime = "0.20.0" -shuttle-secrets = "0.20.0" +shuttle-rocket = "0.21.0" +shuttle-runtime = "0.21.0" +shuttle-secrets = "0.21.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index fe67f84a..0b6fb979 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-rocket = "0.21.0" +shuttle-runtime = "0.21.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.21.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 4b526675..2b16bd38 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-rocket = "0.21.0" +shuttle-runtime = "0.21.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 70ca51fa..b12409ff 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-salvo = "0.21.0" +shuttle-runtime = "0.21.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 9db0b77d..89d21afa 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-serenity = "0.21.0" +shuttle-runtime = "0.21.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.20.0" +shuttle-secrets = "0.21.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 1e98a11f..65f33ab4 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.20.0" -shuttle-serenity = "0.20.0" -shuttle-runtime = "0.20.0" -shuttle-shared-db = { version = "0.20.0", features = ["postgres"] } +shuttle-secrets = "0.21.0" +shuttle-serenity = "0.21.0" +shuttle-runtime = "0.21.0" +shuttle-shared-db = { version = "0.21.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 74741282..fac48d49 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-thruster = "0.21.0" +shuttle-runtime = "0.21.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index ae64fe71..0aacfeb8 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.20.0", features = ["postgres"] } -shuttle-thruster = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-aws-rds = { version = "0.21.0", features = ["postgres"] } +shuttle-thruster = "0.21.0" +shuttle-runtime = "0.21.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 0e55e466..3cbb7e42 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.20.0" -shuttle-runtime = "0.20.0" +shuttle-tide = "0.21.0" +shuttle-runtime = "0.21.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index d0fd1993..4825003a 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.20.0", features = ["postgres"] } -shuttle-runtime = "0.20.0" -shuttle-tide = "0.20.0" +shuttle-aws-rds = { version = "0.21.0", features = ["postgres"] } +shuttle-runtime = "0.21.0" +shuttle-tide = "0.21.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index a7662aef..789b1320 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.20.0" -shuttle-tower = "0.20.0" +shuttle-runtime = "0.21.0" +shuttle-tower = "0.21.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 6fcca267..d169cedd 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.20.0" -shuttle-warp = "0.20.0" +shuttle-runtime = "0.21.0" +shuttle-warp = "0.21.0" tokio = "1.26.0" warp = "0.3.3" From 2262f8a4004bafeb9bb4d3ea8ed32a3cdc1703ef Mon Sep 17 00:00:00 2001 From: Iulian Barbu <14218860+iulianbarbu@users.noreply.github.com> Date: Tue, 18 Jul 2023 18:28:48 +0300 Subject: [PATCH 077/239] custom-resource: added pdo example (#73) * custom-resource: added pdo example * custom: changed the name to custom-service --- custom-resource/pdo/.gitignore | 2 + custom-resource/pdo/Cargo.toml | 13 +++++ custom-resource/pdo/src/lib.rs | 55 +++++++++++++++++++ custom-resource/pdo/src/main.rs | 15 +++++ {custom => custom-service}/none/Cargo.toml | 0 {custom => custom-service}/none/src/main.rs | 0 .../request-scheduler/Cargo.toml | 0 .../request-scheduler/README.md | 0 .../request-scheduler/request.sh | 0 .../request-scheduler/src/error.rs | 0 .../request-scheduler/src/lib.rs | 0 .../request-scheduler/src/main.rs | 0 .../request-scheduler/src/router.rs | 0 13 files changed, 85 insertions(+) create mode 100644 custom-resource/pdo/.gitignore create mode 100644 custom-resource/pdo/Cargo.toml create mode 100644 custom-resource/pdo/src/lib.rs create mode 100644 custom-resource/pdo/src/main.rs rename {custom => custom-service}/none/Cargo.toml (100%) rename {custom => custom-service}/none/src/main.rs (100%) rename {custom => custom-service}/request-scheduler/Cargo.toml (100%) rename {custom => custom-service}/request-scheduler/README.md (100%) rename {custom => custom-service}/request-scheduler/request.sh (100%) rename {custom => custom-service}/request-scheduler/src/error.rs (100%) rename {custom => custom-service}/request-scheduler/src/lib.rs (100%) rename {custom => custom-service}/request-scheduler/src/main.rs (100%) rename {custom => custom-service}/request-scheduler/src/router.rs (100%) diff --git a/custom-resource/pdo/.gitignore b/custom-resource/pdo/.gitignore new file mode 100644 index 00000000..a1a5734e --- /dev/null +++ b/custom-resource/pdo/.gitignore @@ -0,0 +1,2 @@ +/target +Secrets*.toml diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml new file mode 100644 index 00000000..9ce8a7da --- /dev/null +++ b/custom-resource/pdo/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "pdo" +version = "0.1.0" +edition = "2021" + +[dependencies] +async-trait = "0.1.56" +axum = "0.6.18" +serde = { version = "1.0.148", default-features = false, features = ["derive"] } +shuttle-service = "0.21.0" +shuttle-axum = "0.21.0" +shuttle-runtime = "0.21.0" +tokio = "1.28.2" diff --git a/custom-resource/pdo/src/lib.rs b/custom-resource/pdo/src/lib.rs new file mode 100644 index 00000000..dac8efe6 --- /dev/null +++ b/custom-resource/pdo/src/lib.rs @@ -0,0 +1,55 @@ +use async_trait::async_trait; +use serde::Serialize; +use shuttle_service::Factory; +use shuttle_service::ResourceBuilder; +use shuttle_service::Type; + +#[derive(Serialize)] +pub struct Builder { + name: String, +} + +#[derive(Clone)] +pub struct Pdo { + pub name: String, +} + +impl Builder { + /// Name to give resource + pub fn name(mut self, name: &str) -> Self { + self.name = name.to_string(); + self + } +} + +#[async_trait] +impl ResourceBuilder for Builder { + const TYPE: Type = Type::Custom; + + type Config = Self; + + type Output = String; + + fn new() -> Self { + Self { + name: String::new(), + } + } + + fn config(&self) -> &Self::Config { + self + } + + async fn output( + self, + _factory: &mut dyn Factory, + ) -> Result { + Ok(self.name) + } + + async fn build(build_data: &Self::Output) -> Result { + Ok(Pdo { + name: build_data.clone(), + }) + } +} diff --git a/custom-resource/pdo/src/main.rs b/custom-resource/pdo/src/main.rs new file mode 100644 index 00000000..a74326f3 --- /dev/null +++ b/custom-resource/pdo/src/main.rs @@ -0,0 +1,15 @@ +use axum::{extract::State, routing::get, Router}; +use pdo::{Builder, Pdo}; +use std::sync::Arc; + +async fn hello_world(State(pdo): State>) -> String { + pdo.name.clone() +} + +#[shuttle_runtime::main] +async fn axum(#[Builder(name = "John")] pdo: Pdo) -> shuttle_axum::ShuttleAxum { + let state = Arc::new(pdo); + let router = Router::new().route("/", get(hello_world)).with_state(state); + + Ok(router.into()) +} diff --git a/custom/none/Cargo.toml b/custom-service/none/Cargo.toml similarity index 100% rename from custom/none/Cargo.toml rename to custom-service/none/Cargo.toml diff --git a/custom/none/src/main.rs b/custom-service/none/src/main.rs similarity index 100% rename from custom/none/src/main.rs rename to custom-service/none/src/main.rs diff --git a/custom/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml similarity index 100% rename from custom/request-scheduler/Cargo.toml rename to custom-service/request-scheduler/Cargo.toml diff --git a/custom/request-scheduler/README.md b/custom-service/request-scheduler/README.md similarity index 100% rename from custom/request-scheduler/README.md rename to custom-service/request-scheduler/README.md diff --git a/custom/request-scheduler/request.sh b/custom-service/request-scheduler/request.sh similarity index 100% rename from custom/request-scheduler/request.sh rename to custom-service/request-scheduler/request.sh diff --git a/custom/request-scheduler/src/error.rs b/custom-service/request-scheduler/src/error.rs similarity index 100% rename from custom/request-scheduler/src/error.rs rename to custom-service/request-scheduler/src/error.rs diff --git a/custom/request-scheduler/src/lib.rs b/custom-service/request-scheduler/src/lib.rs similarity index 100% rename from custom/request-scheduler/src/lib.rs rename to custom-service/request-scheduler/src/lib.rs diff --git a/custom/request-scheduler/src/main.rs b/custom-service/request-scheduler/src/main.rs similarity index 100% rename from custom/request-scheduler/src/main.rs rename to custom-service/request-scheduler/src/main.rs diff --git a/custom/request-scheduler/src/router.rs b/custom-service/request-scheduler/src/router.rs similarity index 100% rename from custom/request-scheduler/src/router.rs rename to custom-service/request-scheduler/src/router.rs From bd9086e1b83dbe9117f7d94da28fddd77e2ca683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Mon, 31 Jul 2023 14:29:20 +0200 Subject: [PATCH 078/239] Chore/v0.22.0 (#76) * chore: v0.22.0 * chore: bump new example --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 6 +++--- axum/hello-world/Cargo.toml | 4 ++-- axum/static-files/Cargo.toml | 6 +++--- axum/static-next-server/Cargo.toml | 6 +++--- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 6 +++--- axum/with-state/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 10 +++++----- next/hello-world/Cargo.toml | 2 +- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 6 +++--- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 35 files changed, 91 insertions(+), 91 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 69f5d591..24d2dba5 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.21.0" -shuttle-runtime = "0.21.0" +shuttle-actix-web = "0.22.0" +shuttle-runtime = "0.22.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index f664b4ab..ee143376 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.21.0" -shuttle-runtime = "0.21.0" +shuttle-actix-web = "0.22.0" +shuttle-runtime = "0.22.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.21.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.22.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 4ba3482f..7e883c74 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,8 +13,8 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.21.0" -shuttle-runtime = "0.21.0" -shuttle-static-folder = "0.21.0" +shuttle-actix-web = "0.22.0" +shuttle-runtime = "0.22.0" +shuttle-static-folder = "0.22.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index b9fc4dfd..cb78e5ba 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.21.0" -shuttle-runtime = "0.21.0" +shuttle-axum = "0.22.0" +shuttle-runtime = "0.22.0" tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 17110cbb..943fb99f 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.21.0" -shuttle-runtime = "0.21.0" -shuttle-static-folder = "0.21.0" +shuttle-axum = "0.22.0" +shuttle-runtime = "0.22.0" +shuttle-static-folder = "0.22.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 02dac12b..c3bfbb98 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.21.0" -shuttle-runtime = "0.21.0" -shuttle-static-folder = "0.21.0" +shuttle-axum = "0.22.0" +shuttle-runtime = "0.22.0" +shuttle-static-folder = "0.22.0" tokio = "1.26.0" diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index e4d11722..786584b0 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = { version = "0.6.18" } -shuttle-axum = { version = "0.21.0" } -shuttle-runtime = { version = "0.21.0" } -shuttle-turso = { version = "0.21.0" } +shuttle-axum = { version = "0.22.0" } +shuttle-runtime = { version = "0.22.0" } +shuttle-turso = { version = "0.22.0" } libsql-client = "=0.30.1" tokio = { version = "1.26.0" } serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 3596eccc..51146334 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,8 +11,8 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.21.0" -shuttle-runtime = "0.21.0" -shuttle-static-folder = "0.21.0" +shuttle-axum = "0.22.0" +shuttle-runtime = "0.22.0" +shuttle-static-folder = "0.22.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index f7ee2047..93b6e263 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.21.0" -shuttle-runtime = "0.21.0" +shuttle-axum = "0.22.0" +shuttle-runtime = "0.22.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 9ce8a7da..2c387c2d 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.6.18" serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.21.0" -shuttle-axum = "0.21.0" -shuttle-runtime = "0.21.0" +shuttle-service = "0.22.0" +shuttle-axum = "0.22.0" +shuttle-runtime = "0.22.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index d752e627..fce3ee45 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.21.0" +shuttle-runtime = "0.22.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index 5eb7ff83..9d7b7f4e 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -12,6 +12,6 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.21.0" -shuttle-runtime = "0.21.0" +shuttle-persist = "0.22.0" +shuttle-runtime = "0.22.0" tokio = "1.28.0" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index bf945d31..0e25ccb8 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,11 +16,11 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.21.0" -shuttle-runtime = "0.21.0" -shuttle-secrets = "0.21.0" -shuttle-shared-db = { version = "0.21.0", features = ["postgres"] } -shuttle-static-folder = "0.21.0" +shuttle-axum = "0.22.0" +shuttle-runtime = "0.22.0" +shuttle-secrets = "0.22.0" +shuttle-shared-db = { version = "0.22.0", features = ["postgres"] } +shuttle-static-folder = "0.22.0" sqlx = { version = "0.6.3", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index e529c55e..205cce5a 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.21.0" +shuttle-next = "0.22.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index a47e06b4..935dc22d 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.21.0" -shuttle-runtime = "0.21.0" +shuttle-poem = "0.22.0" +shuttle-runtime = "0.22.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index fadb5039..8ca469c6 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.21.0" -shuttle-shared-db = { version = "0.21.0", features = ["mongodb"] } -shuttle-runtime = "0.21.0" +shuttle-poem = "0.22.0" +shuttle-shared-db = { version = "0.22.0", features = ["mongodb"] } +shuttle-runtime = "0.22.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index ed78e7be..0cd0bb43 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.21.0" -shuttle-runtime = "0.21.0" -shuttle-shared-db = { version = "0.21.0", features = ["postgres"] } +shuttle-poem = "0.22.0" +shuttle-runtime = "0.22.0" +shuttle-shared-db = { version = "0.22.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index f7c9c655..2bfd95aa 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.21.0" -shuttle-runtime = "0.21.0" -shuttle-secrets = "0.21.0" +shuttle-poise = "0.22.0" +shuttle-runtime = "0.22.0" +shuttle-secrets = "0.22.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index 3c3d9280..9ff21c9f 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.21.0" -shuttle-runtime = "0.21.0" +shuttle-rocket = "0.22.0" +shuttle-runtime = "0.22.0" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index b1fd4c8f..223facb8 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.21.0" -shuttle-runtime = "0.21.0" -shuttle-static-folder = "0.21.0" +shuttle-rocket = "0.22.0" +shuttle-runtime = "0.22.0" +shuttle-static-folder = "0.22.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 962d5029..e0ab0127 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.21.0" -shuttle-runtime = "0.21.0" +shuttle-rocket = "0.22.0" +shuttle-runtime = "0.22.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index a7979e9f..d653853c 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.21.0" -shuttle-rocket = "0.21.0" -shuttle-runtime = "0.21.0" +shuttle-persist = "0.22.0" +shuttle-rocket = "0.22.0" +shuttle-runtime = "0.22.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 508a7133..74b3a840 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.21.0", features = ["postgres"] } -shuttle-rocket = "0.21.0" -shuttle-runtime = "0.21.0" +shuttle-shared-db = { version = "0.22.0", features = ["postgres"] } +shuttle-rocket = "0.22.0" +shuttle-runtime = "0.22.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 61fa315d..d51ae0be 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = "0.21.0" -shuttle-runtime = "0.21.0" -shuttle-secrets = "0.21.0" +shuttle-rocket = "0.22.0" +shuttle-runtime = "0.22.0" +shuttle-secrets = "0.22.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 0b6fb979..c5bd4566 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = "0.21.0" -shuttle-runtime = "0.21.0" +shuttle-rocket = "0.22.0" +shuttle-runtime = "0.22.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.21.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.22.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 2b16bd38..8320c3d3 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.21.0" -shuttle-runtime = "0.21.0" +shuttle-rocket = "0.22.0" +shuttle-runtime = "0.22.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index b12409ff..aa7c0443 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.21.0" -shuttle-runtime = "0.21.0" +shuttle-salvo = "0.22.0" +shuttle-runtime = "0.22.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 89d21afa..c9a5204a 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.21.0" -shuttle-runtime = "0.21.0" +shuttle-serenity = "0.22.0" +shuttle-runtime = "0.22.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.21.0" +shuttle-secrets = "0.22.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 65f33ab4..4e582bef 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.21.0" -shuttle-serenity = "0.21.0" -shuttle-runtime = "0.21.0" -shuttle-shared-db = { version = "0.21.0", features = ["postgres"] } +shuttle-secrets = "0.22.0" +shuttle-serenity = "0.22.0" +shuttle-runtime = "0.22.0" +shuttle-shared-db = { version = "0.22.0", features = ["postgres"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index fac48d49..3a2461c1 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.21.0" -shuttle-runtime = "0.21.0" +shuttle-thruster = "0.22.0" +shuttle-runtime = "0.22.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 0aacfeb8..04b171d1 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.21.0", features = ["postgres"] } -shuttle-thruster = "0.21.0" -shuttle-runtime = "0.21.0" +shuttle-aws-rds = { version = "0.22.0", features = ["postgres"] } +shuttle-thruster = "0.22.0" +shuttle-runtime = "0.22.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 3cbb7e42..d190f359 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.21.0" -shuttle-runtime = "0.21.0" +shuttle-tide = "0.22.0" +shuttle-runtime = "0.22.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index 4825003a..72cd92e4 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.21.0", features = ["postgres"] } -shuttle-runtime = "0.21.0" -shuttle-tide = "0.21.0" +shuttle-aws-rds = { version = "0.22.0", features = ["postgres"] } +shuttle-runtime = "0.22.0" +shuttle-tide = "0.22.0" sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 789b1320..cee2de13 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.21.0" -shuttle-tower = "0.21.0" +shuttle-runtime = "0.22.0" +shuttle-tower = "0.22.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index d169cedd..d9f92584 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.21.0" -shuttle-warp = "0.21.0" +shuttle-runtime = "0.22.0" +shuttle-warp = "0.22.0" tokio = "1.26.0" warp = "0.3.3" From d286f4159927cf82a173ee41112e623773e82e62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Mon, 31 Jul 2023 14:32:50 +0200 Subject: [PATCH 079/239] chore: bump sqlx in resources (#75) * chore: bump sqlx in resources * chore: bump sqlx version in examples --- actix-web/postgres/Cargo.toml | 2 +- fullstack-templates/saas/backend/Cargo.toml | 2 +- poem/postgres/Cargo.toml | 2 +- rocket/postgres/Cargo.toml | 2 +- rocket/url-shortener/Cargo.toml | 2 +- serenity/postgres/Cargo.toml | 2 +- thruster/postgres/Cargo.toml | 2 +- tide/postgres/Cargo.toml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index ee143376..8b2aec8a 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -9,5 +9,5 @@ shuttle-actix-web = "0.22.0" shuttle-runtime = "0.22.0" serde = "1.0.148" shuttle-shared-db = { version = "0.22.0", features = ["postgres"] } -sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } +sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 0e25ccb8..58e9d448 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -21,7 +21,7 @@ shuttle-runtime = "0.22.0" shuttle-secrets = "0.22.0" shuttle-shared-db = { version = "0.22.0", features = ["postgres"] } shuttle-static-folder = "0.22.0" -sqlx = { version = "0.6.3", features = ["runtime-tokio-native-tls", "postgres", "time"] } +sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" tower = "0.4.13" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 0cd0bb43..ebd598a2 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -9,5 +9,5 @@ serde = "1.0.148" shuttle-poem = "0.22.0" shuttle-runtime = "0.22.0" shuttle-shared-db = { version = "0.22.0", features = ["postgres"] } -sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } +sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 74b3a840..ec17f73b 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -9,5 +9,5 @@ serde = "1.0.148" shuttle-shared-db = { version = "0.22.0", features = ["postgres"] } shuttle-rocket = "0.22.0" shuttle-runtime = "0.22.0" -sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } +sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index c5bd4566..1c709726 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -10,6 +10,6 @@ shuttle-rocket = "0.22.0" shuttle-runtime = "0.22.0" serde = "1.0.148" shuttle-shared-db = { version = "0.22.0", features = ["postgres"] } -sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } +sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 4e582bef..fe69fde8 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -11,6 +11,6 @@ shuttle-secrets = "0.22.0" shuttle-serenity = "0.22.0" shuttle-runtime = "0.22.0" shuttle-shared-db = { version = "0.22.0", features = ["postgres"] } -sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } +sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 04b171d1..ae40e1d5 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -10,6 +10,6 @@ serde_json = "1.0.89" shuttle-aws-rds = { version = "0.22.0", features = ["postgres"] } shuttle-thruster = "0.22.0" shuttle-runtime = "0.22.0" -sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } +sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index 72cd92e4..a1d253c9 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -8,6 +8,6 @@ serde = { version = "1.0.148", features = ["derive"] } shuttle-aws-rds = { version = "0.22.0", features = ["postgres"] } shuttle-runtime = "0.22.0" shuttle-tide = "0.22.0" -sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "postgres"] } +sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" From fdd0ceb6e509f75e418293327f0f64ed918c1732 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Fri, 4 Aug 2023 11:54:41 +0200 Subject: [PATCH 080/239] Add example of how to run a standalone binary alongside the Shuttle one (#61) * Add example of how to run a standalone binary alongside the Shuttle one * add missing items to list * fix: feedback --- README.md | 7 ++++-- other/standalone-binary/Cargo.toml | 17 +++++++++++++ other/standalone-binary/README.md | 11 +++++++++ other/standalone-binary/Secrets.toml | 1 + other/standalone-binary/src/lib.rs | 30 +++++++++++++++++++++++ other/standalone-binary/src/main.rs | 16 ++++++++++++ other/standalone-binary/src/standalone.rs | 19 ++++++++++++++ 7 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 other/standalone-binary/Cargo.toml create mode 100644 other/standalone-binary/README.md create mode 100644 other/standalone-binary/Secrets.toml create mode 100644 other/standalone-binary/src/lib.rs create mode 100644 other/standalone-binary/src/main.rs create mode 100644 other/standalone-binary/src/standalone.rs diff --git a/README.md b/README.md index 841eda5e..c30bbd9a 100644 --- a/README.md +++ b/README.md @@ -78,8 +78,10 @@ Tide | [hello-world](./tide/hello-world/) | Hello World | `cargo shuttle init -- Tide | [postgres](./tide/postgres/) | TODO app with a Postgres DB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder tide/postgres` Tower | [hello-world](./tower/hello-world/) | Hello World | `cargo shuttle init --template tower` Warp | [hello-world](./warp/hello-world/) | Hello World | `cargo shuttle init --template warp` -*Custom Service* | [none](./custom/none/) | No framework - Custom empty service - A barebones minimal Shuttle app that does nothing | `cargo shuttle init --template none` -*Custom Service* | [request-scheduler](./custom/request-scheduler/) | A custom *Request Scheduler* service | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder request-scheduler` +*Custom Service* | [none](./custom-service/none/) | Empty service - A barebones implementation of Shuttle Service trait that does nothing | `cargo shuttle init --template none` +*Custom Service* | [request-scheduler](./custom-service/request-scheduler/) | A custom *Request Scheduler* service | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder custom-service/request-scheduler` +*Custom Resource* | [pdo](./custom-resource/pdo/) | Custom Shuttle resource that holds a Plain Data Object (PDO), shown in the context of an Axum app | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder custom-resource/pdo` +*Other* | [standalone-binary](./other/standalone-binary/) | How to split a project to allow it to run both with Shuttle and standalone | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder other/standalone-binary` ## Community Examples @@ -98,6 +100,7 @@ You can submit a Pull Request to add your example to the list. FRAMEWORK | [NAME](LINK_TO_REPO) | DESCRIPTION | `cargo shuttle init --from USER/REPO --subfolder PATH` +- Try to keep the description below 120 characters - If the example is in the root of the repo, you can remove the --subfolder argument. - Add `gl:` or `bb:` prefix for examples hosted on GitLab or BitBucket (see examples at the top). diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml new file mode 100644 index 00000000..c7714d87 --- /dev/null +++ b/other/standalone-binary/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "multi-binary" +version = "0.1.0" +edition = "2021" +publish = false + +[[bin]] +name = "standalone" +path = "src/standalone.rs" + +[dependencies] +axum = "0.6.18" +dotenvy = "0.15.7" +shuttle-axum = "0.22.0" +shuttle-runtime = "0.22.0" +shuttle-secrets = "0.22.0" +tokio = "1.28.2" diff --git a/other/standalone-binary/README.md b/other/standalone-binary/README.md new file mode 100644 index 00000000..8f7905c9 --- /dev/null +++ b/other/standalone-binary/README.md @@ -0,0 +1,11 @@ +# Standalone binary - run an app with Shuttle or standalone + +This example shows how to separate a project's Shuttle logic from its core functionality so that two binaries can be made: one running with Shuttle using `cargo shuttle run` that can be deployed to Shuttle, and one that can be run with `cargo run --bin ...`. + +The main idea is to have a main binary that Shuttle runs, and another binary that runs standalone. +All startup logic is placed in the binary source files, while the implementation (endpoints etc) is moved to the library of the crate. + +- `src/main.rs` is the main binary with Shuttle, run with `cargo shuttle run` +- `src/standalone.rs` is without Shuttle, run with `cargo run --bin standalone` (you can change the name) + +This example shows how to use separate logic for getting secrets, but the same approach can be applied to other resources that are initiated by Shuttle's main function. diff --git a/other/standalone-binary/Secrets.toml b/other/standalone-binary/Secrets.toml new file mode 100644 index 00000000..d1ace109 --- /dev/null +++ b/other/standalone-binary/Secrets.toml @@ -0,0 +1 @@ +SOME_API_KEY = "This is a secret" diff --git a/other/standalone-binary/src/lib.rs b/other/standalone-binary/src/lib.rs new file mode 100644 index 00000000..6a132a31 --- /dev/null +++ b/other/standalone-binary/src/lib.rs @@ -0,0 +1,30 @@ +use axum::{extract::State, routing::get, Router}; + +async fn hello_world() -> &'static str { + "Hello, world!" +} + +async fn some_service(State(state): State) -> &'static str { + println!("Secret from state: {}", state.api_key); + "This function can use a secret to generate the response" +} + +#[derive(Clone)] +struct MyAxumState { + pub api_key: String, + // add other stuff here +} + +/// This function builds the Router (the struct that shuttle_runtime::main wants to return). +/// It uses any resource that Shuttle's main function gets hold of. +/// The standalone binary has to provide those by itself. +pub fn build_router(api_key_for_some_service: String) -> Router { + let state = MyAxumState { + api_key: api_key_for_some_service, + }; + + Router::new() + .route("/", get(hello_world)) + .route("/service", get(some_service)) + .with_state(state) +} diff --git a/other/standalone-binary/src/main.rs b/other/standalone-binary/src/main.rs new file mode 100644 index 00000000..84fd00e8 --- /dev/null +++ b/other/standalone-binary/src/main.rs @@ -0,0 +1,16 @@ +use shuttle_axum::ShuttleAxum; +use shuttle_secrets::SecretStore; + +use multi_binary::build_router; + +#[shuttle_runtime::main] +async fn axum(#[shuttle_secrets::Secrets] secret_store: SecretStore) -> ShuttleAxum { + // Get all resources 'the Shuttle way' + let my_secret = secret_store.get("SOME_API_KEY").unwrap(); + + // Use the shared build function + let router = build_router(my_secret); + + // Let Shuttle do the serving + Ok(router.into()) +} diff --git a/other/standalone-binary/src/standalone.rs b/other/standalone-binary/src/standalone.rs new file mode 100644 index 00000000..d0d58641 --- /dev/null +++ b/other/standalone-binary/src/standalone.rs @@ -0,0 +1,19 @@ +use multi_binary::build_router; + +#[tokio::main] +async fn main() -> Result<(), Box> { + // Get all resources in some way + dotenvy::from_filename("Secrets.toml")?; + let my_secret = std::env::var("SOME_API_KEY").unwrap(); + + // Use the shared build function + let router = build_router(my_secret); + + // Do the serving on its own + axum::Server::bind(&"127.0.0.1:8000".parse().unwrap()) + .serve(router.into_make_service()) + .await + .unwrap(); + + Ok(()) +} From 562f967dcfa17075cad6317c27fcf03ba84d372c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Mon, 7 Aug 2023 12:25:32 +0200 Subject: [PATCH 081/239] chore: v0.23.0 (#79) --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 6 +++--- axum/hello-world/Cargo.toml | 4 ++-- axum/static-files/Cargo.toml | 6 +++--- axum/static-next-server/Cargo.toml | 6 +++--- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 6 +++--- axum/with-state/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 10 +++++----- next/hello-world/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 6 +++--- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 6 +++--- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 36 files changed, 94 insertions(+), 94 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 24d2dba5..7748fb37 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.22.0" -shuttle-runtime = "0.22.0" +shuttle-actix-web = "0.23.0" +shuttle-runtime = "0.23.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 8b2aec8a..7acdecbe 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.22.0" -shuttle-runtime = "0.22.0" +shuttle-actix-web = "0.23.0" +shuttle-runtime = "0.23.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.22.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.23.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 7e883c74..6c5c3363 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,8 +13,8 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.22.0" -shuttle-runtime = "0.22.0" -shuttle-static-folder = "0.22.0" +shuttle-actix-web = "0.23.0" +shuttle-runtime = "0.23.0" +shuttle-static-folder = "0.23.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index cb78e5ba..e557f1e7 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.22.0" -shuttle-runtime = "0.22.0" +shuttle-axum = "0.23.0" +shuttle-runtime = "0.23.0" tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 943fb99f..906a7999 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.22.0" -shuttle-runtime = "0.22.0" -shuttle-static-folder = "0.22.0" +shuttle-axum = "0.23.0" +shuttle-runtime = "0.23.0" +shuttle-static-folder = "0.23.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index c3bfbb98..8ccbd4da 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.22.0" -shuttle-runtime = "0.22.0" -shuttle-static-folder = "0.22.0" +shuttle-axum = "0.23.0" +shuttle-runtime = "0.23.0" +shuttle-static-folder = "0.23.0" tokio = "1.26.0" diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 786584b0..75b419e8 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = { version = "0.6.18" } -shuttle-axum = { version = "0.22.0" } -shuttle-runtime = { version = "0.22.0" } -shuttle-turso = { version = "0.22.0" } +shuttle-axum = { version = "0.23.0" } +shuttle-runtime = { version = "0.23.0" } +shuttle-turso = { version = "0.23.0" } libsql-client = "=0.30.1" tokio = { version = "1.26.0" } serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 51146334..6950eb42 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,8 +11,8 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.22.0" -shuttle-runtime = "0.22.0" -shuttle-static-folder = "0.22.0" +shuttle-axum = "0.23.0" +shuttle-runtime = "0.23.0" +shuttle-static-folder = "0.23.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index 93b6e263..344d3076 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.22.0" -shuttle-runtime = "0.22.0" +shuttle-axum = "0.23.0" +shuttle-runtime = "0.23.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 2c387c2d..eda4437e 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.6.18" serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.22.0" -shuttle-axum = "0.22.0" -shuttle-runtime = "0.22.0" +shuttle-service = "0.23.0" +shuttle-axum = "0.23.0" +shuttle-runtime = "0.23.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index fce3ee45..96afe345 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.22.0" +shuttle-runtime = "0.23.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index 9d7b7f4e..43723b21 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -12,6 +12,6 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.22.0" -shuttle-runtime = "0.22.0" +shuttle-persist = "0.23.0" +shuttle-runtime = "0.23.0" tokio = "1.28.0" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 58e9d448..ef1c2e0a 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,11 +16,11 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.22.0" -shuttle-runtime = "0.22.0" -shuttle-secrets = "0.22.0" -shuttle-shared-db = { version = "0.22.0", features = ["postgres"] } -shuttle-static-folder = "0.22.0" +shuttle-axum = "0.23.0" +shuttle-runtime = "0.23.0" +shuttle-secrets = "0.23.0" +shuttle-shared-db = { version = "0.23.0", features = ["postgres"] } +shuttle-static-folder = "0.23.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index 205cce5a..5c84325b 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.22.0" +shuttle-next = "0.23.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index c7714d87..dc4955b0 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -11,7 +11,7 @@ path = "src/standalone.rs" [dependencies] axum = "0.6.18" dotenvy = "0.15.7" -shuttle-axum = "0.22.0" -shuttle-runtime = "0.22.0" -shuttle-secrets = "0.22.0" +shuttle-axum = "0.23.0" +shuttle-runtime = "0.23.0" +shuttle-secrets = "0.23.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 935dc22d..d713ef10 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.22.0" -shuttle-runtime = "0.22.0" +shuttle-poem = "0.23.0" +shuttle-runtime = "0.23.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 8ca469c6..3ca6e330 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.22.0" -shuttle-shared-db = { version = "0.22.0", features = ["mongodb"] } -shuttle-runtime = "0.22.0" +shuttle-poem = "0.23.0" +shuttle-shared-db = { version = "0.23.0", features = ["mongodb"] } +shuttle-runtime = "0.23.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index ebd598a2..88a11d60 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.22.0" -shuttle-runtime = "0.22.0" -shuttle-shared-db = { version = "0.22.0", features = ["postgres"] } +shuttle-poem = "0.23.0" +shuttle-runtime = "0.23.0" +shuttle-shared-db = { version = "0.23.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 2bfd95aa..a80efc7f 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.22.0" -shuttle-runtime = "0.22.0" -shuttle-secrets = "0.22.0" +shuttle-poise = "0.23.0" +shuttle-runtime = "0.23.0" +shuttle-secrets = "0.23.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index 9ff21c9f..8e163276 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.22.0" -shuttle-runtime = "0.22.0" +shuttle-rocket = "0.23.0" +shuttle-runtime = "0.23.0" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 223facb8..2bb7ba94 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.22.0" -shuttle-runtime = "0.22.0" -shuttle-static-folder = "0.22.0" +shuttle-rocket = "0.23.0" +shuttle-runtime = "0.23.0" +shuttle-static-folder = "0.23.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index e0ab0127..07b9caf6 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.22.0" -shuttle-runtime = "0.22.0" +shuttle-rocket = "0.23.0" +shuttle-runtime = "0.23.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index d653853c..d97d0ac2 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.22.0" -shuttle-rocket = "0.22.0" -shuttle-runtime = "0.22.0" +shuttle-persist = "0.23.0" +shuttle-rocket = "0.23.0" +shuttle-runtime = "0.23.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index ec17f73b..4f0cbc7f 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.22.0", features = ["postgres"] } -shuttle-rocket = "0.22.0" -shuttle-runtime = "0.22.0" +shuttle-shared-db = { version = "0.23.0", features = ["postgres"] } +shuttle-rocket = "0.23.0" +shuttle-runtime = "0.23.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index d51ae0be..d0dd7f32 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = "0.22.0" -shuttle-runtime = "0.22.0" -shuttle-secrets = "0.22.0" +shuttle-rocket = "0.23.0" +shuttle-runtime = "0.23.0" +shuttle-secrets = "0.23.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 1c709726..9c9109b2 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = "0.22.0" -shuttle-runtime = "0.22.0" +shuttle-rocket = "0.23.0" +shuttle-runtime = "0.23.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.22.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.23.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 8320c3d3..78a489de 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.22.0" -shuttle-runtime = "0.22.0" +shuttle-rocket = "0.23.0" +shuttle-runtime = "0.23.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index aa7c0443..24dd1b0a 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.22.0" -shuttle-runtime = "0.22.0" +shuttle-salvo = "0.23.0" +shuttle-runtime = "0.23.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index c9a5204a..95bde6d0 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.22.0" -shuttle-runtime = "0.22.0" +shuttle-serenity = "0.23.0" +shuttle-runtime = "0.23.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.22.0" +shuttle-secrets = "0.23.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index fe69fde8..f6d46cc9 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.22.0" -shuttle-serenity = "0.22.0" -shuttle-runtime = "0.22.0" -shuttle-shared-db = { version = "0.22.0", features = ["postgres"] } +shuttle-secrets = "0.23.0" +shuttle-serenity = "0.23.0" +shuttle-runtime = "0.23.0" +shuttle-shared-db = { version = "0.23.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 3a2461c1..aa21939d 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.22.0" -shuttle-runtime = "0.22.0" +shuttle-thruster = "0.23.0" +shuttle-runtime = "0.23.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index ae40e1d5..25089061 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.22.0", features = ["postgres"] } -shuttle-thruster = "0.22.0" -shuttle-runtime = "0.22.0" +shuttle-aws-rds = { version = "0.23.0", features = ["postgres"] } +shuttle-thruster = "0.23.0" +shuttle-runtime = "0.23.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index d190f359..81d46251 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.22.0" -shuttle-runtime = "0.22.0" +shuttle-tide = "0.23.0" +shuttle-runtime = "0.23.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index a1d253c9..83f43f90 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.22.0", features = ["postgres"] } -shuttle-runtime = "0.22.0" -shuttle-tide = "0.22.0" +shuttle-aws-rds = { version = "0.23.0", features = ["postgres"] } +shuttle-runtime = "0.23.0" +shuttle-tide = "0.23.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index cee2de13..cb5b84d4 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.22.0" -shuttle-tower = "0.22.0" +shuttle-runtime = "0.23.0" +shuttle-tower = "0.23.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index d9f92584..24b8dcc5 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.22.0" -shuttle-warp = "0.22.0" +shuttle-runtime = "0.23.0" +shuttle-warp = "0.23.0" tokio = "1.26.0" warp = "0.3.3" From 6837de8edcc08a9405e3d794702f6933d249abe2 Mon Sep 17 00:00:00 2001 From: AlphaKeks <85143381+AlphaKeks@users.noreply.github.com> Date: Tue, 15 Aug 2023 22:49:37 +0200 Subject: [PATCH 082/239] feat: examples for injecting a custom tracing layer (#78) * feat: custom `tracing-subscriber` layer * feat: utilize new `Registry` type * refactor: extend example with logging to a file * feat: add example for receiving logs with axum This example creates a custom logger which sends any new logs through a tokio channel, which can be subscribed to from an `AppState` struct on axum's side. A user can make a GET request to `/logs/:amount` to tell the server how many logs they want before closing the connection. The server will then wait for `amount` messages to be received before returning them all as a json array. You start with a GET request: ```http GET /logs/3 ``` This will block until 3 messages have been received, so let's send some! ```http POST /message/hello POST /message/world POST /message/how%20are%20you%3F ``` Now the initial GET request should have resolved with 3 json objects containing the tracing logs generated in each message request. * fix: adjust paths to work if used as submodule in main repo * docs: update docs to include new examples * fix: change `eprintln` to `println` * nit: comments and versions --------- Co-authored-by: AlphaKeks Co-authored-by: jonaro00 <54029719+jonaro00@users.noreply.github.com> --- README.md | 2 + tracing/axum-logs-endpoint/Cargo.toml | 17 ++++ tracing/axum-logs-endpoint/Shuttle.toml | 1 + tracing/axum-logs-endpoint/src/logger.rs | 48 ++++++++++++ tracing/axum-logs-endpoint/src/main.rs | 54 +++++++++++++ tracing/axum-logs-endpoint/src/state.rs | 21 +++++ tracing/custom-layer/Cargo.toml | 11 +++ tracing/custom-layer/Shuttle.toml | 1 + tracing/custom-layer/src/main.rs | 98 ++++++++++++++++++++++++ 9 files changed, 253 insertions(+) create mode 100644 tracing/axum-logs-endpoint/Cargo.toml create mode 100644 tracing/axum-logs-endpoint/Shuttle.toml create mode 100644 tracing/axum-logs-endpoint/src/logger.rs create mode 100644 tracing/axum-logs-endpoint/src/main.rs create mode 100644 tracing/axum-logs-endpoint/src/state.rs create mode 100644 tracing/custom-layer/Cargo.toml create mode 100644 tracing/custom-layer/Shuttle.toml create mode 100644 tracing/custom-layer/src/main.rs diff --git a/README.md b/README.md index c30bbd9a..3987329f 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,8 @@ Thruster | [postgres](./thruster/postgres/) | TODO app with a Postgres DB | `car Tide | [hello-world](./tide/hello-world/) | Hello World | `cargo shuttle init --template tide` Tide | [postgres](./tide/postgres/) | TODO app with a Postgres DB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder tide/postgres` Tower | [hello-world](./tower/hello-world/) | Hello World | `cargo shuttle init --template tower` +Tracing | [custom-layer](./tracing/custom-layer/) | Custom tracing layer | `cargo shuttle init --template --from shuttle-hq/shuttle-examples --subfolder tracing/custom-layer` +Tracing | [axum-logs-endpoint](./tracing/axum-logs-endpoint/) | Expose application logs with Axum | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder tracing/axum-logs-endpoint` Warp | [hello-world](./warp/hello-world/) | Hello World | `cargo shuttle init --template warp` *Custom Service* | [none](./custom-service/none/) | Empty service - A barebones implementation of Shuttle Service trait that does nothing | `cargo shuttle init --template none` *Custom Service* | [request-scheduler](./custom-service/request-scheduler/) | A custom *Request Scheduler* service | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder custom-service/request-scheduler` diff --git a/tracing/axum-logs-endpoint/Cargo.toml b/tracing/axum-logs-endpoint/Cargo.toml new file mode 100644 index 00000000..d91a0a75 --- /dev/null +++ b/tracing/axum-logs-endpoint/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "axum-logs-endpoint" +version = "0.1.0" +edition = "2021" + +[dependencies] +tracing = "0.1.37" +tracing-subscriber = { version = "0.3.17", features = ["json"] } +tokio = "1.28.2" + +axum = "0.6.19" +axum-error = "0.2.0" +serde = { version = "1.0.180", features = ["derive"] } +serde_json = "1.0.104" +shuttle-runtime = "0.23.0" +shuttle-axum = "0.23.0" +lazy_static = "1.4.0" diff --git a/tracing/axum-logs-endpoint/Shuttle.toml b/tracing/axum-logs-endpoint/Shuttle.toml new file mode 100644 index 00000000..6dd40ba9 --- /dev/null +++ b/tracing/axum-logs-endpoint/Shuttle.toml @@ -0,0 +1 @@ +name = "axum-logs-endpoint" diff --git a/tracing/axum-logs-endpoint/src/logger.rs b/tracing/axum-logs-endpoint/src/logger.rs new file mode 100644 index 00000000..76a3b957 --- /dev/null +++ b/tracing/axum-logs-endpoint/src/logger.rs @@ -0,0 +1,48 @@ +use lazy_static::lazy_static; +use serde_json::Value as JsonValue; +use std::{io, sync::Mutex}; +use tokio::sync::broadcast; +use tracing::metadata::LevelFilter; +use tracing_subscriber::Layer; + +lazy_static! { + pub static ref LOG_CHANNEL: broadcast::Sender = broadcast::channel(64).0; +} + +pub struct Logger { + tx: broadcast::Sender, +} + +impl Logger { + pub fn new() -> Self { + Self { + tx: LOG_CHANNEL.clone(), + } + } + + pub fn make_layer() -> impl Layer { + tracing_subscriber::fmt::layer() + .pretty() + .json() + .with_writer(Mutex::new(Self::new())) + .with_filter(LevelFilter::INFO) + } +} + +impl io::Write for Logger { + fn write(&mut self, buf: &[u8]) -> io::Result { + let Ok(log) = serde_json::from_slice(buf) else { + return Ok(0); + }; + + if let Ok(n) = self.tx.send(log) { + return Ok(n); + } + + Ok(0) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} diff --git a/tracing/axum-logs-endpoint/src/main.rs b/tracing/axum-logs-endpoint/src/main.rs new file mode 100644 index 00000000..5e9d61a9 --- /dev/null +++ b/tracing/axum-logs-endpoint/src/main.rs @@ -0,0 +1,54 @@ +use std::{sync::Arc, time::SystemTime}; + +use axum::{ + extract::{Path, State}, + routing::{get, post}, + Json, Router, +}; +use axum_error::Result; +use serde_json::Value as JsonValue; +use shuttle_axum::ShuttleAxum; +use tracing::info; + +mod logger; +use logger::Logger; + +mod state; +use state::AppState; + +#[shuttle_runtime::main(tracing_layer = Logger::make_layer)] +async fn axum_logs() -> ShuttleAxum { + let state = AppState::new(); + let router = Router::new() + .route("/", get(|| async { "Hello, world!" })) + .route("/message/:message", post(send_message)) + .route("/logs/:amount", get(get_logs)) + .with_state(state); + + Ok(router.into()) +} + +// Creates a tracing log with `message` +async fn send_message(Path(message): Path) -> String { + info!(?message, now = ?SystemTime::now()); + message +} + +// Waits for `amount` log lines to arrive in the channel and returns them +async fn get_logs( + Path(amount): Path, + State(state): State>, +) -> Result>> { + let mut rx = state.sub(); + let mut logs = Vec::new(); + + while let Ok(log) = rx.recv().await { + logs.push(log); + + if logs.len() == amount { + break; + } + } + + Ok(Json(logs)) +} diff --git a/tracing/axum-logs-endpoint/src/state.rs b/tracing/axum-logs-endpoint/src/state.rs new file mode 100644 index 00000000..1d65274e --- /dev/null +++ b/tracing/axum-logs-endpoint/src/state.rs @@ -0,0 +1,21 @@ +use crate::logger::LOG_CHANNEL; +use serde_json::Value as JsonValue; +use std::sync::Arc; +use tokio::sync::broadcast; + +#[derive(Debug)] +pub struct AppState { + logs: broadcast::Sender, +} + +impl AppState { + pub fn new() -> Arc { + Arc::new(Self { + logs: LOG_CHANNEL.clone(), + }) + } + + pub fn sub(&self) -> broadcast::Receiver { + self.logs.subscribe() + } +} diff --git a/tracing/custom-layer/Cargo.toml b/tracing/custom-layer/Cargo.toml new file mode 100644 index 00000000..89dfab4d --- /dev/null +++ b/tracing/custom-layer/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "custom-tracing-layer" +version = "0.1.0" +edition = "2021" + +[dependencies] +lazy_static = "1.4.0" +shuttle-runtime = "0.23.0" +tracing = "0.1.37" +tracing-subscriber = "0.3.17" +tokio = "1.28.2" diff --git a/tracing/custom-layer/Shuttle.toml b/tracing/custom-layer/Shuttle.toml new file mode 100644 index 00000000..7481d921 --- /dev/null +++ b/tracing/custom-layer/Shuttle.toml @@ -0,0 +1 @@ +name = "custom-tracing-layer-example" diff --git a/tracing/custom-layer/src/main.rs b/tracing/custom-layer/src/main.rs new file mode 100644 index 00000000..3c011ee7 --- /dev/null +++ b/tracing/custom-layer/src/main.rs @@ -0,0 +1,98 @@ +use lazy_static::lazy_static; +use std::{net::SocketAddr, time::Duration}; +use tokio::sync::broadcast; +use tracing::info; +use tracing_subscriber::fmt::MakeWriter; + +lazy_static! { + /// Global channel for sending logs + pub static ref LOG_CHANNEL: broadcast::Sender = broadcast::channel(64).0; +} + +#[shuttle_runtime::main(tracing_layer = Logger::init)] +async fn init() -> Result { + Ok(MyService::new()) +} + +#[derive(Debug)] +struct MyService { + pub logs: broadcast::Receiver, +} + +impl MyService { + pub fn new() -> Self { + Self { + logs: LOG_CHANNEL.subscribe(), + } + } +} + +#[shuttle_runtime::async_trait] +impl shuttle_runtime::Service for MyService { + async fn bind(mut self, _addr: SocketAddr) -> Result<(), shuttle_runtime::Error> { + // send some messages... + for i in 0..10 { + tokio::spawn(async move { + tokio::time::sleep(Duration::from_secs(i)).await; + info!("Hello from thread #{i}!"); + }); + } + + while let Ok(message) = self.logs.recv().await { + // do something with your logs! + println!("Got a new log!"); + tokio::fs::write(Logger::LOG_FILE, message).await?; + } + + Ok(()) + } +} + +/// Logger struct passed to our custom tracing layer +#[derive(Debug)] +struct Logger { + sender: broadcast::Sender, +} + +// Necessary for [`MakeWriter`] impl +impl std::io::Write for Logger { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + let message = String::from_utf8_lossy(buf); + + if let Err(err) = self.sender.send(message.to_string()) { + eprintln!("Failed to send message: {err:?}"); + return Err(std::io::Error::new(std::io::ErrorKind::Other, err)); + } + + Ok(buf.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} + +// Necessary for passing [`Logger`] as a custom writer to [`tracing_subscriber`] +impl MakeWriter<'_> for Logger { + type Writer = Self; + + fn make_writer(&self) -> Self::Writer { + Self { + sender: LOG_CHANNEL.clone(), + } + } +} + +impl Logger { + const LOG_FILE: &str = "/var/log/my-service.log"; + + pub fn init() -> impl tracing_subscriber::Layer { + let logger = Self { + sender: LOG_CHANNEL.clone(), + }; + + tracing_subscriber::fmt::layer() + .without_time() + .with_writer(logger) + } +} From a079b84e1b2ce8331b9ec5c7d8f5234704da8b71 Mon Sep 17 00:00:00 2001 From: Iulian Barbu <14218860+iulianbarbu@users.noreply.github.com> Date: Wed, 16 Aug 2023 15:02:59 +0300 Subject: [PATCH 083/239] chore: v0.24.0 release (#80) --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 6 +++--- axum/hello-world/Cargo.toml | 4 ++-- axum/static-files/Cargo.toml | 6 +++--- axum/static-next-server/Cargo.toml | 6 +++--- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 6 +++--- axum/with-state/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 10 +++++----- fullstack-templates/saas/package-lock.json | 2 +- next/hello-world/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 6 +++--- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 6 +++--- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- tracing/axum-logs-endpoint/Cargo.toml | 4 ++-- tracing/custom-layer/Cargo.toml | 2 +- warp/hello-world/Cargo.toml | 4 ++-- 39 files changed, 98 insertions(+), 98 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 7748fb37..f3f8a990 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.23.0" -shuttle-runtime = "0.23.0" +shuttle-actix-web = "0.24.0" +shuttle-runtime = "0.24.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 7acdecbe..6e222f4f 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.23.0" -shuttle-runtime = "0.23.0" +shuttle-actix-web = "0.24.0" +shuttle-runtime = "0.24.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.23.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.24.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 6c5c3363..c7b300c1 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,8 +13,8 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.23.0" -shuttle-runtime = "0.23.0" -shuttle-static-folder = "0.23.0" +shuttle-actix-web = "0.24.0" +shuttle-runtime = "0.24.0" +shuttle-static-folder = "0.24.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index e557f1e7..a03a2644 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.23.0" -shuttle-runtime = "0.23.0" +shuttle-axum = "0.24.0" +shuttle-runtime = "0.24.0" tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 906a7999..49c90d70 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.23.0" -shuttle-runtime = "0.23.0" -shuttle-static-folder = "0.23.0" +shuttle-axum = "0.24.0" +shuttle-runtime = "0.24.0" +shuttle-static-folder = "0.24.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 8ccbd4da..cc902e78 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.23.0" -shuttle-runtime = "0.23.0" -shuttle-static-folder = "0.23.0" +shuttle-axum = "0.24.0" +shuttle-runtime = "0.24.0" +shuttle-static-folder = "0.24.0" tokio = "1.26.0" diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 75b419e8..3c738913 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = { version = "0.6.18" } -shuttle-axum = { version = "0.23.0" } -shuttle-runtime = { version = "0.23.0" } -shuttle-turso = { version = "0.23.0" } +shuttle-axum = { version = "0.24.0" } +shuttle-runtime = { version = "0.24.0" } +shuttle-turso = { version = "0.24.0" } libsql-client = "=0.30.1" tokio = { version = "1.26.0" } serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 6950eb42..c7f3b461 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,8 +11,8 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.23.0" -shuttle-runtime = "0.23.0" -shuttle-static-folder = "0.23.0" +shuttle-axum = "0.24.0" +shuttle-runtime = "0.24.0" +shuttle-static-folder = "0.24.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index 344d3076..3495b754 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.23.0" -shuttle-runtime = "0.23.0" +shuttle-axum = "0.24.0" +shuttle-runtime = "0.24.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index eda4437e..e6d8c740 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.6.18" serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.23.0" -shuttle-axum = "0.23.0" -shuttle-runtime = "0.23.0" +shuttle-service = "0.24.0" +shuttle-axum = "0.24.0" +shuttle-runtime = "0.24.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 96afe345..ecd8423f 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.23.0" +shuttle-runtime = "0.24.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index 43723b21..45205f2a 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -12,6 +12,6 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.23.0" -shuttle-runtime = "0.23.0" +shuttle-persist = "0.24.0" +shuttle-runtime = "0.24.0" tokio = "1.28.0" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index ef1c2e0a..1dd52a17 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,11 +16,11 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.23.0" -shuttle-runtime = "0.23.0" -shuttle-secrets = "0.23.0" -shuttle-shared-db = { version = "0.23.0", features = ["postgres"] } -shuttle-static-folder = "0.23.0" +shuttle-axum = "0.24.0" +shuttle-runtime = "0.24.0" +shuttle-secrets = "0.24.0" +shuttle-shared-db = { version = "0.24.0", features = ["postgres"] } +shuttle-static-folder = "0.24.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/fullstack-templates/saas/package-lock.json b/fullstack-templates/saas/package-lock.json index 5e734fb4..2bd0188a 100644 --- a/fullstack-templates/saas/package-lock.json +++ b/fullstack-templates/saas/package-lock.json @@ -3530,7 +3530,7 @@ "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", "dependencies": { "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" + "scheduler": "^0.24.0" }, "peerDependencies": { "react": "^18.2.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index 5c84325b..8841646a 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.23.0" +shuttle-next = "0.24.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index dc4955b0..5ed47db9 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -11,7 +11,7 @@ path = "src/standalone.rs" [dependencies] axum = "0.6.18" dotenvy = "0.15.7" -shuttle-axum = "0.23.0" -shuttle-runtime = "0.23.0" -shuttle-secrets = "0.23.0" +shuttle-axum = "0.24.0" +shuttle-runtime = "0.24.0" +shuttle-secrets = "0.24.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index d713ef10..8a26e4df 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.23.0" -shuttle-runtime = "0.23.0" +shuttle-poem = "0.24.0" +shuttle-runtime = "0.24.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 3ca6e330..03741290 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.23.0" -shuttle-shared-db = { version = "0.23.0", features = ["mongodb"] } -shuttle-runtime = "0.23.0" +shuttle-poem = "0.24.0" +shuttle-shared-db = { version = "0.24.0", features = ["mongodb"] } +shuttle-runtime = "0.24.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 88a11d60..af3fd56c 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.23.0" -shuttle-runtime = "0.23.0" -shuttle-shared-db = { version = "0.23.0", features = ["postgres"] } +shuttle-poem = "0.24.0" +shuttle-runtime = "0.24.0" +shuttle-shared-db = { version = "0.24.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index a80efc7f..b7ff19f2 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.23.0" -shuttle-runtime = "0.23.0" -shuttle-secrets = "0.23.0" +shuttle-poise = "0.24.0" +shuttle-runtime = "0.24.0" +shuttle-secrets = "0.24.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index 8e163276..307550d2 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.23.0" -shuttle-runtime = "0.23.0" +shuttle-rocket = "0.24.0" +shuttle-runtime = "0.24.0" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 2bb7ba94..3094eb30 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.23.0" -shuttle-runtime = "0.23.0" -shuttle-static-folder = "0.23.0" +shuttle-rocket = "0.24.0" +shuttle-runtime = "0.24.0" +shuttle-static-folder = "0.24.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 07b9caf6..cf876e22 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.23.0" -shuttle-runtime = "0.23.0" +shuttle-rocket = "0.24.0" +shuttle-runtime = "0.24.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index d97d0ac2..71b77cea 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.23.0" -shuttle-rocket = "0.23.0" -shuttle-runtime = "0.23.0" +shuttle-persist = "0.24.0" +shuttle-rocket = "0.24.0" +shuttle-runtime = "0.24.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 4f0cbc7f..f56b1404 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.23.0", features = ["postgres"] } -shuttle-rocket = "0.23.0" -shuttle-runtime = "0.23.0" +shuttle-shared-db = { version = "0.24.0", features = ["postgres"] } +shuttle-rocket = "0.24.0" +shuttle-runtime = "0.24.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index d0dd7f32..58028563 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = "0.23.0" -shuttle-runtime = "0.23.0" -shuttle-secrets = "0.23.0" +shuttle-rocket = "0.24.0" +shuttle-runtime = "0.24.0" +shuttle-secrets = "0.24.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 9c9109b2..d0603321 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = "0.23.0" -shuttle-runtime = "0.23.0" +shuttle-rocket = "0.24.0" +shuttle-runtime = "0.24.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.23.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.24.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 78a489de..8953f247 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.23.0" -shuttle-runtime = "0.23.0" +shuttle-rocket = "0.24.0" +shuttle-runtime = "0.24.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 24dd1b0a..ee950d4c 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.23.0" -shuttle-runtime = "0.23.0" +shuttle-salvo = "0.24.0" +shuttle-runtime = "0.24.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 95bde6d0..3269c1d1 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.23.0" -shuttle-runtime = "0.23.0" +shuttle-serenity = "0.24.0" +shuttle-runtime = "0.24.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.23.0" +shuttle-secrets = "0.24.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index f6d46cc9..b395d78c 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.23.0" -shuttle-serenity = "0.23.0" -shuttle-runtime = "0.23.0" -shuttle-shared-db = { version = "0.23.0", features = ["postgres"] } +shuttle-secrets = "0.24.0" +shuttle-serenity = "0.24.0" +shuttle-runtime = "0.24.0" +shuttle-shared-db = { version = "0.24.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index aa21939d..0a0646de 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.23.0" -shuttle-runtime = "0.23.0" +shuttle-thruster = "0.24.0" +shuttle-runtime = "0.24.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 25089061..2d926101 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.23.0", features = ["postgres"] } -shuttle-thruster = "0.23.0" -shuttle-runtime = "0.23.0" +shuttle-aws-rds = { version = "0.24.0", features = ["postgres"] } +shuttle-thruster = "0.24.0" +shuttle-runtime = "0.24.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 81d46251..de955924 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.23.0" -shuttle-runtime = "0.23.0" +shuttle-tide = "0.24.0" +shuttle-runtime = "0.24.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index 83f43f90..cebdc3cc 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.23.0", features = ["postgres"] } -shuttle-runtime = "0.23.0" -shuttle-tide = "0.23.0" +shuttle-aws-rds = { version = "0.24.0", features = ["postgres"] } +shuttle-runtime = "0.24.0" +shuttle-tide = "0.24.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index cb5b84d4..9c86186b 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.23.0" -shuttle-tower = "0.23.0" +shuttle-runtime = "0.24.0" +shuttle-tower = "0.24.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/axum-logs-endpoint/Cargo.toml b/tracing/axum-logs-endpoint/Cargo.toml index d91a0a75..eb38ecc6 100644 --- a/tracing/axum-logs-endpoint/Cargo.toml +++ b/tracing/axum-logs-endpoint/Cargo.toml @@ -12,6 +12,6 @@ axum = "0.6.19" axum-error = "0.2.0" serde = { version = "1.0.180", features = ["derive"] } serde_json = "1.0.104" -shuttle-runtime = "0.23.0" -shuttle-axum = "0.23.0" +shuttle-runtime = "0.24.0" +shuttle-axum = "0.24.0" lazy_static = "1.4.0" diff --git a/tracing/custom-layer/Cargo.toml b/tracing/custom-layer/Cargo.toml index 89dfab4d..25a316b8 100644 --- a/tracing/custom-layer/Cargo.toml +++ b/tracing/custom-layer/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] lazy_static = "1.4.0" -shuttle-runtime = "0.23.0" +shuttle-runtime = "0.24.0" tracing = "0.1.37" tracing-subscriber = "0.3.17" tokio = "1.28.2" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 24b8dcc5..aa697d3c 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.23.0" -shuttle-warp = "0.23.0" +shuttle-runtime = "0.24.0" +shuttle-warp = "0.24.0" tokio = "1.26.0" warp = "0.3.3" From d617b764b04d99647636b4e552207d993a635d58 Mon Sep 17 00:00:00 2001 From: Tyler Bloom Date: Fri, 18 Aug 2023 07:32:52 -0400 Subject: [PATCH 084/239] Added a fullstack Rust template to the 'Community Examples' section of the README (#74) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 3987329f..64441411 100644 --- a/README.md +++ b/README.md @@ -112,3 +112,4 @@ FRAMEWORK | [NAME](LINK_TO_REPO) | DESCRIPTION | `cargo shuttle init --from USER **Framework** | **Name & Link** | **Description** | **Command** --------------|-----------------|-------------|---------------- Axum | [Test](https://github.com/shuttle-hq/shuttle-examples) | A test example A test example A test example | `cargo shuttle init --from / --subfolder ` +Axum/Any | [Fullstack Rust](https://github.com/TylerBloom/shuttle-fullstack-rust-example) | A basic project template for fullstack Rust projects | `cargo shuttle init --from TylerBloom/shuttle-fullstack-rust-example` From edeb214fe8edf204d2bb3b8053b7a31292020141 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Sat, 26 Aug 2023 03:37:00 -0700 Subject: [PATCH 085/239] add axum yew webapp example (#82) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 64441411..61987aa4 100644 --- a/README.md +++ b/README.md @@ -113,3 +113,4 @@ FRAMEWORK | [NAME](LINK_TO_REPO) | DESCRIPTION | `cargo shuttle init --from USER --------------|-----------------|-------------|---------------- Axum | [Test](https://github.com/shuttle-hq/shuttle-examples) | A test example A test example A test example | `cargo shuttle init --from / --subfolder ` Axum/Any | [Fullstack Rust](https://github.com/TylerBloom/shuttle-fullstack-rust-example) | A basic project template for fullstack Rust projects | `cargo shuttle init --from TylerBloom/shuttle-fullstack-rust-example` +Axum/Yew | [Web App with Yew](https://github.com/sentinel1909/shuttle-template-yew) | A basic project template for a web app using the Yew framework | `cargo shuttle init --from sentinel1909/shuttle-template-yew` | From 07f1d3f3a643c014f35037f87e6d36cb87906b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Mon, 28 Aug 2023 12:43:50 +0200 Subject: [PATCH 086/239] chore: v0.25.0 (#83) --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 6 +++--- axum/hello-world/Cargo.toml | 4 ++-- axum/static-files/Cargo.toml | 6 +++--- axum/static-next-server/Cargo.toml | 6 +++--- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 6 +++--- axum/with-state/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 10 +++++----- next/hello-world/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 6 +++--- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 6 +++--- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- tracing/axum-logs-endpoint/Cargo.toml | 4 ++-- tracing/custom-layer/Cargo.toml | 2 +- warp/hello-world/Cargo.toml | 4 ++-- 38 files changed, 97 insertions(+), 97 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index f3f8a990..e1636dc4 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.24.0" -shuttle-runtime = "0.24.0" +shuttle-actix-web = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 6e222f4f..730cf7bd 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.24.0" -shuttle-runtime = "0.24.0" +shuttle-actix-web = "0.25.0" +shuttle-runtime = "0.25.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.24.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index c7b300c1..039dac0d 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,8 +13,8 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.24.0" -shuttle-runtime = "0.24.0" -shuttle-static-folder = "0.24.0" +shuttle-actix-web = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-static-folder = "0.25.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index a03a2644..0b7d5bb7 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.24.0" -shuttle-runtime = "0.24.0" +shuttle-axum = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 49c90d70..07f4afb9 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.24.0" -shuttle-runtime = "0.24.0" -shuttle-static-folder = "0.24.0" +shuttle-axum = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-static-folder = "0.25.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index cc902e78..5c495af1 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.24.0" -shuttle-runtime = "0.24.0" -shuttle-static-folder = "0.24.0" +shuttle-axum = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-static-folder = "0.25.0" tokio = "1.26.0" diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 3c738913..4a9e6193 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = { version = "0.6.18" } -shuttle-axum = { version = "0.24.0" } -shuttle-runtime = { version = "0.24.0" } -shuttle-turso = { version = "0.24.0" } +shuttle-axum = { version = "0.25.0" } +shuttle-runtime = { version = "0.25.0" } +shuttle-turso = { version = "0.25.0" } libsql-client = "=0.30.1" tokio = { version = "1.26.0" } serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index c7f3b461..dee0b541 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,8 +11,8 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.24.0" -shuttle-runtime = "0.24.0" -shuttle-static-folder = "0.24.0" +shuttle-axum = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-static-folder = "0.25.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index 3495b754..c62c3398 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.24.0" -shuttle-runtime = "0.24.0" +shuttle-axum = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index e6d8c740..ecdbcd95 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.6.18" serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.24.0" -shuttle-axum = "0.24.0" -shuttle-runtime = "0.24.0" +shuttle-service = "0.25.0" +shuttle-axum = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index ecd8423f..f7a08045 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.24.0" +shuttle-runtime = "0.25.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index 45205f2a..dc2341d9 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -12,6 +12,6 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.24.0" -shuttle-runtime = "0.24.0" +shuttle-persist = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.28.0" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 1dd52a17..b83d6491 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,11 +16,11 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.24.0" -shuttle-runtime = "0.24.0" -shuttle-secrets = "0.24.0" -shuttle-shared-db = { version = "0.24.0", features = ["postgres"] } -shuttle-static-folder = "0.24.0" +shuttle-axum = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-secrets = "0.25.0" +shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } +shuttle-static-folder = "0.25.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index 8841646a..7324dfc2 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.24.0" +shuttle-next = "0.25.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 5ed47db9..682c91c6 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -11,7 +11,7 @@ path = "src/standalone.rs" [dependencies] axum = "0.6.18" dotenvy = "0.15.7" -shuttle-axum = "0.24.0" -shuttle-runtime = "0.24.0" -shuttle-secrets = "0.24.0" +shuttle-axum = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-secrets = "0.25.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 8a26e4df..b7a0091b 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.24.0" -shuttle-runtime = "0.24.0" +shuttle-poem = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 03741290..9df9144d 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.24.0" -shuttle-shared-db = { version = "0.24.0", features = ["mongodb"] } -shuttle-runtime = "0.24.0" +shuttle-poem = "0.25.0" +shuttle-shared-db = { version = "0.25.0", features = ["mongodb"] } +shuttle-runtime = "0.25.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index af3fd56c..d347f2ca 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.24.0" -shuttle-runtime = "0.24.0" -shuttle-shared-db = { version = "0.24.0", features = ["postgres"] } +shuttle-poem = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index b7ff19f2..4e422723 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.24.0" -shuttle-runtime = "0.24.0" -shuttle-secrets = "0.24.0" +shuttle-poise = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-secrets = "0.25.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index 307550d2..33bba1ba 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.24.0" -shuttle-runtime = "0.24.0" +shuttle-rocket = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 3094eb30..6bd6ad22 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.24.0" -shuttle-runtime = "0.24.0" -shuttle-static-folder = "0.24.0" +shuttle-rocket = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-static-folder = "0.25.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index cf876e22..0feca5ba 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.24.0" -shuttle-runtime = "0.24.0" +shuttle-rocket = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 71b77cea..63955297 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.24.0" -shuttle-rocket = "0.24.0" -shuttle-runtime = "0.24.0" +shuttle-persist = "0.25.0" +shuttle-rocket = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index f56b1404..4f075af2 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.24.0", features = ["postgres"] } -shuttle-rocket = "0.24.0" -shuttle-runtime = "0.24.0" +shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } +shuttle-rocket = "0.25.0" +shuttle-runtime = "0.25.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 58028563..8e59fc7c 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = "0.24.0" -shuttle-runtime = "0.24.0" -shuttle-secrets = "0.24.0" +shuttle-rocket = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-secrets = "0.25.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index d0603321..89ec7d5b 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = "0.24.0" -shuttle-runtime = "0.24.0" +shuttle-rocket = "0.25.0" +shuttle-runtime = "0.25.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.24.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 8953f247..9b3c0c82 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.24.0" -shuttle-runtime = "0.24.0" +shuttle-rocket = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index ee950d4c..d1e53b05 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.24.0" -shuttle-runtime = "0.24.0" +shuttle-salvo = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 3269c1d1..23f4dc9d 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.24.0" -shuttle-runtime = "0.24.0" +shuttle-serenity = "0.25.0" +shuttle-runtime = "0.25.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.24.0" +shuttle-secrets = "0.25.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index b395d78c..37a91599 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.24.0" -shuttle-serenity = "0.24.0" -shuttle-runtime = "0.24.0" -shuttle-shared-db = { version = "0.24.0", features = ["postgres"] } +shuttle-secrets = "0.25.0" +shuttle-serenity = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 0a0646de..4e21383d 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.24.0" -shuttle-runtime = "0.24.0" +shuttle-thruster = "0.25.0" +shuttle-runtime = "0.25.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 2d926101..16056010 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.24.0", features = ["postgres"] } -shuttle-thruster = "0.24.0" -shuttle-runtime = "0.24.0" +shuttle-aws-rds = { version = "0.25.0", features = ["postgres"] } +shuttle-thruster = "0.25.0" +shuttle-runtime = "0.25.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index de955924..6a18db78 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.24.0" -shuttle-runtime = "0.24.0" +shuttle-tide = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index cebdc3cc..a4fbcefe 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.24.0", features = ["postgres"] } -shuttle-runtime = "0.24.0" -shuttle-tide = "0.24.0" +shuttle-aws-rds = { version = "0.25.0", features = ["postgres"] } +shuttle-runtime = "0.25.0" +shuttle-tide = "0.25.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 9c86186b..91221c05 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.24.0" -shuttle-tower = "0.24.0" +shuttle-runtime = "0.25.0" +shuttle-tower = "0.25.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/axum-logs-endpoint/Cargo.toml b/tracing/axum-logs-endpoint/Cargo.toml index eb38ecc6..8138556f 100644 --- a/tracing/axum-logs-endpoint/Cargo.toml +++ b/tracing/axum-logs-endpoint/Cargo.toml @@ -12,6 +12,6 @@ axum = "0.6.19" axum-error = "0.2.0" serde = { version = "1.0.180", features = ["derive"] } serde_json = "1.0.104" -shuttle-runtime = "0.24.0" -shuttle-axum = "0.24.0" +shuttle-runtime = "0.25.0" +shuttle-axum = "0.25.0" lazy_static = "1.4.0" diff --git a/tracing/custom-layer/Cargo.toml b/tracing/custom-layer/Cargo.toml index 25a316b8..41ad2d28 100644 --- a/tracing/custom-layer/Cargo.toml +++ b/tracing/custom-layer/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] lazy_static = "1.4.0" -shuttle-runtime = "0.24.0" +shuttle-runtime = "0.25.0" tracing = "0.1.37" tracing-subscriber = "0.3.17" tokio = "1.28.2" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index aa697d3c..f47a4d7c 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.24.0" -shuttle-warp = "0.24.0" +shuttle-runtime = "0.25.0" +shuttle-warp = "0.25.0" tokio = "1.26.0" warp = "0.3.3" From ac11cb13a39197bb851c657b01dcab7b244e593a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Orhun=20Parmaks=C4=B1z?= Date: Mon, 28 Aug 2023 18:48:04 +0200 Subject: [PATCH 087/239] feat: add shuttle-metadata example (#81) * feat: add shuttle-service-info example * chore: rename service info to metadata * chore: rename metadata types --- README.md | 1 + axum/metadata/Cargo.toml | 11 +++++++++++ axum/metadata/Shuttle.toml | 1 + axum/metadata/src/main.rs | 11 +++++++++++ 4 files changed, 24 insertions(+) create mode 100644 axum/metadata/Cargo.toml create mode 100644 axum/metadata/Shuttle.toml create mode 100644 axum/metadata/src/main.rs diff --git a/README.md b/README.md index 61987aa4..cc1d52a8 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ Actix Web | [hello-world](./actix-web/hello-world/) | Hello World | `cargo shutt Actix Web | [postgres](./actix-web/postgres/) | TODO app with a Postgres DB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/postgres` Actix Web | [websocket-actorless](./actix-web/websocket-actorless/) | Websocket app that checks the status of Shuttle's API | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/websocket-actorless` Axum | [hello-world](./axum/hello-world/) | Hello World | `cargo shuttle init --template axum` +Axum | [metadata](./axum/metadata/) | Simple app that prints the service information such as Shuttle service name | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/metadata` Axum | [static-files](./axum/static-files/) | Hello World page that serves static HTML and JS files | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/static-files` Axum | [static-next-server](./axum/static-next-server/) | SPA server for serving a apps from frameworks such as Next.js | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/static-next-server` Axum | [websocket](./axum/websocket/) | Websocket app that checks the status of Shuttle's API | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/websocket` diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml new file mode 100644 index 00000000..35179831 --- /dev/null +++ b/axum/metadata/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "metadata" +version = "0.1.0" +edition = "2021" + +[dependencies] +axum = "0.6.18" +shuttle-axum = "0.24.0" +shuttle-runtime = "0.24.0" +shuttle-metadata = "0.24.0" +tokio = "1.28.2" diff --git a/axum/metadata/Shuttle.toml b/axum/metadata/Shuttle.toml new file mode 100644 index 00000000..17fcfc4f --- /dev/null +++ b/axum/metadata/Shuttle.toml @@ -0,0 +1 @@ +name = "metadata-axum-app" diff --git a/axum/metadata/src/main.rs b/axum/metadata/src/main.rs new file mode 100644 index 00000000..f619aac4 --- /dev/null +++ b/axum/metadata/src/main.rs @@ -0,0 +1,11 @@ +use axum::{routing::get, Router}; +use shuttle_metadata::Metadata; + +#[shuttle_runtime::main] +async fn axum( + #[shuttle_metadata::ShuttleMetadata] metadata: Metadata, +) -> shuttle_axum::ShuttleAxum { + let router = Router::new().route("/", get(format!("{:?}", metadata))); + + Ok(router.into()) +} From c7a46afa61e6c9d50ed685a39d3389b4f1187528 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Sat, 2 Sep 2023 18:29:34 +0200 Subject: [PATCH 088/239] remove example list entry --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index cc1d52a8..f307ba9c 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,5 @@ FRAMEWORK | [NAME](LINK_TO_REPO) | DESCRIPTION | `cargo shuttle init --from USER **Framework** | **Name & Link** | **Description** | **Command** --------------|-----------------|-------------|---------------- -Axum | [Test](https://github.com/shuttle-hq/shuttle-examples) | A test example A test example A test example | `cargo shuttle init --from / --subfolder ` Axum/Any | [Fullstack Rust](https://github.com/TylerBloom/shuttle-fullstack-rust-example) | A basic project template for fullstack Rust projects | `cargo shuttle init --from TylerBloom/shuttle-fullstack-rust-example` Axum/Yew | [Web App with Yew](https://github.com/sentinel1909/shuttle-template-yew) | A basic project template for a web app using the Yew framework | `cargo shuttle init --from sentinel1909/shuttle-template-yew` | From 84bc10428544d98d8027f93b4767b2192c13cc99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Orhun=20Parmaks=C4=B1z?= Date: Thu, 14 Sep 2023 13:51:59 +0200 Subject: [PATCH 089/239] feat: add custom-tracing-subscriber example (#84) * feat: add custom-tracing-subscriber example * docs: add comments about custom tracing subscriber * chore: move custom tracing subscriber example * docs: update the comments for custom tracing subscriber * refactor: update tracing examples * chore: remove custom tracing layer examples --- README.md | 3 +- tracing/axum-logs-endpoint/Cargo.toml | 17 ---- tracing/axum-logs-endpoint/Shuttle.toml | 1 - tracing/axum-logs-endpoint/src/logger.rs | 48 --------- tracing/axum-logs-endpoint/src/main.rs | 54 ---------- tracing/axum-logs-endpoint/src/state.rs | 21 ---- tracing/custom-layer/Cargo.toml | 11 --- tracing/custom-layer/Shuttle.toml | 1 - tracing/custom-layer/src/main.rs | 98 ------------------- tracing/custom-tracing-subscriber/Cargo.toml | 13 +++ .../custom-tracing-subscriber/Shuttle.toml | 1 + tracing/custom-tracing-subscriber/src/main.rs | 32 ++++++ 12 files changed, 47 insertions(+), 253 deletions(-) delete mode 100644 tracing/axum-logs-endpoint/Cargo.toml delete mode 100644 tracing/axum-logs-endpoint/Shuttle.toml delete mode 100644 tracing/axum-logs-endpoint/src/logger.rs delete mode 100644 tracing/axum-logs-endpoint/src/main.rs delete mode 100644 tracing/axum-logs-endpoint/src/state.rs delete mode 100644 tracing/custom-layer/Cargo.toml delete mode 100644 tracing/custom-layer/Shuttle.toml delete mode 100644 tracing/custom-layer/src/main.rs create mode 100644 tracing/custom-tracing-subscriber/Cargo.toml create mode 100644 tracing/custom-tracing-subscriber/Shuttle.toml create mode 100644 tracing/custom-tracing-subscriber/src/main.rs diff --git a/README.md b/README.md index f307ba9c..83863465 100644 --- a/README.md +++ b/README.md @@ -78,8 +78,7 @@ Thruster | [postgres](./thruster/postgres/) | TODO app with a Postgres DB | `car Tide | [hello-world](./tide/hello-world/) | Hello World | `cargo shuttle init --template tide` Tide | [postgres](./tide/postgres/) | TODO app with a Postgres DB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder tide/postgres` Tower | [hello-world](./tower/hello-world/) | Hello World | `cargo shuttle init --template tower` -Tracing | [custom-layer](./tracing/custom-layer/) | Custom tracing layer | `cargo shuttle init --template --from shuttle-hq/shuttle-examples --subfolder tracing/custom-layer` -Tracing | [axum-logs-endpoint](./tracing/axum-logs-endpoint/) | Expose application logs with Axum | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder tracing/axum-logs-endpoint` +Tracing | [custom-tracing-subscriber](./tracing/custom-tracing-subscriber/) | Hello world with a custom tracing setup | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder tracing/custom-tracing-subscriber` Warp | [hello-world](./warp/hello-world/) | Hello World | `cargo shuttle init --template warp` *Custom Service* | [none](./custom-service/none/) | Empty service - A barebones implementation of Shuttle Service trait that does nothing | `cargo shuttle init --template none` *Custom Service* | [request-scheduler](./custom-service/request-scheduler/) | A custom *Request Scheduler* service | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder custom-service/request-scheduler` diff --git a/tracing/axum-logs-endpoint/Cargo.toml b/tracing/axum-logs-endpoint/Cargo.toml deleted file mode 100644 index 8138556f..00000000 --- a/tracing/axum-logs-endpoint/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "axum-logs-endpoint" -version = "0.1.0" -edition = "2021" - -[dependencies] -tracing = "0.1.37" -tracing-subscriber = { version = "0.3.17", features = ["json"] } -tokio = "1.28.2" - -axum = "0.6.19" -axum-error = "0.2.0" -serde = { version = "1.0.180", features = ["derive"] } -serde_json = "1.0.104" -shuttle-runtime = "0.25.0" -shuttle-axum = "0.25.0" -lazy_static = "1.4.0" diff --git a/tracing/axum-logs-endpoint/Shuttle.toml b/tracing/axum-logs-endpoint/Shuttle.toml deleted file mode 100644 index 6dd40ba9..00000000 --- a/tracing/axum-logs-endpoint/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "axum-logs-endpoint" diff --git a/tracing/axum-logs-endpoint/src/logger.rs b/tracing/axum-logs-endpoint/src/logger.rs deleted file mode 100644 index 76a3b957..00000000 --- a/tracing/axum-logs-endpoint/src/logger.rs +++ /dev/null @@ -1,48 +0,0 @@ -use lazy_static::lazy_static; -use serde_json::Value as JsonValue; -use std::{io, sync::Mutex}; -use tokio::sync::broadcast; -use tracing::metadata::LevelFilter; -use tracing_subscriber::Layer; - -lazy_static! { - pub static ref LOG_CHANNEL: broadcast::Sender = broadcast::channel(64).0; -} - -pub struct Logger { - tx: broadcast::Sender, -} - -impl Logger { - pub fn new() -> Self { - Self { - tx: LOG_CHANNEL.clone(), - } - } - - pub fn make_layer() -> impl Layer { - tracing_subscriber::fmt::layer() - .pretty() - .json() - .with_writer(Mutex::new(Self::new())) - .with_filter(LevelFilter::INFO) - } -} - -impl io::Write for Logger { - fn write(&mut self, buf: &[u8]) -> io::Result { - let Ok(log) = serde_json::from_slice(buf) else { - return Ok(0); - }; - - if let Ok(n) = self.tx.send(log) { - return Ok(n); - } - - Ok(0) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} diff --git a/tracing/axum-logs-endpoint/src/main.rs b/tracing/axum-logs-endpoint/src/main.rs deleted file mode 100644 index 5e9d61a9..00000000 --- a/tracing/axum-logs-endpoint/src/main.rs +++ /dev/null @@ -1,54 +0,0 @@ -use std::{sync::Arc, time::SystemTime}; - -use axum::{ - extract::{Path, State}, - routing::{get, post}, - Json, Router, -}; -use axum_error::Result; -use serde_json::Value as JsonValue; -use shuttle_axum::ShuttleAxum; -use tracing::info; - -mod logger; -use logger::Logger; - -mod state; -use state::AppState; - -#[shuttle_runtime::main(tracing_layer = Logger::make_layer)] -async fn axum_logs() -> ShuttleAxum { - let state = AppState::new(); - let router = Router::new() - .route("/", get(|| async { "Hello, world!" })) - .route("/message/:message", post(send_message)) - .route("/logs/:amount", get(get_logs)) - .with_state(state); - - Ok(router.into()) -} - -// Creates a tracing log with `message` -async fn send_message(Path(message): Path) -> String { - info!(?message, now = ?SystemTime::now()); - message -} - -// Waits for `amount` log lines to arrive in the channel and returns them -async fn get_logs( - Path(amount): Path, - State(state): State>, -) -> Result>> { - let mut rx = state.sub(); - let mut logs = Vec::new(); - - while let Ok(log) = rx.recv().await { - logs.push(log); - - if logs.len() == amount { - break; - } - } - - Ok(Json(logs)) -} diff --git a/tracing/axum-logs-endpoint/src/state.rs b/tracing/axum-logs-endpoint/src/state.rs deleted file mode 100644 index 1d65274e..00000000 --- a/tracing/axum-logs-endpoint/src/state.rs +++ /dev/null @@ -1,21 +0,0 @@ -use crate::logger::LOG_CHANNEL; -use serde_json::Value as JsonValue; -use std::sync::Arc; -use tokio::sync::broadcast; - -#[derive(Debug)] -pub struct AppState { - logs: broadcast::Sender, -} - -impl AppState { - pub fn new() -> Arc { - Arc::new(Self { - logs: LOG_CHANNEL.clone(), - }) - } - - pub fn sub(&self) -> broadcast::Receiver { - self.logs.subscribe() - } -} diff --git a/tracing/custom-layer/Cargo.toml b/tracing/custom-layer/Cargo.toml deleted file mode 100644 index 41ad2d28..00000000 --- a/tracing/custom-layer/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "custom-tracing-layer" -version = "0.1.0" -edition = "2021" - -[dependencies] -lazy_static = "1.4.0" -shuttle-runtime = "0.25.0" -tracing = "0.1.37" -tracing-subscriber = "0.3.17" -tokio = "1.28.2" diff --git a/tracing/custom-layer/Shuttle.toml b/tracing/custom-layer/Shuttle.toml deleted file mode 100644 index 7481d921..00000000 --- a/tracing/custom-layer/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "custom-tracing-layer-example" diff --git a/tracing/custom-layer/src/main.rs b/tracing/custom-layer/src/main.rs deleted file mode 100644 index 3c011ee7..00000000 --- a/tracing/custom-layer/src/main.rs +++ /dev/null @@ -1,98 +0,0 @@ -use lazy_static::lazy_static; -use std::{net::SocketAddr, time::Duration}; -use tokio::sync::broadcast; -use tracing::info; -use tracing_subscriber::fmt::MakeWriter; - -lazy_static! { - /// Global channel for sending logs - pub static ref LOG_CHANNEL: broadcast::Sender = broadcast::channel(64).0; -} - -#[shuttle_runtime::main(tracing_layer = Logger::init)] -async fn init() -> Result { - Ok(MyService::new()) -} - -#[derive(Debug)] -struct MyService { - pub logs: broadcast::Receiver, -} - -impl MyService { - pub fn new() -> Self { - Self { - logs: LOG_CHANNEL.subscribe(), - } - } -} - -#[shuttle_runtime::async_trait] -impl shuttle_runtime::Service for MyService { - async fn bind(mut self, _addr: SocketAddr) -> Result<(), shuttle_runtime::Error> { - // send some messages... - for i in 0..10 { - tokio::spawn(async move { - tokio::time::sleep(Duration::from_secs(i)).await; - info!("Hello from thread #{i}!"); - }); - } - - while let Ok(message) = self.logs.recv().await { - // do something with your logs! - println!("Got a new log!"); - tokio::fs::write(Logger::LOG_FILE, message).await?; - } - - Ok(()) - } -} - -/// Logger struct passed to our custom tracing layer -#[derive(Debug)] -struct Logger { - sender: broadcast::Sender, -} - -// Necessary for [`MakeWriter`] impl -impl std::io::Write for Logger { - fn write(&mut self, buf: &[u8]) -> std::io::Result { - let message = String::from_utf8_lossy(buf); - - if let Err(err) = self.sender.send(message.to_string()) { - eprintln!("Failed to send message: {err:?}"); - return Err(std::io::Error::new(std::io::ErrorKind::Other, err)); - } - - Ok(buf.len()) - } - - fn flush(&mut self) -> std::io::Result<()> { - Ok(()) - } -} - -// Necessary for passing [`Logger`] as a custom writer to [`tracing_subscriber`] -impl MakeWriter<'_> for Logger { - type Writer = Self; - - fn make_writer(&self) -> Self::Writer { - Self { - sender: LOG_CHANNEL.clone(), - } - } -} - -impl Logger { - const LOG_FILE: &str = "/var/log/my-service.log"; - - pub fn init() -> impl tracing_subscriber::Layer { - let logger = Self { - sender: LOG_CHANNEL.clone(), - }; - - tracing_subscriber::fmt::layer() - .without_time() - .with_writer(logger) - } -} diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml new file mode 100644 index 00000000..143a5806 --- /dev/null +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "custom-tracing-subscriber" +version = "0.1.0" +edition = "2021" + +[dependencies] +actix-web = "4.3.1" +shuttle-actix-web = "0.25.0" +# disable default features to disable the Shuttle default tracing subscriber +shuttle-runtime = { version = "0.25.0", default-features = false } +tokio = "1.26.0" +tracing = "0.1.37" +tracing-subscriber = "0.3.17" diff --git a/tracing/custom-tracing-subscriber/Shuttle.toml b/tracing/custom-tracing-subscriber/Shuttle.toml new file mode 100644 index 00000000..e5147946 --- /dev/null +++ b/tracing/custom-tracing-subscriber/Shuttle.toml @@ -0,0 +1 @@ +name = "custom-tracing-subscriber-actix-web-app" diff --git a/tracing/custom-tracing-subscriber/src/main.rs b/tracing/custom-tracing-subscriber/src/main.rs new file mode 100644 index 00000000..b754211e --- /dev/null +++ b/tracing/custom-tracing-subscriber/src/main.rs @@ -0,0 +1,32 @@ +use actix_web::{get, web::ServiceConfig}; +use shuttle_actix_web::ShuttleActixWeb; +use tracing_subscriber::filter::{EnvFilter, LevelFilter}; + +#[tracing::instrument(name = "hello")] +#[get("/")] +async fn hello_world() -> &'static str { + let msg = "Hello World!"; + tracing::info!("{msg}"); + msg +} + +#[shuttle_runtime::main] +async fn actix_web() -> ShuttleActixWeb { + // We need to write to stdout for Shuttle to record our logs, so we use the + // tracing::fmt subscriber which has sane defaults for applications and also + // writes to stdout. + tracing_subscriber::fmt() + .with_env_filter( + EnvFilter::builder() + .with_default_directive(LevelFilter::INFO.into()) + .from_env_lossy(), + ) + .init(); + tracing::info!("tracing is initialized"); + + let config = move |cfg: &mut ServiceConfig| { + cfg.service(hello_world); + }; + + Ok(config.into()) +} From cadded90e0196299c835b39b82ad3929f02b7c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Thu, 14 Sep 2023 13:56:51 +0200 Subject: [PATCH 090/239] chore: v0.26.0 (#85) --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 6 +++--- axum/hello-world/Cargo.toml | 4 ++-- axum/static-files/Cargo.toml | 6 +++--- axum/static-next-server/Cargo.toml | 6 +++--- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 6 +++--- axum/with-state/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 10 +++++----- next/hello-world/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 6 +++--- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 6 +++--- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/postgres/Secrets.toml | 1 + rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 38 files changed, 97 insertions(+), 96 deletions(-) create mode 100644 rocket/postgres/Secrets.toml diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index e1636dc4..fab20daf 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-actix-web = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 730cf7bd..d6c35820 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-actix-web = "0.26.0" +shuttle-runtime = "0.26.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 039dac0d..27e9c085 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,8 +13,8 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-static-folder = "0.25.0" +shuttle-actix-web = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-static-folder = "0.26.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 0b7d5bb7..2aa2e2d8 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-axum = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 07f4afb9..74fd4b18 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-static-folder = "0.25.0" +shuttle-axum = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-static-folder = "0.26.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 5c495af1..f47d7da7 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-static-folder = "0.25.0" +shuttle-axum = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-static-folder = "0.26.0" tokio = "1.26.0" diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 4a9e6193..a9f65c7a 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = { version = "0.6.18" } -shuttle-axum = { version = "0.25.0" } -shuttle-runtime = { version = "0.25.0" } -shuttle-turso = { version = "0.25.0" } +shuttle-axum = { version = "0.26.0" } +shuttle-runtime = { version = "0.26.0" } +shuttle-turso = { version = "0.26.0" } libsql-client = "=0.30.1" tokio = { version = "1.26.0" } serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index dee0b541..4793226f 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,8 +11,8 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-static-folder = "0.25.0" +shuttle-axum = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-static-folder = "0.26.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index c62c3398..399dda2f 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-axum = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index ecdbcd95..8f043a02 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.6.18" serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.25.0" -shuttle-axum = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-service = "0.26.0" +shuttle-axum = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index f7a08045..16647e0a 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.25.0" +shuttle-runtime = "0.26.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index dc2341d9..e0701b84 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -12,6 +12,6 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-persist = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.28.0" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index b83d6491..e086bb62 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,11 +16,11 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-secrets = "0.25.0" -shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } -shuttle-static-folder = "0.25.0" +shuttle-axum = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-secrets = "0.26.0" +shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } +shuttle-static-folder = "0.26.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index 7324dfc2..be82119b 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.25.0" +shuttle-next = "0.26.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 682c91c6..40209f4e 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -11,7 +11,7 @@ path = "src/standalone.rs" [dependencies] axum = "0.6.18" dotenvy = "0.15.7" -shuttle-axum = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-secrets = "0.25.0" +shuttle-axum = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-secrets = "0.26.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index b7a0091b..5b532494 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-poem = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 9df9144d..086ed461 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.25.0" -shuttle-shared-db = { version = "0.25.0", features = ["mongodb"] } -shuttle-runtime = "0.25.0" +shuttle-poem = "0.26.0" +shuttle-shared-db = { version = "0.26.0", features = ["mongodb"] } +shuttle-runtime = "0.26.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index d347f2ca..4d46e401 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } +shuttle-poem = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 4e422723..80e82410 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-secrets = "0.25.0" +shuttle-poise = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-secrets = "0.26.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index 33bba1ba..0e98c325 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-rocket = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 6bd6ad22..a2526322 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-static-folder = "0.25.0" +shuttle-rocket = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-static-folder = "0.26.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 0feca5ba..2aabd383 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-rocket = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 63955297..64a07106 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.25.0" -shuttle-rocket = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-persist = "0.26.0" +shuttle-rocket = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 4f075af2..77345a4a 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } -shuttle-rocket = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } +shuttle-rocket = "0.26.0" +shuttle-runtime = "0.26.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/postgres/Secrets.toml b/rocket/postgres/Secrets.toml new file mode 100644 index 00000000..fd76ede3 --- /dev/null +++ b/rocket/postgres/Secrets.toml @@ -0,0 +1 @@ +PASSWORD = "test" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 8e59fc7c..473ccae1 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-secrets = "0.25.0" +shuttle-rocket = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-secrets = "0.26.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 89ec7d5b..0dda1650 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-rocket = "0.26.0" +shuttle-runtime = "0.26.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 9b3c0c82..cbeb3802 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-rocket = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index d1e53b05..e1903eb6 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-salvo = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 23f4dc9d..92f86803 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-serenity = "0.26.0" +shuttle-runtime = "0.26.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.25.0" +shuttle-secrets = "0.26.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 37a91599..97402e71 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.25.0" -shuttle-serenity = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } +shuttle-secrets = "0.26.0" +shuttle-serenity = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 4e21383d..0d69309d 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-thruster = "0.26.0" +shuttle-runtime = "0.26.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 16056010..7a9e7d3f 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.25.0", features = ["postgres"] } -shuttle-thruster = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-aws-rds = { version = "0.26.0", features = ["postgres"] } +shuttle-thruster = "0.26.0" +shuttle-runtime = "0.26.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 6a18db78..46cc4015 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-tide = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index a4fbcefe..fb46d60d 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.25.0", features = ["postgres"] } -shuttle-runtime = "0.25.0" -shuttle-tide = "0.25.0" +shuttle-aws-rds = { version = "0.26.0", features = ["postgres"] } +shuttle-runtime = "0.26.0" +shuttle-tide = "0.26.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 91221c05..5c5ea5f3 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.25.0" -shuttle-tower = "0.25.0" +shuttle-runtime = "0.26.0" +shuttle-tower = "0.26.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 143a5806..ab38d6c5 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.25.0" +shuttle-actix-web = "0.26.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.25.0", default-features = false } +shuttle-runtime = { version = "0.26.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = "0.3.17" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index f47a4d7c..328cbaa7 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.25.0" -shuttle-warp = "0.25.0" +shuttle-runtime = "0.26.0" +shuttle-warp = "0.26.0" tokio = "1.26.0" warp = "0.3.3" From c781aa63ff4fa0abf40e63ccbc5279261e3ceeba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Thu, 14 Sep 2023 15:03:02 +0200 Subject: [PATCH 091/239] Revert "chore: v0.26.0 (#85)" (#86) This reverts commit cadded90e0196299c835b39b82ad3929f02b7c45. --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 6 +++--- axum/hello-world/Cargo.toml | 4 ++-- axum/static-files/Cargo.toml | 6 +++--- axum/static-next-server/Cargo.toml | 6 +++--- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 6 +++--- axum/with-state/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 10 +++++----- next/hello-world/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 6 +++--- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 6 +++--- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/postgres/Secrets.toml | 1 - rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 38 files changed, 96 insertions(+), 97 deletions(-) delete mode 100644 rocket/postgres/Secrets.toml diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index fab20daf..e1636dc4 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-actix-web = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index d6c35820..730cf7bd 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-actix-web = "0.25.0" +shuttle-runtime = "0.25.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 27e9c085..039dac0d 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,8 +13,8 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-static-folder = "0.26.0" +shuttle-actix-web = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-static-folder = "0.25.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 2aa2e2d8..0b7d5bb7 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-axum = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 74fd4b18..07f4afb9 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-static-folder = "0.26.0" +shuttle-axum = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-static-folder = "0.25.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index f47d7da7..5c495af1 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-static-folder = "0.26.0" +shuttle-axum = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-static-folder = "0.25.0" tokio = "1.26.0" diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index a9f65c7a..4a9e6193 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = { version = "0.6.18" } -shuttle-axum = { version = "0.26.0" } -shuttle-runtime = { version = "0.26.0" } -shuttle-turso = { version = "0.26.0" } +shuttle-axum = { version = "0.25.0" } +shuttle-runtime = { version = "0.25.0" } +shuttle-turso = { version = "0.25.0" } libsql-client = "=0.30.1" tokio = { version = "1.26.0" } serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 4793226f..dee0b541 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,8 +11,8 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-static-folder = "0.26.0" +shuttle-axum = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-static-folder = "0.25.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index 399dda2f..c62c3398 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-axum = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 8f043a02..ecdbcd95 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.6.18" serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.26.0" -shuttle-axum = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-service = "0.25.0" +shuttle-axum = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 16647e0a..f7a08045 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.26.0" +shuttle-runtime = "0.25.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index e0701b84..dc2341d9 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -12,6 +12,6 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-persist = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.28.0" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index e086bb62..b83d6491 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,11 +16,11 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-secrets = "0.26.0" -shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } -shuttle-static-folder = "0.26.0" +shuttle-axum = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-secrets = "0.25.0" +shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } +shuttle-static-folder = "0.25.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index be82119b..7324dfc2 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.26.0" +shuttle-next = "0.25.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 40209f4e..682c91c6 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -11,7 +11,7 @@ path = "src/standalone.rs" [dependencies] axum = "0.6.18" dotenvy = "0.15.7" -shuttle-axum = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-secrets = "0.26.0" +shuttle-axum = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-secrets = "0.25.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 5b532494..b7a0091b 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-poem = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 086ed461..9df9144d 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.26.0" -shuttle-shared-db = { version = "0.26.0", features = ["mongodb"] } -shuttle-runtime = "0.26.0" +shuttle-poem = "0.25.0" +shuttle-shared-db = { version = "0.25.0", features = ["mongodb"] } +shuttle-runtime = "0.25.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 4d46e401..d347f2ca 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } +shuttle-poem = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 80e82410..4e422723 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-secrets = "0.26.0" +shuttle-poise = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-secrets = "0.25.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index 0e98c325..33bba1ba 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-rocket = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index a2526322..6bd6ad22 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-static-folder = "0.26.0" +shuttle-rocket = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-static-folder = "0.25.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 2aabd383..0feca5ba 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-rocket = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 64a07106..63955297 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.26.0" -shuttle-rocket = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-persist = "0.25.0" +shuttle-rocket = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 77345a4a..4f075af2 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } -shuttle-rocket = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } +shuttle-rocket = "0.25.0" +shuttle-runtime = "0.25.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/postgres/Secrets.toml b/rocket/postgres/Secrets.toml deleted file mode 100644 index fd76ede3..00000000 --- a/rocket/postgres/Secrets.toml +++ /dev/null @@ -1 +0,0 @@ -PASSWORD = "test" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 473ccae1..8e59fc7c 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-secrets = "0.26.0" +shuttle-rocket = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-secrets = "0.25.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 0dda1650..89ec7d5b 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-rocket = "0.25.0" +shuttle-runtime = "0.25.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index cbeb3802..9b3c0c82 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-rocket = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index e1903eb6..d1e53b05 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-salvo = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 92f86803..23f4dc9d 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-serenity = "0.25.0" +shuttle-runtime = "0.25.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.26.0" +shuttle-secrets = "0.25.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 97402e71..37a91599 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.26.0" -shuttle-serenity = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } +shuttle-secrets = "0.25.0" +shuttle-serenity = "0.25.0" +shuttle-runtime = "0.25.0" +shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 0d69309d..4e21383d 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-thruster = "0.25.0" +shuttle-runtime = "0.25.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 7a9e7d3f..16056010 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.26.0", features = ["postgres"] } -shuttle-thruster = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-aws-rds = { version = "0.25.0", features = ["postgres"] } +shuttle-thruster = "0.25.0" +shuttle-runtime = "0.25.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 46cc4015..6a18db78 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-tide = "0.25.0" +shuttle-runtime = "0.25.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index fb46d60d..a4fbcefe 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.26.0", features = ["postgres"] } -shuttle-runtime = "0.26.0" -shuttle-tide = "0.26.0" +shuttle-aws-rds = { version = "0.25.0", features = ["postgres"] } +shuttle-runtime = "0.25.0" +shuttle-tide = "0.25.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 5c5ea5f3..91221c05 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.26.0" -shuttle-tower = "0.26.0" +shuttle-runtime = "0.25.0" +shuttle-tower = "0.25.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index ab38d6c5..143a5806 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.26.0" +shuttle-actix-web = "0.25.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.26.0", default-features = false } +shuttle-runtime = { version = "0.25.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = "0.3.17" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 328cbaa7..f47a4d7c 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.26.0" -shuttle-warp = "0.26.0" +shuttle-runtime = "0.25.0" +shuttle-warp = "0.25.0" tokio = "1.26.0" warp = "0.3.3" From 4a6c33d70e470f5e96dc094a867fec575a39799f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Mon, 18 Sep 2023 09:12:32 +0200 Subject: [PATCH 092/239] Revert "Revert "chore: v0.26.0 (#85)" (#86)" (#87) This reverts commit c781aa63ff4fa0abf40e63ccbc5279261e3ceeba. --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 6 +++--- axum/hello-world/Cargo.toml | 4 ++-- axum/static-files/Cargo.toml | 6 +++--- axum/static-next-server/Cargo.toml | 6 +++--- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 6 +++--- axum/with-state/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 10 +++++----- next/hello-world/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 6 +++--- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 6 +++--- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/postgres/Secrets.toml | 1 + rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 38 files changed, 97 insertions(+), 96 deletions(-) create mode 100644 rocket/postgres/Secrets.toml diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index e1636dc4..fab20daf 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-actix-web = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 730cf7bd..d6c35820 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-actix-web = "0.26.0" +shuttle-runtime = "0.26.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 039dac0d..27e9c085 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,8 +13,8 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-static-folder = "0.25.0" +shuttle-actix-web = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-static-folder = "0.26.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 0b7d5bb7..2aa2e2d8 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-axum = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 07f4afb9..74fd4b18 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-static-folder = "0.25.0" +shuttle-axum = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-static-folder = "0.26.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 5c495af1..f47d7da7 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-static-folder = "0.25.0" +shuttle-axum = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-static-folder = "0.26.0" tokio = "1.26.0" diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 4a9e6193..a9f65c7a 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = { version = "0.6.18" } -shuttle-axum = { version = "0.25.0" } -shuttle-runtime = { version = "0.25.0" } -shuttle-turso = { version = "0.25.0" } +shuttle-axum = { version = "0.26.0" } +shuttle-runtime = { version = "0.26.0" } +shuttle-turso = { version = "0.26.0" } libsql-client = "=0.30.1" tokio = { version = "1.26.0" } serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index dee0b541..4793226f 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,8 +11,8 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-static-folder = "0.25.0" +shuttle-axum = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-static-folder = "0.26.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index c62c3398..399dda2f 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-axum = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index ecdbcd95..8f043a02 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.6.18" serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.25.0" -shuttle-axum = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-service = "0.26.0" +shuttle-axum = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index f7a08045..16647e0a 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.25.0" +shuttle-runtime = "0.26.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index dc2341d9..e0701b84 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -12,6 +12,6 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-persist = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.28.0" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index b83d6491..e086bb62 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,11 +16,11 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-secrets = "0.25.0" -shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } -shuttle-static-folder = "0.25.0" +shuttle-axum = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-secrets = "0.26.0" +shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } +shuttle-static-folder = "0.26.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index 7324dfc2..be82119b 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.25.0" +shuttle-next = "0.26.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 682c91c6..40209f4e 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -11,7 +11,7 @@ path = "src/standalone.rs" [dependencies] axum = "0.6.18" dotenvy = "0.15.7" -shuttle-axum = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-secrets = "0.25.0" +shuttle-axum = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-secrets = "0.26.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index b7a0091b..5b532494 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-poem = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 9df9144d..086ed461 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.25.0" -shuttle-shared-db = { version = "0.25.0", features = ["mongodb"] } -shuttle-runtime = "0.25.0" +shuttle-poem = "0.26.0" +shuttle-shared-db = { version = "0.26.0", features = ["mongodb"] } +shuttle-runtime = "0.26.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index d347f2ca..4d46e401 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } +shuttle-poem = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 4e422723..80e82410 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-secrets = "0.25.0" +shuttle-poise = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-secrets = "0.26.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index 33bba1ba..0e98c325 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-rocket = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 6bd6ad22..a2526322 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-static-folder = "0.25.0" +shuttle-rocket = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-static-folder = "0.26.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 0feca5ba..2aabd383 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-rocket = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 63955297..64a07106 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.25.0" -shuttle-rocket = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-persist = "0.26.0" +shuttle-rocket = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 4f075af2..77345a4a 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } -shuttle-rocket = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } +shuttle-rocket = "0.26.0" +shuttle-runtime = "0.26.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/postgres/Secrets.toml b/rocket/postgres/Secrets.toml new file mode 100644 index 00000000..fd76ede3 --- /dev/null +++ b/rocket/postgres/Secrets.toml @@ -0,0 +1 @@ +PASSWORD = "test" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 8e59fc7c..473ccae1 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-secrets = "0.25.0" +shuttle-rocket = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-secrets = "0.26.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 89ec7d5b..0dda1650 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-rocket = "0.26.0" +shuttle-runtime = "0.26.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 9b3c0c82..cbeb3802 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-rocket = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index d1e53b05..e1903eb6 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-salvo = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 23f4dc9d..92f86803 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-serenity = "0.26.0" +shuttle-runtime = "0.26.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.25.0" +shuttle-secrets = "0.26.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 37a91599..97402e71 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.25.0" -shuttle-serenity = "0.25.0" -shuttle-runtime = "0.25.0" -shuttle-shared-db = { version = "0.25.0", features = ["postgres"] } +shuttle-secrets = "0.26.0" +shuttle-serenity = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 4e21383d..0d69309d 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-thruster = "0.26.0" +shuttle-runtime = "0.26.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 16056010..7a9e7d3f 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.25.0", features = ["postgres"] } -shuttle-thruster = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-aws-rds = { version = "0.26.0", features = ["postgres"] } +shuttle-thruster = "0.26.0" +shuttle-runtime = "0.26.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 6a18db78..46cc4015 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.25.0" -shuttle-runtime = "0.25.0" +shuttle-tide = "0.26.0" +shuttle-runtime = "0.26.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index a4fbcefe..fb46d60d 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.25.0", features = ["postgres"] } -shuttle-runtime = "0.25.0" -shuttle-tide = "0.25.0" +shuttle-aws-rds = { version = "0.26.0", features = ["postgres"] } +shuttle-runtime = "0.26.0" +shuttle-tide = "0.26.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 91221c05..5c5ea5f3 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.25.0" -shuttle-tower = "0.25.0" +shuttle-runtime = "0.26.0" +shuttle-tower = "0.26.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 143a5806..ab38d6c5 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.25.0" +shuttle-actix-web = "0.26.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.25.0", default-features = false } +shuttle-runtime = { version = "0.26.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = "0.3.17" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index f47a4d7c..328cbaa7 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.25.0" -shuttle-warp = "0.25.0" +shuttle-runtime = "0.26.0" +shuttle-warp = "0.26.0" tokio = "1.26.0" warp = "0.3.3" From 1e627598ff5205905b429cb3880b894de4eeda03 Mon Sep 17 00:00:00 2001 From: Vardhan Patil Date: Thu, 21 Sep 2023 00:19:59 +0530 Subject: [PATCH 093/239] ci: Create github action that runs `cargo clippy` and `cargo fmt` (#40) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ci: Create ci.sh, run fmt and clippy fix Run `cargo clippy --fix` and `cargo fmt` on all directories so that less crates fail the ci. Currently, the next/hello-world crate fails cargo clippy, because cargo-clippy assumes the arch to be the same as the device running it, while shuttle-next assumes that it is being run on wasi. This commit doesn't include the actual action yml file, which will get added in the next commit * ci: Create a github actions workflow that runs ci.sh This workflow will run the ci.sh script that was created in the last commit. * ci: Create a github actions workflow that runs ci.sh This workflow will run the ci.sh script that was created in the last commit. * ci: Fix the rust.yml workflow I ended up creating a bunch of accidental "merge tag" commits because git is hard Run ./ci.sh directly instead of using `sh -x` * Install protoc in ci so that the build doesn't fail * Remove protoc from the github action * re add protoc * Change /bin/bash to /usr/bin/env bash for compatibility reasons Co-authored-by: Orhun Parmaksız * Update .github/workflows/rust.yml Co-authored-by: Orhun Parmaksız * Pass manifest path as an argument instead of pushd * Rename rust.yml to ci.yml * Fix incorrect formatting causing ci to fail * Add wasm32-wasi * Add target file * disable ci for failing crates * Fix formatting errors * fix ci.sh not running clippy * clippy * add sccache * fix path * bump metadata example * fix warnings, simplify * split job in half to not run out of storage * try with less cores * shared target dir * fix request scheduler --------- Co-authored-by: Orhun Parmaksız Co-authored-by: jonaro00 <54029719+jonaro00@users.noreply.github.com> --- .github/workflows/ci.yml | 66 +++++++++++++++++++ actix-web/hello-world/src/main.rs | 3 +- actix-web/postgres/src/main.rs | 2 +- actix-web/websocket-actorless/src/main.rs | 7 +- axum/metadata/Cargo.toml | 6 +- axum/static-next-server/src/main.rs | 3 +- ci.sh | 29 ++++++++ custom-service/request-scheduler/Cargo.toml | 1 + custom-service/request-scheduler/src/lib.rs | 33 +--------- .../request-scheduler/src/router.rs | 2 +- fullstack-templates/saas/backend/src/auth.rs | 8 ++- fullstack-templates/saas/backend/src/main.rs | 8 ++- .../saas/backend/src/payments.rs | 2 +- next/hello-world/.target | 1 + poem/mongodb/src/main.rs | 4 +- poem/postgres/src/main.rs | 6 +- poise/hello-world/src/main.rs | 2 +- rocket/persist/src/main.rs | 2 +- rocket/workspace/Cargo.toml | 2 +- thruster/hello-world/src/main.rs | 2 +- thruster/postgres/src/main.rs | 2 +- tide/postgres/src/main.rs | 2 +- 22 files changed, 130 insertions(+), 63 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100755 ci.sh create mode 100644 next/hello-world/.target diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..42511e53 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,66 @@ +name: CI + +on: + push: + branches: [ "main", "develop" ] + pull_request: + branches: [ "main", "develop" ] + workflow_dispatch: + +env: + CARGO_TERM_COLOR: always + +jobs: + fmt-clippy-a-p: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Install wasm32-wasi target + run: rustup target add wasm32-wasi + + - name: Install sccache + run: | + SCCACHE_VERSION='v0.5.4' + curl -L https://github.com/mozilla/sccache/releases/download/$SCCACHE_VERSION/sccache-$SCCACHE_VERSION-x86_64-unknown-linux-musl.tar.gz \ + | tar -xOz sccache-$SCCACHE_VERSION-x86_64-unknown-linux-musl/sccache \ + > /home/runner/.cargo/bin/sccache \ + && chmod +x /home/runner/.cargo/bin/sccache + + - name: Check formatting and Clippy + shell: bash + run: ./ci.sh a q + env: + RUSTC_WRAPPER: /home/runner/.cargo/bin/sccache + CARGO_TARGET_DIR: /tmp/target + + - name: Show sccache stats + run: /home/runner/.cargo/bin/sccache --show-stats + + fmt-clippy-q-z: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Install wasm32-wasi target + run: rustup target add wasm32-wasi + + - name: Install sccache + run: | + SCCACHE_VERSION='v0.5.4' + curl -L https://github.com/mozilla/sccache/releases/download/$SCCACHE_VERSION/sccache-$SCCACHE_VERSION-x86_64-unknown-linux-musl.tar.gz \ + | tar -xOz sccache-$SCCACHE_VERSION-x86_64-unknown-linux-musl/sccache \ + > /home/runner/.cargo/bin/sccache \ + && chmod +x /home/runner/.cargo/bin/sccache + + - name: Check formatting and Clippy + shell: bash + run: ./ci.sh q zzz + env: + RUSTC_WRAPPER: /home/runner/.cargo/bin/sccache + CARGO_TARGET_DIR: /tmp/target + + - name: Show sccache stats + run: /home/runner/.cargo/bin/sccache --show-stats diff --git a/actix-web/hello-world/src/main.rs b/actix-web/hello-world/src/main.rs index c0c2f056..285e3709 100644 --- a/actix-web/hello-world/src/main.rs +++ b/actix-web/hello-world/src/main.rs @@ -7,8 +7,7 @@ async fn hello_world() -> &'static str { } #[shuttle_runtime::main] -async fn actix_web( -) -> ShuttleActixWeb { +async fn actix_web() -> ShuttleActixWeb { let config = move |cfg: &mut ServiceConfig| { cfg.service(hello_world); }; diff --git a/actix-web/postgres/src/main.rs b/actix-web/postgres/src/main.rs index c6b018d1..df3163d4 100644 --- a/actix-web/postgres/src/main.rs +++ b/actix-web/postgres/src/main.rs @@ -6,7 +6,7 @@ use actix_web::{ }; use serde::{Deserialize, Serialize}; use shuttle_actix_web::ShuttleActixWeb; -use shuttle_runtime::{CustomError}; +use shuttle_runtime::CustomError; use sqlx::{Executor, FromRow, PgPool}; #[get("/{id}")] diff --git a/actix-web/websocket-actorless/src/main.rs b/actix-web/websocket-actorless/src/main.rs index 459b6870..1b5ca52e 100644 --- a/actix-web/websocket-actorless/src/main.rs +++ b/actix-web/websocket-actorless/src/main.rs @@ -101,12 +101,11 @@ async fn websocket( async fn index() -> impl Responder { NamedFile::open_async("./static/index.html") .await - .map_err(|e| actix_web::error::ErrorInternalServerError(e)) + .map_err(actix_web::error::ErrorInternalServerError) } #[shuttle_runtime::main] -async fn actix_web( -) -> ShuttleActixWeb { +async fn actix_web() -> ShuttleActixWeb { // We're going to use channels to communicate between threads. // api state channel let (tx_api_state, rx_api_state) = watch::channel(ApiStateMessage::default()); @@ -168,7 +167,7 @@ async fn actix_web( if let Err(e) = shared_tx_api_state2.send(ApiStateMessage { client_count, - origin: format!("ws_update"), + origin: "ws_update".to_string(), date_time: Utc::now(), is_up, }) { diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index 35179831..55d82893 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.24.0" -shuttle-runtime = "0.24.0" -shuttle-metadata = "0.24.0" +shuttle-axum = "0.26.0" +shuttle-runtime = "0.26.0" +shuttle-metadata = "0.26.0" tokio = "1.28.2" diff --git a/axum/static-next-server/src/main.rs b/axum/static-next-server/src/main.rs index 6ce5e935..a13132ed 100644 --- a/axum/static-next-server/src/main.rs +++ b/axum/static-next-server/src/main.rs @@ -7,8 +7,7 @@ use axum_extra::routing::SpaRouter; async fn axum( #[shuttle_static_folder::StaticFolder] static_folder: PathBuf, ) -> shuttle_axum::ShuttleAxum { - let router = - Router::new().merge(SpaRouter::new("/", static_folder).index_file("index.html")); + let router = Router::new().merge(SpaRouter::new("/", static_folder).index_file("index.html")); Ok(router.into()) } diff --git a/ci.sh b/ci.sh new file mode 100755 index 00000000..469cc1f9 --- /dev/null +++ b/ci.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +set -euo pipefail +IFS=$'\n\t' + +# Get all directories with Cargo.toml files, alphabetically between $1 and $2 +FROM="./$1" +TO="./$2" +DIRS=$(find . -name Cargo.toml -exec dirname {} \; | sort | awk -v from="$FROM" -v to="$TO" '($0 >= from) && ($0 < to) {print $0}') + +# Loop through each directory and run cargo fmt and cargo clippy, exit on failure +for dir in $DIRS; do + if [ -f "$dir/.disable_ci" ]; then + echo "Skipping $dir" + continue + fi + + echo "Checking $dir" + + if [ -f "$dir/.target" ]; then + target=$(<$dir/.target) + + cargo fmt --all --manifest-path "$dir/Cargo.toml" -- --check + cargo clippy --no-deps --target $target --manifest-path "$dir/Cargo.toml" -- -D warnings + else + cargo fmt --all --manifest-path "$dir/Cargo.toml" -- --check + cargo clippy --no-deps --manifest-path "$dir/Cargo.toml" -- -D warnings + fi +done diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index e0701b84..0712a522 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -15,3 +15,4 @@ serde = "1.0.163" shuttle-persist = "0.26.0" shuttle-runtime = "0.26.0" tokio = "1.28.0" +tracing = "0.1.37" diff --git a/custom-service/request-scheduler/src/lib.rs b/custom-service/request-scheduler/src/lib.rs index 19a66afc..ff938ca8 100644 --- a/custom-service/request-scheduler/src/lib.rs +++ b/custom-service/request-scheduler/src/lib.rs @@ -1,34 +1,3 @@ -//! Shuttle service integration for cron. -//! -//! ## Example -//! Create a new `CrontabService` by providing a `shuttle_persist::PersistInstance` -//! and an `axum::Router` -//! -//! ```rust,no_run -//! use shuttle_crontab::{CrontabService, ShuttleCrontab}; -//! use shuttle_persist::{Persist, PersistInstance}; -//! -//! #[shuttle_runtime::main] -//! async fn crontab(#[Persist] persist: PersistInstance) -> ShuttleCrontab { -//! let router = Router::new().route("/trigger-me", get(|| async { -//! "Triggered by the crontab service".to_string() -//! })); -//! CrontabService::new(persist, router) -//! } -//! ``` -//! -//! This will create an `axum::Service` with a cron runner mounted at `/crontab`. -//! The `/crontab/set` endpoint accepts a schedule and a URL as form data and -//! persists the cron job with `shuttle_persist` between runs. -//! -//! Call the endpoint with something like the following to set up a -//! -//!``` -//!curl -v http://localhost:8000/crontab/set\ -//! -H "Content-Type: application/x-www-form-urlencoded"\ -//! -d "schedule='*/2 * * * * *'&url='http://localhost:8000/trigger-me'" -//!``` -//! use std::str::FromStr; use std::sync::Arc; @@ -38,12 +7,12 @@ use cron::Schedule; use router::make_router; use serde::{Deserialize, Serialize}; use shuttle_persist::PersistInstance; -use shuttle_runtime::tracing::{debug, info}; use tokio::{ sync::mpsc::{self, Receiver, Sender}, sync::oneshot, time::sleep, }; +use tracing::{debug, info}; mod error; use error::CrontabServiceError; diff --git a/custom-service/request-scheduler/src/router.rs b/custom-service/request-scheduler/src/router.rs index 6b7e1afe..d0ff2b11 100644 --- a/custom-service/request-scheduler/src/router.rs +++ b/custom-service/request-scheduler/src/router.rs @@ -4,8 +4,8 @@ use axum::extract::State; use axum::response::IntoResponse; use axum::routing::post; use axum::{extract::Form, Router}; -use shuttle_runtime::tracing::debug; use tokio::sync::oneshot; +use tracing::debug; use crate::error::CrontabServiceError; use crate::{CrontabServiceState, Msg, RawJob}; diff --git a/fullstack-templates/saas/backend/src/auth.rs b/fullstack-templates/saas/backend/src/auth.rs index 231fc82d..69c8bd42 100644 --- a/fullstack-templates/saas/backend/src/auth.rs +++ b/fullstack-templates/saas/backend/src/auth.rs @@ -90,7 +90,7 @@ pub async fn logout( jar: PrivateCookieJar, ) -> Result { let Some(cookie) = jar.get("sessionid").map(|cookie| cookie.value().to_owned()) else { - return Ok(jar) + return Ok(jar); }; let query = sqlx::query("DELETE FROM sessions WHERE session_id = $1") @@ -110,9 +110,11 @@ pub async fn validate_session( next: Next, ) -> (PrivateCookieJar, Response) { let Some(cookie) = jar.get("foo").map(|cookie| cookie.value().to_owned()) else { - println!("Couldn't find a cookie in the jar"); - return (jar,(StatusCode::FORBIDDEN, "Forbidden!".to_string()).into_response()) + return ( + jar, + (StatusCode::FORBIDDEN, "Forbidden!".to_string()).into_response(), + ); }; let find_session = diff --git a/fullstack-templates/saas/backend/src/main.rs b/fullstack-templates/saas/backend/src/main.rs index 3d4b22d3..0ec3e276 100644 --- a/fullstack-templates/saas/backend/src/main.rs +++ b/fullstack-templates/saas/backend/src/main.rs @@ -97,5 +97,11 @@ fn grab_secrets(secrets: shuttle_secrets::SecretStore) -> (String, String, Strin .get("DOMAIN_URL") .unwrap_or_else(|| "None".to_string()); - (stripe_key, stripe_sub_price, mailgun_key, mailgun_url, domain) + ( + stripe_key, + stripe_sub_price, + mailgun_key, + mailgun_url, + domain, + ) } diff --git a/fullstack-templates/saas/backend/src/payments.rs b/fullstack-templates/saas/backend/src/payments.rs index ec5de90d..19f60251 100644 --- a/fullstack-templates/saas/backend/src/payments.rs +++ b/fullstack-templates/saas/backend/src/payments.rs @@ -78,7 +78,7 @@ pub async fn create_checkout( params.default_payment_method = Some(&payment_method.id); let Ok(_) = Subscription::create(&ctx, params).await else { - return Err(StatusCode::INTERNAL_SERVER_ERROR) + return Err(StatusCode::INTERNAL_SERVER_ERROR); }; Ok(StatusCode::OK) diff --git a/next/hello-world/.target b/next/hello-world/.target new file mode 100644 index 00000000..caff62a7 --- /dev/null +++ b/next/hello-world/.target @@ -0,0 +1 @@ +wasm32-wasi \ No newline at end of file diff --git a/poem/mongodb/src/main.rs b/poem/mongodb/src/main.rs index 82b754cb..2c4af642 100644 --- a/poem/mongodb/src/main.rs +++ b/poem/mongodb/src/main.rs @@ -55,9 +55,7 @@ async fn add(Json(todo): Json, collection: Data<&Collection>) -> Res } #[shuttle_runtime::main] -async fn poem( - #[shuttle_shared_db::MongoDb] db: Database, -) -> ShuttlePoem { +async fn poem(#[shuttle_shared_db::MongoDb] db: Database) -> ShuttlePoem { let collection = db.collection::("todos"); let app = Route::new() diff --git a/poem/postgres/src/main.rs b/poem/postgres/src/main.rs index bd4986b4..ccd3b446 100644 --- a/poem/postgres/src/main.rs +++ b/poem/postgres/src/main.rs @@ -7,8 +7,8 @@ use poem::{ EndpointExt, Result, Route, }; use serde::{Deserialize, Serialize}; -use shuttle_runtime::CustomError; use shuttle_poem::ShuttlePoem; +use shuttle_runtime::CustomError; use sqlx::{Executor, FromRow, PgPool}; #[handler] @@ -34,9 +34,7 @@ async fn add(Json(data): Json, state: Data<&PgPool>) -> Result ShuttlePoem { +async fn poem(#[shuttle_shared_db::Postgres] pool: PgPool) -> ShuttlePoem { pool.execute(include_str!("../schema.sql")) .await .map_err(CustomError::new)?; diff --git a/poise/hello-world/src/main.rs b/poise/hello-world/src/main.rs index ef3a302a..1219db60 100644 --- a/poise/hello-world/src/main.rs +++ b/poise/hello-world/src/main.rs @@ -1,7 +1,7 @@ use anyhow::Context as _; use poise::serenity_prelude as serenity; -use shuttle_secrets::SecretStore; use shuttle_poise::ShuttlePoise; +use shuttle_secrets::SecretStore; struct Data {} // User data, which is stored and accessible in all command invocations type Error = Box; diff --git a/rocket/persist/src/main.rs b/rocket/persist/src/main.rs index 2e7d2a7d..52befd69 100644 --- a/rocket/persist/src/main.rs +++ b/rocket/persist/src/main.rs @@ -28,7 +28,7 @@ async fn add( // Change data Json to Weather let weather: Weather = data.into_inner(); - let _state = state + state .persist .save::( format!("weather_{}", &weather.date.as_str()).as_str(), diff --git a/rocket/workspace/Cargo.toml b/rocket/workspace/Cargo.toml index 9bca4b63..fb1eebfc 100644 --- a/rocket/workspace/Cargo.toml +++ b/rocket/workspace/Cargo.toml @@ -1,5 +1,5 @@ [workspace] - +resolver = "2" members = [ "hello-world", "shared", diff --git a/thruster/hello-world/src/main.rs b/thruster/hello-world/src/main.rs index 6abe5adc..a05ff16f 100644 --- a/thruster/hello-world/src/main.rs +++ b/thruster/hello-world/src/main.rs @@ -14,6 +14,6 @@ async fn thruster() -> shuttle_thruster::ShuttleThruster> { let server = HyperServer::new( App::::create(generate_context, ()).get("/", m![hello]), ); - + Ok(server.into()) } diff --git a/thruster/postgres/src/main.rs b/thruster/postgres/src/main.rs index 73981e64..dc553102 100644 --- a/thruster/postgres/src/main.rs +++ b/thruster/postgres/src/main.rs @@ -109,6 +109,6 @@ async fn thruster( .post("/todos", m![add]) .get("/todos/:id", m![retrieve]), ); - + Ok(server.into()) } diff --git a/tide/postgres/src/main.rs b/tide/postgres/src/main.rs index f405646b..1513d849 100644 --- a/tide/postgres/src/main.rs +++ b/tide/postgres/src/main.rs @@ -1,5 +1,5 @@ use serde::{Deserialize, Serialize}; -use shuttle_runtime::{CustomError}; +use shuttle_runtime::CustomError; use shuttle_tide::ShuttleTide; use sqlx::{Executor, FromRow, PgPool}; use tide::{Body, Request}; From 8ff7ff06343f0e1ff82f1b92835e71d48f01a356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Thu, 21 Sep 2023 10:52:37 +0200 Subject: [PATCH 094/239] chore: v0.27.0 (#89) --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 6 +++--- axum/hello-world/Cargo.toml | 4 ++-- axum/static-files/Cargo.toml | 6 +++--- axum/static-next-server/Cargo.toml | 6 +++--- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 6 +++--- axum/with-state/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 10 +++++----- next/hello-world/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 6 +++--- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 6 +++--- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 37 files changed, 96 insertions(+), 96 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index fab20daf..6405ed7b 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-actix-web = "0.27.0" +shuttle-runtime = "0.27.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index d6c35820..f75f2343 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-actix-web = "0.27.0" +shuttle-runtime = "0.27.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.27.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 27e9c085..f474f793 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,8 +13,8 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-static-folder = "0.26.0" +shuttle-actix-web = "0.27.0" +shuttle-runtime = "0.27.0" +shuttle-static-folder = "0.27.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 2aa2e2d8..91235e0b 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-axum = "0.27.0" +shuttle-runtime = "0.27.0" tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 74fd4b18..e9518d8d 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-static-folder = "0.26.0" +shuttle-axum = "0.27.0" +shuttle-runtime = "0.27.0" +shuttle-static-folder = "0.27.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index f47d7da7..3b40f117 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-static-folder = "0.26.0" +shuttle-axum = "0.27.0" +shuttle-runtime = "0.27.0" +shuttle-static-folder = "0.27.0" tokio = "1.26.0" diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index a9f65c7a..6c8adc5f 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = { version = "0.6.18" } -shuttle-axum = { version = "0.26.0" } -shuttle-runtime = { version = "0.26.0" } -shuttle-turso = { version = "0.26.0" } +shuttle-axum = { version = "0.27.0" } +shuttle-runtime = { version = "0.27.0" } +shuttle-turso = { version = "0.27.0" } libsql-client = "=0.30.1" tokio = { version = "1.26.0" } serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 4793226f..60ae5696 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,8 +11,8 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-static-folder = "0.26.0" +shuttle-axum = "0.27.0" +shuttle-runtime = "0.27.0" +shuttle-static-folder = "0.27.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index 399dda2f..897ad985 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-axum = "0.27.0" +shuttle-runtime = "0.27.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 8f043a02..c0f8e674 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.6.18" serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.26.0" -shuttle-axum = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-service = "0.27.0" +shuttle-axum = "0.27.0" +shuttle-runtime = "0.27.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 16647e0a..908cce0b 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.26.0" +shuttle-runtime = "0.27.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index e0701b84..b4831456 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -12,6 +12,6 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-persist = "0.27.0" +shuttle-runtime = "0.27.0" tokio = "1.28.0" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index e086bb62..80d7dc77 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,11 +16,11 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-secrets = "0.26.0" -shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } -shuttle-static-folder = "0.26.0" +shuttle-axum = "0.27.0" +shuttle-runtime = "0.27.0" +shuttle-secrets = "0.27.0" +shuttle-shared-db = { version = "0.27.0", features = ["postgres"] } +shuttle-static-folder = "0.27.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index be82119b..28b6bdf3 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.26.0" +shuttle-next = "0.27.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 40209f4e..31424009 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -11,7 +11,7 @@ path = "src/standalone.rs" [dependencies] axum = "0.6.18" dotenvy = "0.15.7" -shuttle-axum = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-secrets = "0.26.0" +shuttle-axum = "0.27.0" +shuttle-runtime = "0.27.0" +shuttle-secrets = "0.27.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 5b532494..cefe73fd 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-poem = "0.27.0" +shuttle-runtime = "0.27.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 086ed461..4c9d2d64 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.26.0" -shuttle-shared-db = { version = "0.26.0", features = ["mongodb"] } -shuttle-runtime = "0.26.0" +shuttle-poem = "0.27.0" +shuttle-shared-db = { version = "0.27.0", features = ["mongodb"] } +shuttle-runtime = "0.27.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 4d46e401..7de1045b 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } +shuttle-poem = "0.27.0" +shuttle-runtime = "0.27.0" +shuttle-shared-db = { version = "0.27.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 80e82410..c9c1e57c 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-secrets = "0.26.0" +shuttle-poise = "0.27.0" +shuttle-runtime = "0.27.0" +shuttle-secrets = "0.27.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index 0e98c325..4ac833c5 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-rocket = "0.27.0" +shuttle-runtime = "0.27.0" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index a2526322..7b6f7999 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-static-folder = "0.26.0" +shuttle-rocket = "0.27.0" +shuttle-runtime = "0.27.0" +shuttle-static-folder = "0.27.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 2aabd383..a1e3477e 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-rocket = "0.27.0" +shuttle-runtime = "0.27.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 64a07106..bdb75573 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.26.0" -shuttle-rocket = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-persist = "0.27.0" +shuttle-rocket = "0.27.0" +shuttle-runtime = "0.27.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 77345a4a..081c2c7c 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } -shuttle-rocket = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-shared-db = { version = "0.27.0", features = ["postgres"] } +shuttle-rocket = "0.27.0" +shuttle-runtime = "0.27.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 473ccae1..86867b2a 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-secrets = "0.26.0" +shuttle-rocket = "0.27.0" +shuttle-runtime = "0.27.0" +shuttle-secrets = "0.27.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 0dda1650..cab982ba 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-rocket = "0.27.0" +shuttle-runtime = "0.27.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.27.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index cbeb3802..ac7aa6c1 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-rocket = "0.27.0" +shuttle-runtime = "0.27.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index e1903eb6..8d1e31e2 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-salvo = "0.27.0" +shuttle-runtime = "0.27.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 92f86803..0d90d2be 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-serenity = "0.27.0" +shuttle-runtime = "0.27.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.26.0" +shuttle-secrets = "0.27.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 97402e71..84a69569 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.26.0" -shuttle-serenity = "0.26.0" -shuttle-runtime = "0.26.0" -shuttle-shared-db = { version = "0.26.0", features = ["postgres"] } +shuttle-secrets = "0.27.0" +shuttle-serenity = "0.27.0" +shuttle-runtime = "0.27.0" +shuttle-shared-db = { version = "0.27.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 0d69309d..2a417017 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-thruster = "0.27.0" +shuttle-runtime = "0.27.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 7a9e7d3f..d0ee56e8 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.26.0", features = ["postgres"] } -shuttle-thruster = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-aws-rds = { version = "0.27.0", features = ["postgres"] } +shuttle-thruster = "0.27.0" +shuttle-runtime = "0.27.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 46cc4015..df2d0657 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.26.0" -shuttle-runtime = "0.26.0" +shuttle-tide = "0.27.0" +shuttle-runtime = "0.27.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index fb46d60d..3965893a 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.26.0", features = ["postgres"] } -shuttle-runtime = "0.26.0" -shuttle-tide = "0.26.0" +shuttle-aws-rds = { version = "0.27.0", features = ["postgres"] } +shuttle-runtime = "0.27.0" +shuttle-tide = "0.27.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 5c5ea5f3..51dd56df 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.26.0" -shuttle-tower = "0.26.0" +shuttle-runtime = "0.27.0" +shuttle-tower = "0.27.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index ab38d6c5..e44b4d7a 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.26.0" +shuttle-actix-web = "0.27.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.26.0", default-features = false } +shuttle-runtime = { version = "0.27.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = "0.3.17" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 328cbaa7..0dd7c2c9 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.26.0" -shuttle-warp = "0.26.0" +shuttle-runtime = "0.27.0" +shuttle-warp = "0.27.0" tokio = "1.26.0" warp = "0.3.3" From 0bffd33cadb478c7aac556ef31c0aef82c4fe6fa Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Thu, 21 Sep 2023 12:03:15 +0200 Subject: [PATCH 095/239] feat: remove uses of static-folder (#88) * feat: remove uses of static-folder * add PR template * chore: bump metadata versions * fix(rocket): unused import --------- Co-authored-by: oddgrd <29732646+oddgrd@users.noreply.github.com> --- .github/pull_request_template.md | 16 ++++++++++++++++ actix-web/websocket-actorless/Cargo.toml | 1 - axum/metadata/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 1 - axum/static-files/src/main.rs | 8 ++------ axum/static-next-server/.ignore | 1 - axum/static-next-server/Cargo.toml | 1 - axum/static-next-server/README.md | 2 +- axum/static-next-server/Shuttle.toml | 3 +++ axum/static-next-server/src/main.rs | 6 ++---- axum/websocket/Cargo.toml | 1 - axum/websocket/src/main.rs | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 1 - fullstack-templates/saas/backend/src/main.rs | 11 ++++++++--- rocket/dyn-templates/Cargo.toml | 1 - rocket/dyn-templates/src/main.rs | 17 +++++------------ 16 files changed, 42 insertions(+), 38 deletions(-) create mode 100644 .github/pull_request_template.md delete mode 100644 axum/static-next-server/.ignore create mode 100644 axum/static-next-server/Shuttle.toml diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..da45b522 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,16 @@ + +## Description of change + + + + + +## How has this been tested? (if applicable) + + + diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index f474f793..206ce0ed 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -15,6 +15,5 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" shuttle-actix-web = "0.27.0" shuttle-runtime = "0.27.0" -shuttle-static-folder = "0.27.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index 35179831..ffe1f0ea 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.24.0" -shuttle-runtime = "0.24.0" -shuttle-metadata = "0.24.0" +shuttle-axum = "0.27.0" +shuttle-runtime = "0.27.0" +shuttle-metadata = "0.27.0" tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index e9518d8d..ef42576e 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -8,6 +8,5 @@ publish = false axum = "0.6.18" shuttle-axum = "0.27.0" shuttle-runtime = "0.27.0" -shuttle-static-folder = "0.27.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-files/src/main.rs b/axum/static-files/src/main.rs index 8e81df59..9755c362 100644 --- a/axum/static-files/src/main.rs +++ b/axum/static-files/src/main.rs @@ -8,14 +8,10 @@ async fn hello_world() -> &'static str { } #[shuttle_runtime::main] -async fn axum( - // Name your static assets folder by passing `folder = ` to `StaticFolder` - // If you don't pass a name, it will default to `static`. - #[shuttle_static_folder::StaticFolder(folder = "assets")] static_folder: PathBuf, -) -> shuttle_axum::ShuttleAxum { +async fn axum() -> shuttle_axum::ShuttleAxum { let router = Router::new() .route("/", get(hello_world)) - .nest_service("/assets", ServeDir::new(static_folder)); + .nest_service("/assets", ServeDir::new(PathBuf::from("assets"))); Ok(router.into()) } diff --git a/axum/static-next-server/.ignore b/axum/static-next-server/.ignore deleted file mode 100644 index 5016c4e0..00000000 --- a/axum/static-next-server/.ignore +++ /dev/null @@ -1 +0,0 @@ -!static/ diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 3b40f117..c6ce0bf2 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -9,5 +9,4 @@ axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } shuttle-axum = "0.27.0" shuttle-runtime = "0.27.0" -shuttle-static-folder = "0.27.0" tokio = "1.26.0" diff --git a/axum/static-next-server/README.md b/axum/static-next-server/README.md index ca599ac6..c2f21c83 100644 --- a/axum/static-next-server/README.md +++ b/axum/static-next-server/README.md @@ -4,6 +4,6 @@ This example is a template for an [axum](https://github.com/tokio-rs/axum) serve ## Note -This project misses the `static` NextJS bundle because it's common to not commit it to GitHub. This is done through a `.gitignore`, but Shuttle uses a `.ignore` file which waves the `.gitignore` rule. That's because otherwise Shuttle wouldn't package the `static` directory to be able to deploy it, because of the `.gitignore` filtering. +This project misses the `static` NextJS bundle because it's common to not commit it to GitHub. This is done through a `.gitignore`, but Shuttle uses the assets list in `Shuttle.toml` file which waves the `.gitignore` rule. That's because otherwise Shuttle wouldn't package the `static` directory to be able to deploy it, because of the `.gitignore` filtering. As a result, building this project or trying to run it locally will fail because of the missing `static` folder. diff --git a/axum/static-next-server/Shuttle.toml b/axum/static-next-server/Shuttle.toml new file mode 100644 index 00000000..849387a8 --- /dev/null +++ b/axum/static-next-server/Shuttle.toml @@ -0,0 +1,3 @@ +assets = [ + "static/*", +] diff --git a/axum/static-next-server/src/main.rs b/axum/static-next-server/src/main.rs index 6ce5e935..97232acd 100644 --- a/axum/static-next-server/src/main.rs +++ b/axum/static-next-server/src/main.rs @@ -4,11 +4,9 @@ use axum::Router; use axum_extra::routing::SpaRouter; #[shuttle_runtime::main] -async fn axum( - #[shuttle_static_folder::StaticFolder] static_folder: PathBuf, -) -> shuttle_axum::ShuttleAxum { +async fn axum() -> shuttle_axum::ShuttleAxum { let router = - Router::new().merge(SpaRouter::new("/", static_folder).index_file("index.html")); + Router::new().merge(SpaRouter::new("/", PathBuf::from("static")).index_file("index.html")); Ok(router.into()) } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 60ae5696..c5a94dab 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -13,6 +13,5 @@ serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" shuttle-axum = "0.27.0" shuttle-runtime = "0.27.0" -shuttle-static-folder = "0.27.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/websocket/src/main.rs b/axum/websocket/src/main.rs index b8b7a3bb..734aee58 100644 --- a/axum/websocket/src/main.rs +++ b/axum/websocket/src/main.rs @@ -38,7 +38,7 @@ struct Response { } #[shuttle_runtime::main] -async fn axum(#[shuttle_static_folder::StaticFolder] static_folder: PathBuf) -> ShuttleAxum { +async fn axum() -> ShuttleAxum { let (tx, rx) = watch::channel(Message::Text("{}".to_string())); let state = Arc::new(Mutex::new(State { @@ -75,7 +75,7 @@ async fn axum(#[shuttle_static_folder::StaticFolder] static_folder: PathBuf) -> let router = Router::new() .route("/websocket", get(websocket_handler)) - .nest_service("/", ServeDir::new(static_folder)) + .nest_service("/", ServeDir::new(PathBuf::from("static"))) .layer(Extension(state)); Ok(router.into()) diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 80d7dc77..fed048a1 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -20,7 +20,6 @@ shuttle-axum = "0.27.0" shuttle-runtime = "0.27.0" shuttle-secrets = "0.27.0" shuttle-shared-db = { version = "0.27.0", features = ["postgres"] } -shuttle-static-folder = "0.27.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/fullstack-templates/saas/backend/src/main.rs b/fullstack-templates/saas/backend/src/main.rs index 3d4b22d3..be099a7b 100644 --- a/fullstack-templates/saas/backend/src/main.rs +++ b/fullstack-templates/saas/backend/src/main.rs @@ -40,7 +40,6 @@ impl FromRef for Key { async fn axum( #[shuttle_shared_db::Postgres] postgres: PgPool, #[shuttle_secrets::Secrets] secrets: shuttle_secrets::SecretStore, - #[shuttle_static_folder::StaticFolder(folder = "public")] public: PathBuf, ) -> shuttle_axum::ShuttleAxum { sqlx::migrate!() .run(&postgres) @@ -64,7 +63,7 @@ async fn axum( let router = Router::new() .nest("/api", api_router) .fallback_service(get(|req| async move { - match ServeDir::new(public).oneshot(req).await { + match ServeDir::new(PathBuf::from("public")).oneshot(req).await { Ok(res) => res.map(boxed), Err(err) => Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) @@ -97,5 +96,11 @@ fn grab_secrets(secrets: shuttle_secrets::SecretStore) -> (String, String, Strin .get("DOMAIN_URL") .unwrap_or_else(|| "None".to_string()); - (stripe_key, stripe_sub_price, mailgun_key, mailgun_url, domain) + ( + stripe_key, + stripe_sub_price, + mailgun_key, + mailgun_url, + domain, + ) } diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 7b6f7999..ee68bd0d 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -7,6 +7,5 @@ edition = "2021" rocket = "0.5.0-rc.2" shuttle-rocket = "0.27.0" shuttle-runtime = "0.27.0" -shuttle-static-folder = "0.27.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/dyn-templates/src/main.rs b/rocket/dyn-templates/src/main.rs index 99ff8d16..5d9bab7e 100644 --- a/rocket/dyn-templates/src/main.rs +++ b/rocket/dyn-templates/src/main.rs @@ -4,7 +4,6 @@ extern crate rocket; // use rocket::fs::{FileServer, relative}; use rocket::response::Redirect; use rocket_dyn_templates::{context, Template}; -use std::path::PathBuf; #[get("/")] fn index() -> Redirect { @@ -23,18 +22,12 @@ pub fn hello(name: &str) -> Template { } #[shuttle_runtime::main] -async fn rocket( - #[shuttle_static_folder::StaticFolder(folder = "templates")] static_folder: PathBuf, -) -> shuttle_rocket::ShuttleRocket { - /* The provisioned static folder template directory will not be a sub folder - of the location of the executable so it is necessary to merge the - template_dir setting into the configuration at runtime so that dynamic templates work. +async fn rocket() -> shuttle_rocket::ShuttleRocket { + // Note that shuttle does not include Rocket.toml + // so merging config is the preferred way to modify any settings + // that would otherwise be set in Rocket.toml - Note that shuttle does not include Rocket.toml - so merging config is the preferred way to modify any settings - that would otherwise be set in Rocket.toml - */ - let template_dir = static_folder.to_str().unwrap(); + let template_dir = "templates"; let figment = rocket::Config::figment().merge(("template_dir", template_dir)); let rocket = rocket::custom(figment) // If you also wish to serve static content, uncomment line below and corresponding 'use' on line 4 From 3b68a7d00c19fcc2e5ad6e3e59f1fe3a0e25d48f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Thu, 21 Sep 2023 12:13:49 +0200 Subject: [PATCH 096/239] feat: set rocket static files dir with rocket.toml (#91) --- rocket/dyn-templates/Rocket.toml | 2 ++ rocket/dyn-templates/src/main.rs | 10 ++-------- rocket/dyn-templates/templates/index.html.hbs | 2 +- 3 files changed, 5 insertions(+), 9 deletions(-) create mode 100644 rocket/dyn-templates/Rocket.toml diff --git a/rocket/dyn-templates/Rocket.toml b/rocket/dyn-templates/Rocket.toml new file mode 100644 index 00000000..219cb373 --- /dev/null +++ b/rocket/dyn-templates/Rocket.toml @@ -0,0 +1,2 @@ +[default] +template_dir = "templates" diff --git a/rocket/dyn-templates/src/main.rs b/rocket/dyn-templates/src/main.rs index 5d9bab7e..6ef11fcb 100644 --- a/rocket/dyn-templates/src/main.rs +++ b/rocket/dyn-templates/src/main.rs @@ -7,7 +7,7 @@ use rocket_dyn_templates::{context, Template}; #[get("/")] fn index() -> Redirect { - Redirect::to(uri!("/", hello(name = "Your Name"))) + Redirect::to(uri!("/", hello(name = "your-name"))) } #[get("/hello/")] pub fn hello(name: &str) -> Template { @@ -23,13 +23,7 @@ pub fn hello(name: &str) -> Template { #[shuttle_runtime::main] async fn rocket() -> shuttle_rocket::ShuttleRocket { - // Note that shuttle does not include Rocket.toml - // so merging config is the preferred way to modify any settings - // that would otherwise be set in Rocket.toml - - let template_dir = "templates"; - let figment = rocket::Config::figment().merge(("template_dir", template_dir)); - let rocket = rocket::custom(figment) + let rocket = rocket::build() // If you also wish to serve static content, uncomment line below and corresponding 'use' on line 4 // .mount("/", FileServer::from(relative!("templates"))) .mount("/", routes![index, hello]) diff --git a/rocket/dyn-templates/templates/index.html.hbs b/rocket/dyn-templates/templates/index.html.hbs index 84b7d9cd..06a28b64 100644 --- a/rocket/dyn-templates/templates/index.html.hbs +++ b/rocket/dyn-templates/templates/index.html.hbs @@ -6,7 +6,7 @@

Hi {{ name }}!

-

Try entering your own name in the page url to see the page content change ./hello/edit_this_part_of_url

+

Try entering your own name in the page url to see the page content change ./hello/edit_this_part_of_url

Here are the items supplied by the vec! macro in the Template::render context:

    {{#each items}} From 4712db64c4921a61922d285855f980123557e359 Mon Sep 17 00:00:00 2001 From: Joshua Mo <102877324+joshua-mo-143@users.noreply.github.com> Date: Mon, 2 Oct 2023 18:17:22 +0100 Subject: [PATCH 097/239] feat: fix auth for SaaS template (#95) * feat: fix auth * ci: fmt --- fullstack-templates/saas/backend/src/auth.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fullstack-templates/saas/backend/src/auth.rs b/fullstack-templates/saas/backend/src/auth.rs index 69c8bd42..db3dd674 100644 --- a/fullstack-templates/saas/backend/src/auth.rs +++ b/fullstack-templates/saas/backend/src/auth.rs @@ -58,9 +58,12 @@ pub async fn login( match query.await { Ok(res) => { - if bcrypt::verify(login.password, res.get("password")).is_err() { - return Err(StatusCode::BAD_REQUEST); + match bcrypt::verify(login.password, res.get("password")) { + Ok(true) => {} + Ok(false) => return Err(StatusCode::BAD_REQUEST), + Err(_) => return Err(StatusCode::BAD_REQUEST), } + let session_id = rand::random::().to_string(); sqlx::query("INSERT INTO sessions (session_id, user_id) VALUES ($1, $2) ON CONFLICT (user_id) DO UPDATE SET session_id = EXCLUDED.session_id") From cfc433f0626c5fa64306df79320b76fc014cd1b4 Mon Sep 17 00:00:00 2001 From: oddgrd <29732646+oddgrd@users.noreply.github.com> Date: Mon, 2 Oct 2023 16:41:30 +0200 Subject: [PATCH 098/239] chore: v0.28.0 --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/static-next-server/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- axum/with-state/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 8 ++++---- next/hello-world/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 6 +++--- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 38 files changed, 93 insertions(+), 93 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 6405ed7b..bf44791b 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-actix-web = "0.28.0" +shuttle-runtime = "0.28.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index f75f2343..3cd4be42 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-actix-web = "0.28.0" +shuttle-runtime = "0.28.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.27.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.28.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 206ce0ed..ff0a5293 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-actix-web = "0.28.0" +shuttle-runtime = "0.28.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 91235e0b..a012431e 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-axum = "0.28.0" +shuttle-runtime = "0.28.0" tokio = "1.28.2" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index ffe1f0ea..1da07390 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.27.0" -shuttle-runtime = "0.27.0" -shuttle-metadata = "0.27.0" +shuttle-axum = "0.28.0" +shuttle-runtime = "0.28.0" +shuttle-metadata = "0.28.0" tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index ef42576e..3c316335 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-axum = "0.28.0" +shuttle-runtime = "0.28.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index c6ce0bf2..b61949b6 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,6 +7,6 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-axum = "0.28.0" +shuttle-runtime = "0.28.0" tokio = "1.26.0" diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 6c8adc5f..a34aaaa8 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = { version = "0.6.18" } -shuttle-axum = { version = "0.27.0" } -shuttle-runtime = { version = "0.27.0" } -shuttle-turso = { version = "0.27.0" } +shuttle-axum = { version = "0.28.0" } +shuttle-runtime = { version = "0.28.0" } +shuttle-turso = { version = "0.28.0" } libsql-client = "=0.30.1" tokio = { version = "1.26.0" } serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index c5a94dab..93ed9978 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,7 +11,7 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-axum = "0.28.0" +shuttle-runtime = "0.28.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index 897ad985..51f164e0 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-axum = "0.28.0" +shuttle-runtime = "0.28.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index c0f8e674..432a7ee9 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.6.18" serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.27.0" -shuttle-axum = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-service = "0.28.0" +shuttle-axum = "0.28.0" +shuttle-runtime = "0.28.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 908cce0b..89895d57 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.27.0" +shuttle-runtime = "0.28.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index 5d9df4a5..a3dbce48 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-persist = "0.28.0" +shuttle-runtime = "0.28.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index fed048a1..4f0b96ad 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,10 +16,10 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.27.0" -shuttle-runtime = "0.27.0" -shuttle-secrets = "0.27.0" -shuttle-shared-db = { version = "0.27.0", features = ["postgres"] } +shuttle-axum = "0.28.0" +shuttle-runtime = "0.28.0" +shuttle-secrets = "0.28.0" +shuttle-shared-db = { version = "0.28.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index 28b6bdf3..7e372e96 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.27.0" +shuttle-next = "0.28.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 31424009..7ae7013c 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -11,7 +11,7 @@ path = "src/standalone.rs" [dependencies] axum = "0.6.18" dotenvy = "0.15.7" -shuttle-axum = "0.27.0" -shuttle-runtime = "0.27.0" -shuttle-secrets = "0.27.0" +shuttle-axum = "0.28.0" +shuttle-runtime = "0.28.0" +shuttle-secrets = "0.28.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index cefe73fd..e6b2cfde 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-poem = "0.28.0" +shuttle-runtime = "0.28.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 4c9d2d64..fab7e633 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.27.0" -shuttle-shared-db = { version = "0.27.0", features = ["mongodb"] } -shuttle-runtime = "0.27.0" +shuttle-poem = "0.28.0" +shuttle-shared-db = { version = "0.28.0", features = ["mongodb"] } +shuttle-runtime = "0.28.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 7de1045b..47f7100f 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.27.0" -shuttle-runtime = "0.27.0" -shuttle-shared-db = { version = "0.27.0", features = ["postgres"] } +shuttle-poem = "0.28.0" +shuttle-runtime = "0.28.0" +shuttle-shared-db = { version = "0.28.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index c9c1e57c..45efa4b7 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.27.0" -shuttle-runtime = "0.27.0" -shuttle-secrets = "0.27.0" +shuttle-poise = "0.28.0" +shuttle-runtime = "0.28.0" +shuttle-secrets = "0.28.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index 4ac833c5..a445530b 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-rocket = "0.28.0" +shuttle-runtime = "0.28.0" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index ee68bd0d..d1fc3c11 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-rocket = "0.28.0" +shuttle-runtime = "0.28.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index a1e3477e..f93f399b 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-rocket = "0.28.0" +shuttle-runtime = "0.28.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index bdb75573..c25b6868 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.27.0" -shuttle-rocket = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-persist = "0.28.0" +shuttle-rocket = "0.28.0" +shuttle-runtime = "0.28.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 081c2c7c..f708886c 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.27.0", features = ["postgres"] } -shuttle-rocket = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-shared-db = { version = "0.28.0", features = ["postgres"] } +shuttle-rocket = "0.28.0" +shuttle-runtime = "0.28.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 86867b2a..54b90714 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = "0.27.0" -shuttle-runtime = "0.27.0" -shuttle-secrets = "0.27.0" +shuttle-rocket = "0.28.0" +shuttle-runtime = "0.28.0" +shuttle-secrets = "0.28.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index cab982ba..2ab6653c 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-rocket = "0.28.0" +shuttle-runtime = "0.28.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.27.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.28.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index ac7aa6c1..e24ca16f 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-rocket = "0.28.0" +shuttle-runtime = "0.28.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 8d1e31e2..dc46cf3e 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-salvo = "0.28.0" +shuttle-runtime = "0.28.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 0d90d2be..de310188 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-serenity = "0.28.0" +shuttle-runtime = "0.28.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.27.0" +shuttle-secrets = "0.28.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 84a69569..67d4d087 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.27.0" -shuttle-serenity = "0.27.0" -shuttle-runtime = "0.27.0" -shuttle-shared-db = { version = "0.27.0", features = ["postgres"] } +shuttle-secrets = "0.28.0" +shuttle-serenity = "0.28.0" +shuttle-runtime = "0.28.0" +shuttle-shared-db = { version = "0.28.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 2a417017..c1c960da 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-thruster = "0.28.0" +shuttle-runtime = "0.28.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index d0ee56e8..4ca30ea8 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.27.0", features = ["postgres"] } -shuttle-thruster = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-aws-rds = { version = "0.28.0", features = ["postgres"] } +shuttle-thruster = "0.28.0" +shuttle-runtime = "0.28.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index df2d0657..16305742 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.27.0" -shuttle-runtime = "0.27.0" +shuttle-tide = "0.28.0" +shuttle-runtime = "0.28.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index 3965893a..984f7d9c 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.27.0", features = ["postgres"] } -shuttle-runtime = "0.27.0" -shuttle-tide = "0.27.0" +shuttle-aws-rds = { version = "0.28.0", features = ["postgres"] } +shuttle-runtime = "0.28.0" +shuttle-tide = "0.28.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 51dd56df..06ae19b2 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.27.0" -shuttle-tower = "0.27.0" +shuttle-runtime = "0.28.0" +shuttle-tower = "0.28.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index e44b4d7a..8f4947fd 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.27.0" +shuttle-actix-web = "0.28.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.27.0", default-features = false } +shuttle-runtime = { version = "0.28.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = "0.3.17" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 0dd7c2c9..d6dd2758 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.27.0" -shuttle-warp = "0.27.0" +shuttle-runtime = "0.28.0" +shuttle-warp = "0.28.0" tokio = "1.26.0" warp = "0.3.3" From acdcb0fa8fbb07b0cb758187e10f070ceda6c25a Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Mon, 9 Oct 2023 12:01:45 +0200 Subject: [PATCH 099/239] fix: polishing of starter templates (#97) * fix: polishing of starter templates * update init docs * add Shuttle.toml to saas --- README.md | 12 ++++++------ actix-web/hello-world/src/main.rs | 2 +- axum/hello-world/Cargo.toml | 2 +- axum/hello-world/src/main.rs | 2 +- axum/static-files/src/main.rs | 6 ++---- axum/websocket/src/main.rs | 4 ++-- fullstack-templates/saas/backend/.gitignore | 6 ++---- fullstack-templates/saas/backend/Shuttle.toml | 4 ++++ fullstack-templates/saas/backend/src/main.rs | 3 +-- rocket/hello-world/src/main.rs | 5 ++--- 10 files changed, 22 insertions(+), 24 deletions(-) create mode 100644 fullstack-templates/saas/backend/Shuttle.toml diff --git a/README.md b/README.md index 83863465..f17bffbc 100644 --- a/README.md +++ b/README.md @@ -14,21 +14,21 @@ To clone an example, use the init command of the [`cargo-shuttle`](https://docs. ```bash cargo shuttle init --from https://github.com/shuttle-hq/shuttle-examples --subfolder axum/hello-world -``` - -You can also add `--name my-project-name` and the target path as arguments. Otherwise, they will be prompted for. -The `--from` argument uses [cargo-generate](https://cargo-generate.github.io/cargo-generate/) internally, which means you can also use these forms: +### Other forms: -```bash # GitHub prefix. Change to 'gl:' or 'bb:' for GitLab or BitBucket cargo shuttle init --from gh:username/repository # Also GitHub cargo shuttle init --from username/repository # From local folder -cargo shuttle init --from ../path/to/folder +cargo shuttle init --from ./path/to/folder +cargo shuttle init --from ../../another/folder cargo shuttle init --from /home/user/some/folder + +# Clone into 'my-folder', and use the project name 'my-project-name' +cargo shuttle init --from username/repository --name my-project-name my-folder ``` Then, you can navigate into the folder where it was created, and use these commands to run the example locally, and to deploy it. diff --git a/actix-web/hello-world/src/main.rs b/actix-web/hello-world/src/main.rs index 285e3709..fe1e7f33 100644 --- a/actix-web/hello-world/src/main.rs +++ b/actix-web/hello-world/src/main.rs @@ -7,7 +7,7 @@ async fn hello_world() -> &'static str { } #[shuttle_runtime::main] -async fn actix_web() -> ShuttleActixWeb { +async fn main() -> ShuttleActixWeb { let config = move |cfg: &mut ServiceConfig| { cfg.service(hello_world); }; diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index a012431e..19bf2148 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = "0.6.18" +axum = "0.6.20" shuttle-axum = "0.28.0" shuttle-runtime = "0.28.0" tokio = "1.28.2" diff --git a/axum/hello-world/src/main.rs b/axum/hello-world/src/main.rs index 158c1055..d3b9ea08 100644 --- a/axum/hello-world/src/main.rs +++ b/axum/hello-world/src/main.rs @@ -5,7 +5,7 @@ async fn hello_world() -> &'static str { } #[shuttle_runtime::main] -async fn axum() -> shuttle_axum::ShuttleAxum { +async fn main() -> shuttle_axum::ShuttleAxum { let router = Router::new().route("/", get(hello_world)); Ok(router.into()) diff --git a/axum/static-files/src/main.rs b/axum/static-files/src/main.rs index 9755c362..46c1e790 100644 --- a/axum/static-files/src/main.rs +++ b/axum/static-files/src/main.rs @@ -1,5 +1,3 @@ -use std::path::PathBuf; - use axum::{routing::get, Router}; use tower_http::services::ServeDir; @@ -8,10 +6,10 @@ async fn hello_world() -> &'static str { } #[shuttle_runtime::main] -async fn axum() -> shuttle_axum::ShuttleAxum { +async fn main() -> shuttle_axum::ShuttleAxum { let router = Router::new() .route("/", get(hello_world)) - .nest_service("/assets", ServeDir::new(PathBuf::from("assets"))); + .nest_service("/assets", ServeDir::new("assets")); Ok(router.into()) } diff --git a/axum/websocket/src/main.rs b/axum/websocket/src/main.rs index 734aee58..38bbdda7 100644 --- a/axum/websocket/src/main.rs +++ b/axum/websocket/src/main.rs @@ -1,4 +1,4 @@ -use std::{path::PathBuf, sync::Arc, time::Duration}; +use std::{sync::Arc, time::Duration}; use axum::{ extract::{ @@ -75,7 +75,7 @@ async fn axum() -> ShuttleAxum { let router = Router::new() .route("/websocket", get(websocket_handler)) - .nest_service("/", ServeDir::new(PathBuf::from("static"))) + .nest_service("/", ServeDir::new("static")) .layer(Extension(state)); Ok(router.into()) diff --git a/fullstack-templates/saas/backend/.gitignore b/fullstack-templates/saas/backend/.gitignore index 421b0be5..0e544fc6 100644 --- a/fullstack-templates/saas/backend/.gitignore +++ b/fullstack-templates/saas/backend/.gitignore @@ -1,6 +1,4 @@ target/ -Shuttle.toml -Secrets.toml -Secrets.dev.toml +Secrets*.toml test_sub.sh -public/ \ No newline at end of file +public/ diff --git a/fullstack-templates/saas/backend/Shuttle.toml b/fullstack-templates/saas/backend/Shuttle.toml new file mode 100644 index 00000000..ccf634ae --- /dev/null +++ b/fullstack-templates/saas/backend/Shuttle.toml @@ -0,0 +1,4 @@ +name = "fullstack-saas" +assets = [ + "public/*", +] diff --git a/fullstack-templates/saas/backend/src/main.rs b/fullstack-templates/saas/backend/src/main.rs index be099a7b..030ec99e 100644 --- a/fullstack-templates/saas/backend/src/main.rs +++ b/fullstack-templates/saas/backend/src/main.rs @@ -5,7 +5,6 @@ use axum::routing::get; use axum::Router; use axum_extra::extract::cookie::Key; use sqlx::PgPool; -use std::path::PathBuf; use tower::ServiceExt; use tower_http::services::ServeDir; @@ -63,7 +62,7 @@ async fn axum( let router = Router::new() .nest("/api", api_router) .fallback_service(get(|req| async move { - match ServeDir::new(PathBuf::from("public")).oneshot(req).await { + match ServeDir::new("public").oneshot(req).await { Ok(res) => res.map(boxed), Err(err) => Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) diff --git a/rocket/hello-world/src/main.rs b/rocket/hello-world/src/main.rs index 25ca1a77..988779a6 100644 --- a/rocket/hello-world/src/main.rs +++ b/rocket/hello-world/src/main.rs @@ -1,5 +1,4 @@ -#[macro_use] -extern crate rocket; +use rocket::{get, routes}; #[get("/")] fn index() -> &'static str { @@ -7,7 +6,7 @@ fn index() -> &'static str { } #[shuttle_runtime::main] -async fn rocket() -> shuttle_rocket::ShuttleRocket { +async fn main() -> shuttle_rocket::ShuttleRocket { let rocket = rocket::build().mount("/", routes![index]); Ok(rocket.into()) From f3a9857932db2ffdc892a601ad2997bec4eaaa65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Mon, 9 Oct 2023 13:51:44 +0200 Subject: [PATCH 100/239] chore: v0.29.0 (#98) --- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/static-next-server/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- axum/with-state/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 8 ++++---- next/hello-world/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 6 +++--- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/authentication/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 38 files changed, 93 insertions(+), 93 deletions(-) diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index bf44791b..84fb1579 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-actix-web = "0.29.0" +shuttle-runtime = "0.29.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 3cd4be42..c6f3b9bd 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-actix-web = "0.29.0" +shuttle-runtime = "0.29.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.28.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.29.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index ff0a5293..26eee724 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-actix-web = "0.29.0" +shuttle-runtime = "0.29.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 19bf2148..57d2d43b 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.20" -shuttle-axum = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-axum = "0.29.0" +shuttle-runtime = "0.29.0" tokio = "1.28.2" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index 1da07390..69455a5a 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.28.0" -shuttle-runtime = "0.28.0" -shuttle-metadata = "0.28.0" +shuttle-axum = "0.29.0" +shuttle-runtime = "0.29.0" +shuttle-metadata = "0.29.0" tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 3c316335..d7787472 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-axum = "0.29.0" +shuttle-runtime = "0.29.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index b61949b6..4dfa84fe 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,6 +7,6 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-axum = "0.29.0" +shuttle-runtime = "0.29.0" tokio = "1.26.0" diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index a34aaaa8..455a26ca 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = { version = "0.6.18" } -shuttle-axum = { version = "0.28.0" } -shuttle-runtime = { version = "0.28.0" } -shuttle-turso = { version = "0.28.0" } +shuttle-axum = { version = "0.29.0" } +shuttle-runtime = { version = "0.29.0" } +shuttle-turso = { version = "0.29.0" } libsql-client = "=0.30.1" tokio = { version = "1.26.0" } serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 93ed9978..fbe996fc 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,7 +11,7 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-axum = "0.29.0" +shuttle-runtime = "0.29.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index 51f164e0..2e699c6f 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-axum = "0.29.0" +shuttle-runtime = "0.29.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 432a7ee9..4023e91e 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.6.18" serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.28.0" -shuttle-axum = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-service = "0.29.0" +shuttle-axum = "0.29.0" +shuttle-runtime = "0.29.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 89895d57..900b3e40 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.28.0" +shuttle-runtime = "0.29.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index a3dbce48..603679bf 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-persist = "0.29.0" +shuttle-runtime = "0.29.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 4f0b96ad..9c65ce66 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,10 +16,10 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.28.0" -shuttle-runtime = "0.28.0" -shuttle-secrets = "0.28.0" -shuttle-shared-db = { version = "0.28.0", features = ["postgres"] } +shuttle-axum = "0.29.0" +shuttle-runtime = "0.29.0" +shuttle-secrets = "0.29.0" +shuttle-shared-db = { version = "0.29.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index 7e372e96..6aeac2db 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.28.0" +shuttle-next = "0.29.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 7ae7013c..f89abb9b 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -11,7 +11,7 @@ path = "src/standalone.rs" [dependencies] axum = "0.6.18" dotenvy = "0.15.7" -shuttle-axum = "0.28.0" -shuttle-runtime = "0.28.0" -shuttle-secrets = "0.28.0" +shuttle-axum = "0.29.0" +shuttle-runtime = "0.29.0" +shuttle-secrets = "0.29.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index e6b2cfde..388a71f3 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-poem = "0.29.0" +shuttle-runtime = "0.29.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index fab7e633..90979fae 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.28.0" -shuttle-shared-db = { version = "0.28.0", features = ["mongodb"] } -shuttle-runtime = "0.28.0" +shuttle-poem = "0.29.0" +shuttle-shared-db = { version = "0.29.0", features = ["mongodb"] } +shuttle-runtime = "0.29.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 47f7100f..6bccd25b 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.28.0" -shuttle-runtime = "0.28.0" -shuttle-shared-db = { version = "0.28.0", features = ["postgres"] } +shuttle-poem = "0.29.0" +shuttle-runtime = "0.29.0" +shuttle-shared-db = { version = "0.29.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 45efa4b7..c976b23c 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.28.0" -shuttle-runtime = "0.28.0" -shuttle-secrets = "0.28.0" +shuttle-poise = "0.29.0" +shuttle-runtime = "0.29.0" +shuttle-secrets = "0.29.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/authentication/Cargo.toml b/rocket/authentication/Cargo.toml index a445530b..6ca8d67c 100644 --- a/rocket/authentication/Cargo.toml +++ b/rocket/authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-rocket = "0.29.0" +shuttle-runtime = "0.29.0" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index d1fc3c11..19d5a717 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-rocket = "0.29.0" +shuttle-runtime = "0.29.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index f93f399b..85251ed2 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-rocket = "0.29.0" +shuttle-runtime = "0.29.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index c25b6868..bb7be569 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.28.0" -shuttle-rocket = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-persist = "0.29.0" +shuttle-rocket = "0.29.0" +shuttle-runtime = "0.29.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index f708886c..8fd29acc 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.28.0", features = ["postgres"] } -shuttle-rocket = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-shared-db = { version = "0.29.0", features = ["postgres"] } +shuttle-rocket = "0.29.0" +shuttle-runtime = "0.29.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 54b90714..9de332bd 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = "0.28.0" -shuttle-runtime = "0.28.0" -shuttle-secrets = "0.28.0" +shuttle-rocket = "0.29.0" +shuttle-runtime = "0.29.0" +shuttle-secrets = "0.29.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 2ab6653c..0a936981 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-rocket = "0.29.0" +shuttle-runtime = "0.29.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.28.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.29.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index e24ca16f..210ff248 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-rocket = "0.29.0" +shuttle-runtime = "0.29.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index dc46cf3e..4bda8583 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-salvo = "0.29.0" +shuttle-runtime = "0.29.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index de310188..1605778f 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-serenity = "0.29.0" +shuttle-runtime = "0.29.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.28.0" +shuttle-secrets = "0.29.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 67d4d087..3b7dfcb5 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.28.0" -shuttle-serenity = "0.28.0" -shuttle-runtime = "0.28.0" -shuttle-shared-db = { version = "0.28.0", features = ["postgres"] } +shuttle-secrets = "0.29.0" +shuttle-serenity = "0.29.0" +shuttle-runtime = "0.29.0" +shuttle-shared-db = { version = "0.29.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index c1c960da..de2ba268 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-thruster = "0.29.0" +shuttle-runtime = "0.29.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 4ca30ea8..42d15093 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.28.0", features = ["postgres"] } -shuttle-thruster = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-aws-rds = { version = "0.29.0", features = ["postgres"] } +shuttle-thruster = "0.29.0" +shuttle-runtime = "0.29.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 16305742..d28521f3 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.28.0" -shuttle-runtime = "0.28.0" +shuttle-tide = "0.29.0" +shuttle-runtime = "0.29.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index 984f7d9c..a48f15bf 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.28.0", features = ["postgres"] } -shuttle-runtime = "0.28.0" -shuttle-tide = "0.28.0" +shuttle-aws-rds = { version = "0.29.0", features = ["postgres"] } +shuttle-runtime = "0.29.0" +shuttle-tide = "0.29.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 06ae19b2..98b1c973 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.28.0" -shuttle-tower = "0.28.0" +shuttle-runtime = "0.29.0" +shuttle-tower = "0.29.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 8f4947fd..4259f8fa 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.28.0" +shuttle-actix-web = "0.29.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.28.0", default-features = false } +shuttle-runtime = { version = "0.29.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = "0.3.17" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index d6dd2758..818d557c 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.28.0" -shuttle-warp = "0.28.0" +shuttle-runtime = "0.29.0" +shuttle-warp = "0.29.0" tokio = "1.26.0" warp = "0.3.3" From fe9cae733b324e59e98a6fbae2958b4b9a00bbdc Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Thu, 19 Oct 2023 12:27:30 +0200 Subject: [PATCH 101/239] Custom shuttle binary filename (#99) --- other/standalone-binary/Cargo.toml | 6 +++++- other/standalone-binary/README.md | 9 ++++----- other/standalone-binary/src/{main.rs => bin/shuttle.rs} | 0 other/standalone-binary/src/{ => bin}/standalone.rs | 0 4 files changed, 9 insertions(+), 6 deletions(-) rename other/standalone-binary/src/{main.rs => bin/shuttle.rs} (100%) rename other/standalone-binary/src/{ => bin}/standalone.rs (100%) diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index f89abb9b..b7ca5d15 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -4,9 +4,13 @@ version = "0.1.0" edition = "2021" publish = false +[[bin]] +name = "multi-binary" +path = "src/bin/shuttle.rs" + [[bin]] name = "standalone" -path = "src/standalone.rs" +path = "src/bin/standalone.rs" [dependencies] axum = "0.6.18" diff --git a/other/standalone-binary/README.md b/other/standalone-binary/README.md index 8f7905c9..e8829b65 100644 --- a/other/standalone-binary/README.md +++ b/other/standalone-binary/README.md @@ -1,11 +1,10 @@ # Standalone binary - run an app with Shuttle or standalone -This example shows how to separate a project's Shuttle logic from its core functionality so that two binaries can be made: one running with Shuttle using `cargo shuttle run` that can be deployed to Shuttle, and one that can be run with `cargo run --bin ...`. +This example shows how to separate a project's Shuttle logic from its core functionality so that two binaries can be made: one for running with `cargo shuttle run` and deploying to Shuttle, and one that can be run with `cargo run --bin ...`. -The main idea is to have a main binary that Shuttle runs, and another binary that runs standalone. All startup logic is placed in the binary source files, while the implementation (endpoints etc) is moved to the library of the crate. -- `src/main.rs` is the main binary with Shuttle, run with `cargo shuttle run` -- `src/standalone.rs` is without Shuttle, run with `cargo run --bin standalone` (you can change the name) +- `src/bin/shuttle.rs` is the main binary with Shuttle, run with `cargo shuttle run`. Note that the `[[bin]]` entry in `Cargo.toml` needs to have the same name as the crate. The file can have any name you want. +- `src/bin/standalone.rs` is without Shuttle, run with `cargo run --bin standalone` (you can change the name) -This example shows how to use separate logic for getting secrets, but the same approach can be applied to other resources that are initiated by Shuttle's main function. +This example shows how to use separate logic for getting secrets (`shuttle-secrets` vs homemade solution), but the same approach can be applied to other resources that are initiated by Shuttle's main function. diff --git a/other/standalone-binary/src/main.rs b/other/standalone-binary/src/bin/shuttle.rs similarity index 100% rename from other/standalone-binary/src/main.rs rename to other/standalone-binary/src/bin/shuttle.rs diff --git a/other/standalone-binary/src/standalone.rs b/other/standalone-binary/src/bin/standalone.rs similarity index 100% rename from other/standalone-binary/src/standalone.rs rename to other/standalone-binary/src/bin/standalone.rs From 7e07f1816191693ef064fffd3397451371a362c6 Mon Sep 17 00:00:00 2001 From: Joshua Mo <102877324+joshua-mo-143@users.noreply.github.com> Date: Fri, 20 Oct 2023 15:56:03 +0100 Subject: [PATCH 102/239] refactor: Add examples (#93) * refactor: update and standardise examples * refactor: cargo fmt * refactor: correct routing for axum/postgres * refactor: readme.md * refactor: rocket static files example * refactor: clippy * feat: fix auth for SaaS template (#95) * feat: fix auth * ci: fmt * chore: v0.28.0 * fix: polishing of starter templates (#97) * fix: polishing of starter templates * update init docs * add Shuttle.toml to saas * docs: update readme.md * refactor: update and standardise examples * refactor: cargo fmt * refactor: correct routing for axum/postgres * refactor: readme.md * refactor: rocket static files example * refactor: clippy * docs: update readme.md * chore: deps * chore: deps --------- Co-authored-by: oddgrd <29732646+oddgrd@users.noreply.github.com> Co-authored-by: jonaro00 <54029719+jonaro00@users.noreply.github.com> --- README.md | 8 +- actix-web/cookie-authentication/.gitignore | 2 + actix-web/cookie-authentication/Cargo.toml | 12 ++ actix-web/cookie-authentication/src/main.rs | 77 ++++++++ actix-web/static-files/.gitignore | 2 + actix-web/static-files/Cargo.toml | 11 ++ actix-web/static-files/Shuttle.toml | 1 + actix-web/static-files/assets/index.html | 1 + actix-web/static-files/src/main.rs | 17 ++ axum/jwt-authentication/.gitignore | 2 + axum/jwt-authentication/Cargo.toml | 15 ++ axum/jwt-authentication/src/main.rs | 176 ++++++++++++++++++ axum/postgres/.gitignore | 2 + axum/postgres/Cargo.toml | 13 ++ axum/postgres/migrations/schema.sql | 7 + axum/postgres/src/main.rs | 70 +++++++ .../Cargo.toml | 0 .../README.md | 0 .../Shuttle.toml | 0 .../src/claims.rs | 0 .../src/main.rs | 0 rocket/static-files/.gitignore | 2 + rocket/static-files/Cargo.toml | 10 + rocket/static-files/Shuttle.toml | 1 + rocket/static-files/assets/about.html | 9 + rocket/static-files/assets/index.html | 10 + rocket/static-files/src/main.rs | 21 +++ 27 files changed, 467 insertions(+), 2 deletions(-) create mode 100644 actix-web/cookie-authentication/.gitignore create mode 100644 actix-web/cookie-authentication/Cargo.toml create mode 100644 actix-web/cookie-authentication/src/main.rs create mode 100644 actix-web/static-files/.gitignore create mode 100644 actix-web/static-files/Cargo.toml create mode 100644 actix-web/static-files/Shuttle.toml create mode 100644 actix-web/static-files/assets/index.html create mode 100644 actix-web/static-files/src/main.rs create mode 100644 axum/jwt-authentication/.gitignore create mode 100644 axum/jwt-authentication/Cargo.toml create mode 100644 axum/jwt-authentication/src/main.rs create mode 100644 axum/postgres/.gitignore create mode 100644 axum/postgres/Cargo.toml create mode 100644 axum/postgres/migrations/schema.sql create mode 100644 axum/postgres/src/main.rs rename rocket/{authentication => jwt-authentication}/Cargo.toml (100%) rename rocket/{authentication => jwt-authentication}/README.md (100%) rename rocket/{authentication => jwt-authentication}/Shuttle.toml (100%) rename rocket/{authentication => jwt-authentication}/src/claims.rs (100%) rename rocket/{authentication => jwt-authentication}/src/main.rs (100%) create mode 100644 rocket/static-files/.gitignore create mode 100644 rocket/static-files/Cargo.toml create mode 100644 rocket/static-files/Shuttle.toml create mode 100644 rocket/static-files/assets/about.html create mode 100644 rocket/static-files/assets/index.html create mode 100644 rocket/static-files/src/main.rs diff --git a/README.md b/README.md index f17bffbc..4a954344 100644 --- a/README.md +++ b/README.md @@ -45,30 +45,34 @@ cargo shuttle deploy ## Official Examples -This is a list of all examples maintained in this repostiory. +This is a list of all examples maintained in this repository. **Framework** | **Name & Link** | **Description** | **Command** --------------|-----------------|-------------|---------------- Actix Web | [hello-world](./actix-web/hello-world/) | Hello World | `cargo shuttle init --template actix-web` Actix Web | [postgres](./actix-web/postgres/) | TODO app with a Postgres DB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/postgres` +Actix Web | [static-files](./actix-web/static-files/) | Hello World page that serves static HTML and JS files | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/static-files` Actix Web | [websocket-actorless](./actix-web/websocket-actorless/) | Websocket app that checks the status of Shuttle's API | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/websocket-actorless` +Actix Web | [cookie-authentication](./actix-web/cookie-authentication/) | Use JWT to authenticate API endpoints | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/cookie-authentication` Axum | [hello-world](./axum/hello-world/) | Hello World | `cargo shuttle init --template axum` Axum | [metadata](./axum/metadata/) | Simple app that prints the service information such as Shuttle service name | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/metadata` Axum | [static-files](./axum/static-files/) | Hello World page that serves static HTML and JS files | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/static-files` Axum | [static-next-server](./axum/static-next-server/) | SPA server for serving a apps from frameworks such as Next.js | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/static-next-server` Axum | [websocket](./axum/websocket/) | Websocket app that checks the status of Shuttle's API | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/websocket` Axum | [with-state](./axum/with-state/) | Hello World with example of how to utilize State in Axum | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/with-state` +Axum | [jwt-authentication](./axum/jwt-authentication/) | Use JWT to authenticate API endpoints | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/jwt-authentication` Axum & Next.js | [saas](./fullstack-templates/saas/) | Competent opinionated fullstack web app with pre-made routes and assets | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder fullstack-templates/saas` Poem | [hello-world](./poem/hello-world/) | Hello World | `cargo shuttle init --template poem` Poem | [mongodb](./poem/mongodb/) | TODO app with MongoDB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder poem/mongodb` Poem | [postgres](./poem/postgres/) | TODO app with a Postgres DB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder poem/postgres` Poise | [hello-world](./poise/hello-world/) | Hello World Discord bot | `cargo shuttle init --template poise` -Rocket | [authentication](./rocket/authentication/) | Use JWT to authenticate API endpoints | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/authentication` +Rocket | [jwt-authentication](./rocket/jwt-authentication/) | Use JWT to authenticate API endpoints | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/jwt-authentication` Rocket | [dyn-templates](./rocket/dyn-templates/) | Handlebars dynamic templates | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/dyn-templates` Rocket | [hello-world](./rocket/hello-world/) | Hello World | `cargo shuttle init --template rocket` Rocket | [persist](./rocket/persist/) | Store weather data with Shuttle Persist | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/persist` Rocket | [postgres](./rocket/postgres/) | TODO app with a Postgres DB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/postgres` Rocket | [secrets](./rocket/secrets/) | Extract secrets from your Secrets.toml file | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/secrets` +Rocket | [static-files](./rocket/static-files/) | Hello World page that serves static HTML and JS files | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/static-files` Rocket | [url-shortener](./rocket/url-shortener/) | URL shortener with Postgres storage | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/url-shortener` Rocket | [workspace](./rocket/workspace/) | A cargo workspace where one crate is a Shuttle service | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/workspace` Salvo | [hello-world](./salvo/hello-world/) | Hello World | `cargo shuttle init --template salvo` diff --git a/actix-web/cookie-authentication/.gitignore b/actix-web/cookie-authentication/.gitignore new file mode 100644 index 00000000..a1a5734e --- /dev/null +++ b/actix-web/cookie-authentication/.gitignore @@ -0,0 +1,2 @@ +/target +Secrets*.toml diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml new file mode 100644 index 00000000..bb4bd7cd --- /dev/null +++ b/actix-web/cookie-authentication/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "cookie-authentication" +version = "0.1.0" +edition = "2021" + +[dependencies] +actix-identity = "0.6.0" +actix-session = { version = "0.8.0", features = ["cookie-session"] } +actix-web = "4.3.1" +shuttle-actix-web = "0.29.0" +shuttle-runtime = "0.29.0" +tokio = "1.26.0" diff --git a/actix-web/cookie-authentication/src/main.rs b/actix-web/cookie-authentication/src/main.rs new file mode 100644 index 00000000..ef217955 --- /dev/null +++ b/actix-web/cookie-authentication/src/main.rs @@ -0,0 +1,77 @@ +use actix_identity::{Identity, IdentityMiddleware}; +use actix_session::{config::PersistentSession, storage::CookieSessionStore, SessionMiddleware}; +use actix_web::{ + cookie::{time::Duration, Key}, + error, + http::StatusCode, + middleware, web, HttpMessage as _, HttpRequest, Responder, +}; +use actix_web::{get, web::ServiceConfig}; +use shuttle_actix_web::ShuttleActixWeb; + +const FIVE_MINUTES: Duration = Duration::minutes(5); + +#[get("/")] +async fn index(identity: Option) -> actix_web::Result { + let id = match identity.map(|id| id.id()) { + None => "anonymous".to_owned(), + Some(Ok(id)) => id, + Some(Err(err)) => return Err(error::ErrorInternalServerError(err)), + }; + + Ok(format!("Hello {id}")) +} + +#[get("/login")] +async fn login(req: HttpRequest) -> impl Responder { + Identity::login(&req.extensions(), "user1".to_owned()).unwrap(); + + web::Redirect::to("/").using_status_code(StatusCode::FOUND) +} + +#[get("/logout")] +async fn logout(id: Identity) -> impl Responder { + id.logout(); + + web::Redirect::to("/").using_status_code(StatusCode::FOUND) +} + +#[shuttle_runtime::main] +async fn actix_web() -> ShuttleActixWeb { + // Generate a random secret key. Note that it is important to use a unique + // secret key for every project. Anyone with access to the key can generate + // authentication cookies for any user! + // + // If the secret key is read from a file or the environment, make sure it is generated securely. + // For example, a secure random key (in base64 format) can be generated with the OpenSSL CLI: + // ``` + // openssl rand -base64 64 + // ``` + // + // Then decoded and used converted to a Key: + // ``` + // let secret_key = Key::from(base64::decode(&private_key_base64).unwrap()); + // ``` + let secret_key = Key::generate(); + + let config = move |cfg: &mut ServiceConfig| { + cfg.service( + web::scope("/") + .service(index) + .service(login) + .service(logout) + .wrap(IdentityMiddleware::default()) + .wrap( + SessionMiddleware::builder(CookieSessionStore::default(), secret_key.clone()) + .cookie_name("auth-example".to_owned()) + .cookie_secure(false) + .session_lifecycle(PersistentSession::default().session_ttl(FIVE_MINUTES)) + .build(), + ) + .wrap(middleware::NormalizePath::trim()) + .wrap(middleware::Logger::default()), + ); + }; + + Ok(config.into()) +} diff --git a/actix-web/static-files/.gitignore b/actix-web/static-files/.gitignore new file mode 100644 index 00000000..a1a5734e --- /dev/null +++ b/actix-web/static-files/.gitignore @@ -0,0 +1,2 @@ +/target +Secrets*.toml diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml new file mode 100644 index 00000000..bf67c8d7 --- /dev/null +++ b/actix-web/static-files/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "static-files" +version = "0.1.0" +edition = "2021" + +[dependencies] +actix-files = "0.6.2" +actix-web = "4.3.1" +shuttle-actix-web = "0.29.0" +shuttle-runtime = "0.29.0" +tokio = "1.26.0" diff --git a/actix-web/static-files/Shuttle.toml b/actix-web/static-files/Shuttle.toml new file mode 100644 index 00000000..7bc2b0dd --- /dev/null +++ b/actix-web/static-files/Shuttle.toml @@ -0,0 +1 @@ +assets = ["assets/*"] diff --git a/actix-web/static-files/assets/index.html b/actix-web/static-files/assets/index.html new file mode 100644 index 00000000..cd087558 --- /dev/null +++ b/actix-web/static-files/assets/index.html @@ -0,0 +1 @@ +Hello world! diff --git a/actix-web/static-files/src/main.rs b/actix-web/static-files/src/main.rs new file mode 100644 index 00000000..5a3923d0 --- /dev/null +++ b/actix-web/static-files/src/main.rs @@ -0,0 +1,17 @@ +use actix_files::NamedFile; +use actix_web::{get, web::ServiceConfig, Responder}; +use shuttle_actix_web::ShuttleActixWeb; + +#[get("/")] +async fn index() -> impl Responder { + NamedFile::open_async("assets/index.html").await +} + +#[shuttle_runtime::main] +async fn actix_web() -> ShuttleActixWeb { + let config = move |cfg: &mut ServiceConfig| { + cfg.service(index); + }; + + Ok(config.into()) +} diff --git a/axum/jwt-authentication/.gitignore b/axum/jwt-authentication/.gitignore new file mode 100644 index 00000000..a1a5734e --- /dev/null +++ b/axum/jwt-authentication/.gitignore @@ -0,0 +1,2 @@ +/target +Secrets*.toml diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml new file mode 100644 index 00000000..cdda563c --- /dev/null +++ b/axum/jwt-authentication/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "jwt-authentication" +version = "0.1.0" +edition = "2021" + +[dependencies] +axum = { version = "0.6.18", features = ["headers"] } +jsonwebtoken = "8.3.0" +once_cell = "1.18.0" +serde = { version = "1.0.188", features = ["derive"] } +serde_json = "1.0.107" +shuttle-axum = "0.29.0" +shuttle-runtime = "0.29.0" +tokio = "1.28.2" +tracing-subscriber = "0.3.17" diff --git a/axum/jwt-authentication/src/main.rs b/axum/jwt-authentication/src/main.rs new file mode 100644 index 00000000..bad2f11d --- /dev/null +++ b/axum/jwt-authentication/src/main.rs @@ -0,0 +1,176 @@ +use axum::{ + async_trait, + extract::FromRequestParts, + headers::{authorization::Bearer, Authorization}, + http::{request::Parts, StatusCode}, + response::{IntoResponse, Response}, + routing::{get, post}, + Json, RequestPartsExt, Router, TypedHeader, +}; +use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; +use serde_json::json; +use std::fmt::Display; +use std::time::SystemTime; + +static KEYS: Lazy = Lazy::new(|| { + // note that in production, you will probably want to use a random SHA-256 hash or similar + let secret = "JWT_SECRET".to_string(); + Keys::new(secret.as_bytes()) +}); + +#[shuttle_runtime::main] +async fn main() -> shuttle_axum::ShuttleAxum { + let app = Router::new() + .route("/public", get(public)) + .route("/private", get(private)) + .route("/login", post(login)); + + Ok(app.into()) +} + +async fn public() -> &'static str { + // A public endpoint that anyone can access + "Welcome to the public area :)" +} + +async fn private(claims: Claims) -> Result { + // Send the protected data to the user + Ok(format!( + "Welcome to the protected area :)\nYour data:\n{claims}", + )) +} + +async fn login(Json(payload): Json) -> Result, AuthError> { + // Check if the user sent the credentials + if payload.client_id.is_empty() || payload.client_secret.is_empty() { + return Err(AuthError::MissingCredentials); + } + // Here you can check the user credentials from a database + if payload.client_id != "foo" || payload.client_secret != "bar" { + return Err(AuthError::WrongCredentials); + } + + // add 5 minutes to current unix epoch time as expiry date/time + let exp = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() + .as_secs() + + 300; + + let claims = Claims { + sub: "b@b.com".to_owned(), + company: "ACME".to_owned(), + // Mandatory expiry time as UTC timestamp - takes unix epoch + exp: usize::try_from(exp).unwrap(), + }; + // Create the authorization token + let token = encode(&Header::default(), &claims, &KEYS.encoding) + .map_err(|_| AuthError::TokenCreation)?; + + // Send the authorized token + Ok(Json(AuthBody::new(token))) +} + +// allow us to print the claim details for the private route +impl Display for Claims { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Email: {}\nCompany: {}", self.sub, self.company) + } +} + +// implement a method to create a response type containing the JWT +impl AuthBody { + fn new(access_token: String) -> Self { + Self { + access_token, + token_type: "Bearer".to_string(), + } + } +} + +// implement FromRequestParts for Claims (the JWT struct) +// FromRequestParts allows us to use Claims without consuming the request +#[async_trait] +impl FromRequestParts for Claims +where + S: Send + Sync, +{ + type Rejection = AuthError; + + async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result { + // Extract the token from the authorization header + let TypedHeader(Authorization(bearer)) = parts + .extract::>>() + .await + .map_err(|_| AuthError::InvalidToken)?; + // Decode the user data + let token_data = decode::(bearer.token(), &KEYS.decoding, &Validation::default()) + .map_err(|_| AuthError::InvalidToken)?; + + Ok(token_data.claims) + } +} + +// implement IntoResponse for AuthError so we can use it as an Axum response type +impl IntoResponse for AuthError { + fn into_response(self) -> Response { + let (status, error_message) = match self { + AuthError::WrongCredentials => (StatusCode::UNAUTHORIZED, "Wrong credentials"), + AuthError::MissingCredentials => (StatusCode::BAD_REQUEST, "Missing credentials"), + AuthError::TokenCreation => (StatusCode::INTERNAL_SERVER_ERROR, "Token creation error"), + AuthError::InvalidToken => (StatusCode::BAD_REQUEST, "Invalid token"), + }; + let body = Json(json!({ + "error": error_message, + })); + (status, body).into_response() + } +} + +// encoding/decoding keys - set in the static `once_cell` above +struct Keys { + encoding: EncodingKey, + decoding: DecodingKey, +} + +impl Keys { + fn new(secret: &[u8]) -> Self { + Self { + encoding: EncodingKey::from_secret(secret), + decoding: DecodingKey::from_secret(secret), + } + } +} + +// the JWT claim +#[derive(Debug, Serialize, Deserialize)] +struct Claims { + sub: String, + company: String, + exp: usize, +} + +// the response that we pass back to HTTP client once successfully authorised +#[derive(Debug, Serialize)] +struct AuthBody { + access_token: String, + token_type: String, +} + +// the request type - "client_id" is analogous to a username, client_secret can also be interpreted as a password +#[derive(Debug, Deserialize)] +struct AuthPayload { + client_id: String, + client_secret: String, +} + +// error types for auth errors +#[derive(Debug)] +enum AuthError { + WrongCredentials, + MissingCredentials, + TokenCreation, + InvalidToken, +} diff --git a/axum/postgres/.gitignore b/axum/postgres/.gitignore new file mode 100644 index 00000000..a1a5734e --- /dev/null +++ b/axum/postgres/.gitignore @@ -0,0 +1,2 @@ +/target +Secrets*.toml diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml new file mode 100644 index 00000000..f5c9967e --- /dev/null +++ b/axum/postgres/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "postgres" +version = "0.1.0" +edition = "2021" + +[dependencies] +axum = "0.6.18" +serde = { version = "1.0.188", features = ["derive"] } +shuttle-axum = "0.29.0" +shuttle-runtime = "0.29.0" +shuttle-shared-db = { version = "0.29.0", features = ["postgres"] } +sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } +tokio = "1.28.2" diff --git a/axum/postgres/migrations/schema.sql b/axum/postgres/migrations/schema.sql new file mode 100644 index 00000000..99306c87 --- /dev/null +++ b/axum/postgres/migrations/schema.sql @@ -0,0 +1,7 @@ +DROP TABLE IF EXISTS todos; + +CREATE TABLE IF NOT EXISTS todos ( + id serial PRIMARY KEY, + note TEXT NOT NULL +); + diff --git a/axum/postgres/src/main.rs b/axum/postgres/src/main.rs new file mode 100644 index 00000000..623c35bc --- /dev/null +++ b/axum/postgres/src/main.rs @@ -0,0 +1,70 @@ +use axum::{ + extract::{Path, State}, + http::StatusCode, + response::IntoResponse, + routing::{get, post}, + Json, Router, +}; +use serde::{Deserialize, Serialize}; +use shuttle_runtime::CustomError; +use sqlx::{FromRow, PgPool}; + +async fn retrieve( + Path(id): Path, + State(state): State, +) -> Result { + match sqlx::query_as::<_, Todo>("SELECT * FROM todos WHERE id = $1") + .bind(id) + .fetch_one(&state.pool) + .await + { + Ok(todo) => Ok((StatusCode::OK, Json(todo))), + Err(e) => Err((StatusCode::BAD_REQUEST, e.to_string())), + } +} + +async fn add( + State(state): State, + Json(data): Json, +) -> Result { + match sqlx::query_as::<_, Todo>("INSERT INTO todos (note) VALUES ($1) RETURNING id, note") + .bind(&data.note) + .fetch_one(&state.pool) + .await + { + Ok(todo) => Ok((StatusCode::CREATED, Json(todo))), + Err(e) => Err((StatusCode::BAD_REQUEST, e.to_string())), + } +} + +#[derive(Clone)] +struct MyState { + pool: PgPool, +} + +#[shuttle_runtime::main] +async fn axum(#[shuttle_shared_db::Postgres] pool: PgPool) -> shuttle_axum::ShuttleAxum { + sqlx::migrate!() + .run(&pool) + .await + .map_err(CustomError::new)?; + + let state = MyState { pool }; + let router = Router::new() + .route("/todos", post(add)) + .route("/todos/:id", get(retrieve)) + .with_state(state); + + Ok(router.into()) +} + +#[derive(Deserialize)] +struct TodoNew { + pub note: String, +} + +#[derive(Serialize, FromRow)] +struct Todo { + pub id: i32, + pub note: String, +} diff --git a/rocket/authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml similarity index 100% rename from rocket/authentication/Cargo.toml rename to rocket/jwt-authentication/Cargo.toml diff --git a/rocket/authentication/README.md b/rocket/jwt-authentication/README.md similarity index 100% rename from rocket/authentication/README.md rename to rocket/jwt-authentication/README.md diff --git a/rocket/authentication/Shuttle.toml b/rocket/jwt-authentication/Shuttle.toml similarity index 100% rename from rocket/authentication/Shuttle.toml rename to rocket/jwt-authentication/Shuttle.toml diff --git a/rocket/authentication/src/claims.rs b/rocket/jwt-authentication/src/claims.rs similarity index 100% rename from rocket/authentication/src/claims.rs rename to rocket/jwt-authentication/src/claims.rs diff --git a/rocket/authentication/src/main.rs b/rocket/jwt-authentication/src/main.rs similarity index 100% rename from rocket/authentication/src/main.rs rename to rocket/jwt-authentication/src/main.rs diff --git a/rocket/static-files/.gitignore b/rocket/static-files/.gitignore new file mode 100644 index 00000000..a1a5734e --- /dev/null +++ b/rocket/static-files/.gitignore @@ -0,0 +1,2 @@ +/target +Secrets*.toml diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml new file mode 100644 index 00000000..faef7ef0 --- /dev/null +++ b/rocket/static-files/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "static-files" +version = "0.1.0" +edition = "2021" + +[dependencies] +rocket = "0.5.0-rc.2" +shuttle-rocket = "0.29.0" +shuttle-runtime = "0.29.0" +tokio = "1.26.0" diff --git a/rocket/static-files/Shuttle.toml b/rocket/static-files/Shuttle.toml new file mode 100644 index 00000000..7bc2b0dd --- /dev/null +++ b/rocket/static-files/Shuttle.toml @@ -0,0 +1 @@ +assets = ["assets/*"] diff --git a/rocket/static-files/assets/about.html b/rocket/static-files/assets/about.html new file mode 100644 index 00000000..0f7f7a3c --- /dev/null +++ b/rocket/static-files/assets/about.html @@ -0,0 +1,9 @@ + + + + Static Files + + +

    This is the About page.

    + + diff --git a/rocket/static-files/assets/index.html b/rocket/static-files/assets/index.html new file mode 100644 index 00000000..c3ef507e --- /dev/null +++ b/rocket/static-files/assets/index.html @@ -0,0 +1,10 @@ + + + + Static Files + + +

    This is an example of serving static files with Rocket and Shuttle.

    + Click here to go to the About page + + diff --git a/rocket/static-files/src/main.rs b/rocket/static-files/src/main.rs new file mode 100644 index 00000000..3c5bc59f --- /dev/null +++ b/rocket/static-files/src/main.rs @@ -0,0 +1,21 @@ +use rocket::fs::relative; +use rocket::fs::NamedFile; +use std::path::{Path, PathBuf}; + +#[rocket::get("/")] +pub async fn serve(mut path: PathBuf) -> Option { + path.set_extension("html"); + let mut path = Path::new(relative!("assets")).join(path); + if path.is_dir() { + path.push("index.html"); + } + + NamedFile::open(path).await.ok() +} + +#[shuttle_runtime::main] +async fn rocket() -> shuttle_rocket::ShuttleRocket { + let rocket = rocket::build().mount("/", rocket::routes![serve]); + + Ok(rocket.into()) +} From 67fde9a7bb02cdec1624cca0f37e082e555ba33b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Tue, 24 Oct 2023 08:49:06 +0200 Subject: [PATCH 103/239] chore: update libsql-client version in axum turso (#100) (#103) Co-authored-by: Jeff Mitchell --- axum/turso/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 455a26ca..a67054e2 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -8,7 +8,7 @@ axum = { version = "0.6.18" } shuttle-axum = { version = "0.29.0" } shuttle-runtime = { version = "0.29.0" } shuttle-turso = { version = "0.29.0" } -libsql-client = "=0.30.1" +libsql-client = "0.32.0" tokio = { version = "1.26.0" } serde = { version = "1.0.164", features = ["derive"] } serde_json = "1.0.99" From 75c98cf0701056e9af01574ad8a4cbebddb9b7fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Tue, 24 Oct 2023 10:03:24 +0200 Subject: [PATCH 104/239] chore: v0.30.0 (#104) --- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 6 +++--- axum/postgres/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/static-next-server/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- axum/with-state/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 8 ++++---- next/hello-world/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 6 +++--- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 43 files changed, 104 insertions(+), 104 deletions(-) diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index bb4bd7cd..711953b3 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.6.0" actix-session = { version = "0.8.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-actix-web = "0.30.0" +shuttle-runtime = "0.30.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 84fb1579..2d91cf7a 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-actix-web = "0.30.0" +shuttle-runtime = "0.30.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index c6f3b9bd..b92883d2 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-actix-web = "0.30.0" +shuttle-runtime = "0.30.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.29.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.30.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index bf67c8d7..3428c0d5 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-actix-web = "0.30.0" +shuttle-runtime = "0.30.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 26eee724..50e777a7 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-actix-web = "0.30.0" +shuttle-runtime = "0.30.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 57d2d43b..b9b0e9f8 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.20" -shuttle-axum = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-axum = "0.30.0" +shuttle-runtime = "0.30.0" tokio = "1.28.2" diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index cdda563c..ff7a7c8e 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -9,7 +9,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-axum = "0.30.0" +shuttle-runtime = "0.30.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index 69455a5a..aaa2cdb7 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.29.0" -shuttle-runtime = "0.29.0" -shuttle-metadata = "0.29.0" +shuttle-axum = "0.30.0" +shuttle-runtime = "0.30.0" +shuttle-metadata = "0.30.0" tokio = "1.28.2" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index f5c9967e..1921bcfa 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.6.18" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.29.0" -shuttle-runtime = "0.29.0" -shuttle-shared-db = { version = "0.29.0", features = ["postgres"] } +shuttle-axum = "0.30.0" +shuttle-runtime = "0.30.0" +shuttle-shared-db = { version = "0.30.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index d7787472..2165648c 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-axum = "0.30.0" +shuttle-runtime = "0.30.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 4dfa84fe..14c32caa 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,6 +7,6 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-axum = "0.30.0" +shuttle-runtime = "0.30.0" tokio = "1.26.0" diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index a67054e2..390605b8 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = { version = "0.6.18" } -shuttle-axum = { version = "0.29.0" } -shuttle-runtime = { version = "0.29.0" } -shuttle-turso = { version = "0.29.0" } +shuttle-axum = { version = "0.30.0" } +shuttle-runtime = { version = "0.30.0" } +shuttle-turso = { version = "0.30.0" } libsql-client = "0.32.0" tokio = { version = "1.26.0" } serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index fbe996fc..78d66fb6 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,7 +11,7 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-axum = "0.30.0" +shuttle-runtime = "0.30.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index 2e699c6f..e495f447 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-axum = "0.30.0" +shuttle-runtime = "0.30.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 4023e91e..ff259f85 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.6.18" serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.29.0" -shuttle-axum = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-service = "0.30.0" +shuttle-axum = "0.30.0" +shuttle-runtime = "0.30.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 900b3e40..12ec690e 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.29.0" +shuttle-runtime = "0.30.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index 603679bf..b147d777 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-persist = "0.30.0" +shuttle-runtime = "0.30.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 9c65ce66..f4a68c82 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,10 +16,10 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.29.0" -shuttle-runtime = "0.29.0" -shuttle-secrets = "0.29.0" -shuttle-shared-db = { version = "0.29.0", features = ["postgres"] } +shuttle-axum = "0.30.0" +shuttle-runtime = "0.30.0" +shuttle-secrets = "0.30.0" +shuttle-shared-db = { version = "0.30.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index 6aeac2db..1edcd528 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.29.0" +shuttle-next = "0.30.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index b7ca5d15..cb97cd35 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,7 +15,7 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.6.18" dotenvy = "0.15.7" -shuttle-axum = "0.29.0" -shuttle-runtime = "0.29.0" -shuttle-secrets = "0.29.0" +shuttle-axum = "0.30.0" +shuttle-runtime = "0.30.0" +shuttle-secrets = "0.30.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 388a71f3..ba6c5417 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-poem = "0.30.0" +shuttle-runtime = "0.30.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 90979fae..7badd00c 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.29.0" -shuttle-shared-db = { version = "0.29.0", features = ["mongodb"] } -shuttle-runtime = "0.29.0" +shuttle-poem = "0.30.0" +shuttle-shared-db = { version = "0.30.0", features = ["mongodb"] } +shuttle-runtime = "0.30.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 6bccd25b..e984145a 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.29.0" -shuttle-runtime = "0.29.0" -shuttle-shared-db = { version = "0.29.0", features = ["postgres"] } +shuttle-poem = "0.30.0" +shuttle-runtime = "0.30.0" +shuttle-shared-db = { version = "0.30.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index c976b23c..526d2040 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.29.0" -shuttle-runtime = "0.29.0" -shuttle-secrets = "0.29.0" +shuttle-poise = "0.30.0" +shuttle-runtime = "0.30.0" +shuttle-secrets = "0.30.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 19d5a717..9b6661ff 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-rocket = "0.30.0" +shuttle-runtime = "0.30.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 85251ed2..250d17ee 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-rocket = "0.30.0" +shuttle-runtime = "0.30.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 6ca8d67c..616a1d3d 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-rocket = "0.30.0" +shuttle-runtime = "0.30.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index bb7be569..5864e679 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.29.0" -shuttle-rocket = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-persist = "0.30.0" +shuttle-rocket = "0.30.0" +shuttle-runtime = "0.30.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 8fd29acc..783c75c1 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.29.0", features = ["postgres"] } -shuttle-rocket = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-shared-db = { version = "0.30.0", features = ["postgres"] } +shuttle-rocket = "0.30.0" +shuttle-runtime = "0.30.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 9de332bd..46b3fc1e 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = "0.29.0" -shuttle-runtime = "0.29.0" -shuttle-secrets = "0.29.0" +shuttle-rocket = "0.30.0" +shuttle-runtime = "0.30.0" +shuttle-secrets = "0.30.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index faef7ef0..2b25ae7b 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-rocket = "0.30.0" +shuttle-runtime = "0.30.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 0a936981..659f89b1 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-rocket = "0.30.0" +shuttle-runtime = "0.30.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.29.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.30.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 210ff248..df12c71e 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-rocket = "0.30.0" +shuttle-runtime = "0.30.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 4bda8583..462b7d41 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-salvo = "0.30.0" +shuttle-runtime = "0.30.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 1605778f..bc51caac 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-serenity = "0.30.0" +shuttle-runtime = "0.30.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.29.0" +shuttle-secrets = "0.30.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 3b7dfcb5..fba7d624 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.29.0" -shuttle-serenity = "0.29.0" -shuttle-runtime = "0.29.0" -shuttle-shared-db = { version = "0.29.0", features = ["postgres"] } +shuttle-secrets = "0.30.0" +shuttle-serenity = "0.30.0" +shuttle-runtime = "0.30.0" +shuttle-shared-db = { version = "0.30.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index de2ba268..20813bb6 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-thruster = "0.30.0" +shuttle-runtime = "0.30.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 42d15093..82469eee 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.29.0", features = ["postgres"] } -shuttle-thruster = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-aws-rds = { version = "0.30.0", features = ["postgres"] } +shuttle-thruster = "0.30.0" +shuttle-runtime = "0.30.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index d28521f3..61ac084a 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.29.0" -shuttle-runtime = "0.29.0" +shuttle-tide = "0.30.0" +shuttle-runtime = "0.30.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index a48f15bf..9a24acf9 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.29.0", features = ["postgres"] } -shuttle-runtime = "0.29.0" -shuttle-tide = "0.29.0" +shuttle-aws-rds = { version = "0.30.0", features = ["postgres"] } +shuttle-runtime = "0.30.0" +shuttle-tide = "0.30.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 98b1c973..8cf8b33f 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.29.0" -shuttle-tower = "0.29.0" +shuttle-runtime = "0.30.0" +shuttle-tower = "0.30.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 4259f8fa..21b0f77a 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.29.0" +shuttle-actix-web = "0.30.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.29.0", default-features = false } +shuttle-runtime = { version = "0.30.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = "0.3.17" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 818d557c..38dbb45a 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.29.0" -shuttle-warp = "0.29.0" +shuttle-runtime = "0.30.0" +shuttle-warp = "0.30.0" tokio = "1.26.0" warp = "0.3.3" From 38c466c58c8dc922aa4ca8770dcc63cffba2dbef Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Mon, 30 Oct 2023 09:52:55 -0700 Subject: [PATCH 105/239] Add shuttle-template-actix (#106) * improvement-shuttle-template-actix * chore: fix missing link to repo * chore: fix mistakes noted in PR review --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4a954344..dad155ca 100644 --- a/README.md +++ b/README.md @@ -117,3 +117,4 @@ FRAMEWORK | [NAME](LINK_TO_REPO) | DESCRIPTION | `cargo shuttle init --from USER --------------|-----------------|-------------|---------------- Axum/Any | [Fullstack Rust](https://github.com/TylerBloom/shuttle-fullstack-rust-example) | A basic project template for fullstack Rust projects | `cargo shuttle init --from TylerBloom/shuttle-fullstack-rust-example` Axum/Yew | [Web App with Yew](https://github.com/sentinel1909/shuttle-template-yew) | A basic project template for a web app using the Yew framework | `cargo shuttle init --from sentinel1909/shuttle-template-yew` | +Actix Web | [Web API with Actix Web](https://github.com/sentinel1909/shuttle-template-actix) | A template for starting an API with Actix Web | `cargo shuttle init --from sentinel1909/shuttle-template-actix` From a7c7fe5af44faf89f1b120a166decdef73160eed Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 31 Oct 2023 07:58:48 +0000 Subject: [PATCH 106/239] Add GitHub OAuth community example (#107) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index dad155ca..aaa57a36 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,7 @@ FRAMEWORK | [NAME](LINK_TO_REPO) | DESCRIPTION | `cargo shuttle init --from USER **Framework** | **Name & Link** | **Description** | **Command** --------------|-----------------|-------------|---------------- +Actix Web/Any | [GitHub Login (OAuth)](https://github.com/robjtede/actix-examples-oauth-github) | Sample app demonstrating GitHub OAuth login using Actix Web | `cargo shuttle init --from robjtede/actix-examples-oauth-github` Axum/Any | [Fullstack Rust](https://github.com/TylerBloom/shuttle-fullstack-rust-example) | A basic project template for fullstack Rust projects | `cargo shuttle init --from TylerBloom/shuttle-fullstack-rust-example` Axum/Yew | [Web App with Yew](https://github.com/sentinel1909/shuttle-template-yew) | A basic project template for a web app using the Yew framework | `cargo shuttle init --from sentinel1909/shuttle-template-yew` | Actix Web | [Web API with Actix Web](https://github.com/sentinel1909/shuttle-template-actix) | A template for starting an API with Actix Web | `cargo shuttle init --from sentinel1909/shuttle-template-actix` From 7d5469f8b9d418fc04b1fa0716c955078fd38ffb Mon Sep 17 00:00:00 2001 From: Pieter Date: Thu, 2 Nov 2023 10:28:02 +0000 Subject: [PATCH 107/239] bug: revert turso version update (#108) --- axum/turso/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 390605b8..812309d8 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -8,7 +8,7 @@ axum = { version = "0.6.18" } shuttle-axum = { version = "0.30.0" } shuttle-runtime = { version = "0.30.0" } shuttle-turso = { version = "0.30.0" } -libsql-client = "0.32.0" +libsql-client = "0.31.0" tokio = { version = "1.26.0" } serde = { version = "1.0.164", features = ["derive"] } serde_json = "1.0.99" From 7226d98c19a5fa090de0e14eb596d73979a2186b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Thu, 2 Nov 2023 12:40:30 +0100 Subject: [PATCH 108/239] chore: v0.31.0 (#109) --- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 5 +++-- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 6 +++--- axum/postgres/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/static-next-server/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- axum/with-state/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 8 ++++---- next/hello-world/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 6 +++--- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 43 files changed, 105 insertions(+), 104 deletions(-) diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index 711953b3..a9723388 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.6.0" actix-session = { version = "0.8.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-actix-web = "0.31.0" +shuttle-runtime = "0.31.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 2d91cf7a..89a40f74 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-actix-web = "0.31.0" +shuttle-runtime = "0.31.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index b92883d2..21762172 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-actix-web = "0.31.0" +shuttle-runtime = "0.31.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.30.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.31.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index 3428c0d5..da7b4137 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-actix-web = "0.31.0" +shuttle-runtime = "0.31.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 50e777a7..17fee962 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-actix-web = "0.31.0" +shuttle-runtime = "0.31.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index b9b0e9f8..53793edb 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] axum = "0.6.20" -shuttle-axum = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-axum = "0.31.0" +shuttle-runtime = "0.31.0" tokio = "1.28.2" +tracing = "0.1.40" diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index ff7a7c8e..09f3cad5 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -9,7 +9,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-axum = "0.31.0" +shuttle-runtime = "0.31.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index aaa2cdb7..8ab0ef71 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.30.0" -shuttle-runtime = "0.30.0" -shuttle-metadata = "0.30.0" +shuttle-axum = "0.31.0" +shuttle-runtime = "0.31.0" +shuttle-metadata = "0.31.0" tokio = "1.28.2" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 1921bcfa..8407c869 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.6.18" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.30.0" -shuttle-runtime = "0.30.0" -shuttle-shared-db = { version = "0.30.0", features = ["postgres"] } +shuttle-axum = "0.31.0" +shuttle-runtime = "0.31.0" +shuttle-shared-db = { version = "0.31.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 2165648c..e4270ab6 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-axum = "0.31.0" +shuttle-runtime = "0.31.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 14c32caa..fa39e056 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,6 +7,6 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-axum = "0.31.0" +shuttle-runtime = "0.31.0" tokio = "1.26.0" diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 812309d8..c9aac898 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = { version = "0.6.18" } -shuttle-axum = { version = "0.30.0" } -shuttle-runtime = { version = "0.30.0" } -shuttle-turso = { version = "0.30.0" } +shuttle-axum = { version = "0.31.0" } +shuttle-runtime = { version = "0.31.0" } +shuttle-turso = { version = "0.31.0" } libsql-client = "0.31.0" tokio = { version = "1.26.0" } serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 78d66fb6..f7daf29e 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,7 +11,7 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-axum = "0.31.0" +shuttle-runtime = "0.31.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index e495f447..ac751ee4 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-axum = "0.31.0" +shuttle-runtime = "0.31.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index ff259f85..82650a5f 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.6.18" serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.30.0" -shuttle-axum = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-service = "0.31.0" +shuttle-axum = "0.31.0" +shuttle-runtime = "0.31.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 12ec690e..d99e6b2a 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.30.0" +shuttle-runtime = "0.31.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index b147d777..668dadec 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-persist = "0.31.0" +shuttle-runtime = "0.31.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index f4a68c82..6c0cf562 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,10 +16,10 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.30.0" -shuttle-runtime = "0.30.0" -shuttle-secrets = "0.30.0" -shuttle-shared-db = { version = "0.30.0", features = ["postgres"] } +shuttle-axum = "0.31.0" +shuttle-runtime = "0.31.0" +shuttle-secrets = "0.31.0" +shuttle-shared-db = { version = "0.31.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index 1edcd528..8a4b1640 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.30.0" +shuttle-next = "0.31.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index cb97cd35..948946bf 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,7 +15,7 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.6.18" dotenvy = "0.15.7" -shuttle-axum = "0.30.0" -shuttle-runtime = "0.30.0" -shuttle-secrets = "0.30.0" +shuttle-axum = "0.31.0" +shuttle-runtime = "0.31.0" +shuttle-secrets = "0.31.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index ba6c5417..fa7b4812 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-poem = "0.31.0" +shuttle-runtime = "0.31.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 7badd00c..7cbe98a1 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.30.0" -shuttle-shared-db = { version = "0.30.0", features = ["mongodb"] } -shuttle-runtime = "0.30.0" +shuttle-poem = "0.31.0" +shuttle-shared-db = { version = "0.31.0", features = ["mongodb"] } +shuttle-runtime = "0.31.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index e984145a..d13fe985 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.30.0" -shuttle-runtime = "0.30.0" -shuttle-shared-db = { version = "0.30.0", features = ["postgres"] } +shuttle-poem = "0.31.0" +shuttle-runtime = "0.31.0" +shuttle-shared-db = { version = "0.31.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 526d2040..476c5a10 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.30.0" -shuttle-runtime = "0.30.0" -shuttle-secrets = "0.30.0" +shuttle-poise = "0.31.0" +shuttle-runtime = "0.31.0" +shuttle-secrets = "0.31.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 9b6661ff..dd45c79d 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-rocket = "0.31.0" +shuttle-runtime = "0.31.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 250d17ee..97c3ed7f 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-rocket = "0.31.0" +shuttle-runtime = "0.31.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 616a1d3d..5544b305 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-rocket = "0.31.0" +shuttle-runtime = "0.31.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 5864e679..d6cd226b 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.30.0" -shuttle-rocket = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-persist = "0.31.0" +shuttle-rocket = "0.31.0" +shuttle-runtime = "0.31.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 783c75c1..a8cbd5bb 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.30.0", features = ["postgres"] } -shuttle-rocket = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-shared-db = { version = "0.31.0", features = ["postgres"] } +shuttle-rocket = "0.31.0" +shuttle-runtime = "0.31.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 46b3fc1e..eb1e6d91 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = "0.30.0" -shuttle-runtime = "0.30.0" -shuttle-secrets = "0.30.0" +shuttle-rocket = "0.31.0" +shuttle-runtime = "0.31.0" +shuttle-secrets = "0.31.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index 2b25ae7b..7f2cdeaf 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-rocket = "0.31.0" +shuttle-runtime = "0.31.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 659f89b1..577202ee 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-rocket = "0.31.0" +shuttle-runtime = "0.31.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.30.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.31.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index df12c71e..6abd65f2 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-rocket = "0.31.0" +shuttle-runtime = "0.31.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 462b7d41..85481e8f 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-salvo = "0.31.0" +shuttle-runtime = "0.31.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index bc51caac..250c780f 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-serenity = "0.31.0" +shuttle-runtime = "0.31.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.30.0" +shuttle-secrets = "0.31.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index fba7d624..f9c22d37 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.30.0" -shuttle-serenity = "0.30.0" -shuttle-runtime = "0.30.0" -shuttle-shared-db = { version = "0.30.0", features = ["postgres"] } +shuttle-secrets = "0.31.0" +shuttle-serenity = "0.31.0" +shuttle-runtime = "0.31.0" +shuttle-shared-db = { version = "0.31.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 20813bb6..03448ee4 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-thruster = "0.31.0" +shuttle-runtime = "0.31.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 82469eee..bf753500 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.30.0", features = ["postgres"] } -shuttle-thruster = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-aws-rds = { version = "0.31.0", features = ["postgres"] } +shuttle-thruster = "0.31.0" +shuttle-runtime = "0.31.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 61ac084a..f97ade7e 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.30.0" -shuttle-runtime = "0.30.0" +shuttle-tide = "0.31.0" +shuttle-runtime = "0.31.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index 9a24acf9..dded7ef6 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.30.0", features = ["postgres"] } -shuttle-runtime = "0.30.0" -shuttle-tide = "0.30.0" +shuttle-aws-rds = { version = "0.31.0", features = ["postgres"] } +shuttle-runtime = "0.31.0" +shuttle-tide = "0.31.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 8cf8b33f..4a23bd22 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.30.0" -shuttle-tower = "0.30.0" +shuttle-runtime = "0.31.0" +shuttle-tower = "0.31.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 21b0f77a..26de6a32 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.30.0" +shuttle-actix-web = "0.31.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.30.0", default-features = false } +shuttle-runtime = { version = "0.31.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = "0.3.17" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 38dbb45a..55daae53 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.30.0" -shuttle-warp = "0.30.0" +shuttle-runtime = "0.31.0" +shuttle-warp = "0.31.0" tokio = "1.26.0" warp = "0.3.3" From 25d87714416a4b32ad1e4204b310508cd49e94bc Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 8 Nov 2023 11:27:12 +0100 Subject: [PATCH 109/239] fix: migration filename (#110) --- axum/postgres/migrations/{schema.sql => 1_schema.sql} | 1 - 1 file changed, 1 deletion(-) rename axum/postgres/migrations/{schema.sql => 1_schema.sql} (99%) diff --git a/axum/postgres/migrations/schema.sql b/axum/postgres/migrations/1_schema.sql similarity index 99% rename from axum/postgres/migrations/schema.sql rename to axum/postgres/migrations/1_schema.sql index 99306c87..f6964250 100644 --- a/axum/postgres/migrations/schema.sql +++ b/axum/postgres/migrations/1_schema.sql @@ -4,4 +4,3 @@ CREATE TABLE IF NOT EXISTS todos ( id serial PRIMARY KEY, note TEXT NOT NULL ); - From 153a727d23a28d265856dc2d657e589a2404d2d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Thu, 9 Nov 2023 12:51:18 +0100 Subject: [PATCH 110/239] chore: v0.32.0 (#111) --- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 6 +++--- axum/postgres/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/static-next-server/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- axum/with-state/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 8 ++++---- next/hello-world/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 6 +++--- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 43 files changed, 104 insertions(+), 104 deletions(-) diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index a9723388..1b797eaa 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.6.0" actix-session = { version = "0.8.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-actix-web = "0.32.0" +shuttle-runtime = "0.32.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 89a40f74..4572ef26 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-actix-web = "0.32.0" +shuttle-runtime = "0.32.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 21762172..d8910537 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-actix-web = "0.32.0" +shuttle-runtime = "0.32.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.31.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.32.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index da7b4137..c0390292 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-actix-web = "0.32.0" +shuttle-runtime = "0.32.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 17fee962..018d2e86 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-actix-web = "0.32.0" +shuttle-runtime = "0.32.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 53793edb..20c044b1 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.6.20" -shuttle-axum = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-axum = "0.32.0" +shuttle-runtime = "0.32.0" tokio = "1.28.2" tracing = "0.1.40" diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index 09f3cad5..edf4aab1 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -9,7 +9,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-axum = "0.32.0" +shuttle-runtime = "0.32.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index 8ab0ef71..b730f6d2 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.31.0" -shuttle-runtime = "0.31.0" -shuttle-metadata = "0.31.0" +shuttle-axum = "0.32.0" +shuttle-runtime = "0.32.0" +shuttle-metadata = "0.32.0" tokio = "1.28.2" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 8407c869..10a9ca49 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.6.18" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.31.0" -shuttle-runtime = "0.31.0" -shuttle-shared-db = { version = "0.31.0", features = ["postgres"] } +shuttle-axum = "0.32.0" +shuttle-runtime = "0.32.0" +shuttle-shared-db = { version = "0.32.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index e4270ab6..a1357db6 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-axum = "0.32.0" +shuttle-runtime = "0.32.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index fa39e056..91e2bbf9 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,6 +7,6 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-axum = "0.32.0" +shuttle-runtime = "0.32.0" tokio = "1.26.0" diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index c9aac898..4737b2c5 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = { version = "0.6.18" } -shuttle-axum = { version = "0.31.0" } -shuttle-runtime = { version = "0.31.0" } -shuttle-turso = { version = "0.31.0" } +shuttle-axum = { version = "0.32.0" } +shuttle-runtime = { version = "0.32.0" } +shuttle-turso = { version = "0.32.0" } libsql-client = "0.31.0" tokio = { version = "1.26.0" } serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index f7daf29e..bb98d6f4 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,7 +11,7 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-axum = "0.32.0" +shuttle-runtime = "0.32.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index ac751ee4..953c5f45 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-axum = "0.32.0" +shuttle-runtime = "0.32.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 82650a5f..72b2b559 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.6.18" serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.31.0" -shuttle-axum = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-service = "0.32.0" +shuttle-axum = "0.32.0" +shuttle-runtime = "0.32.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index d99e6b2a..e951a580 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.31.0" +shuttle-runtime = "0.32.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index 668dadec..2199e998 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-persist = "0.32.0" +shuttle-runtime = "0.32.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 6c0cf562..b319612e 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,10 +16,10 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.31.0" -shuttle-runtime = "0.31.0" -shuttle-secrets = "0.31.0" -shuttle-shared-db = { version = "0.31.0", features = ["postgres"] } +shuttle-axum = "0.32.0" +shuttle-runtime = "0.32.0" +shuttle-secrets = "0.32.0" +shuttle-shared-db = { version = "0.32.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index 8a4b1640..05644432 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.31.0" +shuttle-next = "0.32.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 948946bf..3ce10e6b 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,7 +15,7 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.6.18" dotenvy = "0.15.7" -shuttle-axum = "0.31.0" -shuttle-runtime = "0.31.0" -shuttle-secrets = "0.31.0" +shuttle-axum = "0.32.0" +shuttle-runtime = "0.32.0" +shuttle-secrets = "0.32.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index fa7b4812..81d78e59 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-poem = "0.32.0" +shuttle-runtime = "0.32.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 7cbe98a1..40f138fa 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.31.0" -shuttle-shared-db = { version = "0.31.0", features = ["mongodb"] } -shuttle-runtime = "0.31.0" +shuttle-poem = "0.32.0" +shuttle-shared-db = { version = "0.32.0", features = ["mongodb"] } +shuttle-runtime = "0.32.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index d13fe985..06635976 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.31.0" -shuttle-runtime = "0.31.0" -shuttle-shared-db = { version = "0.31.0", features = ["postgres"] } +shuttle-poem = "0.32.0" +shuttle-runtime = "0.32.0" +shuttle-shared-db = { version = "0.32.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 476c5a10..5cfd790e 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.31.0" -shuttle-runtime = "0.31.0" -shuttle-secrets = "0.31.0" +shuttle-poise = "0.32.0" +shuttle-runtime = "0.32.0" +shuttle-secrets = "0.32.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index dd45c79d..e8a1ced2 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-rocket = "0.32.0" +shuttle-runtime = "0.32.0" rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 97c3ed7f..1ef59ff3 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-rocket = "0.32.0" +shuttle-runtime = "0.32.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 5544b305..36de65ae 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-rocket = "0.32.0" +shuttle-runtime = "0.32.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index d6cd226b..de6c5bf2 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.31.0" -shuttle-rocket = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-persist = "0.32.0" +shuttle-rocket = "0.32.0" +shuttle-runtime = "0.32.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index a8cbd5bb..349d27ee 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.31.0", features = ["postgres"] } -shuttle-rocket = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-shared-db = { version = "0.32.0", features = ["postgres"] } +shuttle-rocket = "0.32.0" +shuttle-runtime = "0.32.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index eb1e6d91..2eb6a454 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.2" -shuttle-rocket = "0.31.0" -shuttle-runtime = "0.31.0" -shuttle-secrets = "0.31.0" +shuttle-rocket = "0.32.0" +shuttle-runtime = "0.32.0" +shuttle-secrets = "0.32.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index 7f2cdeaf..ed55feb7 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" -shuttle-rocket = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-rocket = "0.32.0" +shuttle-runtime = "0.32.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 577202ee..8a16a6e9 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.2", features = ["json"] } -shuttle-rocket = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-rocket = "0.32.0" +shuttle-runtime = "0.32.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.31.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.32.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 6abd65f2..15fc6e23 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.2" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-rocket = "0.32.0" +shuttle-runtime = "0.32.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 85481e8f..0c367823 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-salvo = "0.32.0" +shuttle-runtime = "0.32.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 250c780f..de46121a 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-serenity = "0.32.0" +shuttle-runtime = "0.32.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.31.0" +shuttle-secrets = "0.32.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index f9c22d37..f75dcb79 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.31.0" -shuttle-serenity = "0.31.0" -shuttle-runtime = "0.31.0" -shuttle-shared-db = { version = "0.31.0", features = ["postgres"] } +shuttle-secrets = "0.32.0" +shuttle-serenity = "0.32.0" +shuttle-runtime = "0.32.0" +shuttle-shared-db = { version = "0.32.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 03448ee4..7ef09ca2 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-thruster = "0.32.0" +shuttle-runtime = "0.32.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index bf753500..4c69294f 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.31.0", features = ["postgres"] } -shuttle-thruster = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-aws-rds = { version = "0.32.0", features = ["postgres"] } +shuttle-thruster = "0.32.0" +shuttle-runtime = "0.32.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index f97ade7e..dd02fc24 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.31.0" -shuttle-runtime = "0.31.0" +shuttle-tide = "0.32.0" +shuttle-runtime = "0.32.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index dded7ef6..2631df84 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.31.0", features = ["postgres"] } -shuttle-runtime = "0.31.0" -shuttle-tide = "0.31.0" +shuttle-aws-rds = { version = "0.32.0", features = ["postgres"] } +shuttle-runtime = "0.32.0" +shuttle-tide = "0.32.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 4a23bd22..e1c4f67c 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.31.0" -shuttle-tower = "0.31.0" +shuttle-runtime = "0.32.0" +shuttle-tower = "0.32.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 26de6a32..4f155a29 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.31.0" +shuttle-actix-web = "0.32.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.31.0", default-features = false } +shuttle-runtime = { version = "0.32.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = "0.3.17" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 55daae53..6a90d592 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.31.0" -shuttle-warp = "0.31.0" +shuttle-runtime = "0.32.0" +shuttle-warp = "0.32.0" tokio = "1.26.0" warp = "0.3.3" From 281b8a0c803335d062e4c2813a19fbbcd7a76b62 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Wed, 15 Nov 2023 03:42:45 -0800 Subject: [PATCH 111/239] improvement: rocket 0.5.0-rc4 (#112) --- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 2 +- rocket/jwt-authentication/Cargo.toml | 2 +- rocket/jwt-authentication/src/claims.rs | 4 ++-- rocket/persist/Cargo.toml | 2 +- rocket/persist/src/main.rs | 4 ++-- rocket/postgres/Cargo.toml | 2 +- rocket/postgres/src/main.rs | 4 ++-- rocket/secrets/Cargo.toml | 2 +- rocket/static-files/Cargo.toml | 2 +- rocket/url-shortener/Cargo.toml | 2 +- rocket/workspace/hello-world/Cargo.toml | 2 +- 12 files changed, 16 insertions(+), 16 deletions(-) diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index e8a1ced2..ed2a2b07 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -4,8 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -rocket = "0.5.0-rc.2" +rocket = "0.5.0-rc.4" shuttle-rocket = "0.32.0" shuttle-runtime = "0.32.0" -rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } +rocket_dyn_templates = { version = "0.1.0-rc.4", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 1ef59ff3..de27d0a9 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -rocket = "0.5.0-rc.2" +rocket = "0.5.0-rc.4" shuttle-rocket = "0.32.0" shuttle-runtime = "0.32.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 36de65ae..01674a0b 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" chrono = "0.4.23" jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" -rocket = { version = "0.5.0-rc.2", features = ["json"] } +rocket = { version = "0.5.0-rc.4", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } shuttle-rocket = "0.32.0" shuttle-runtime = "0.32.0" diff --git a/rocket/jwt-authentication/src/claims.rs b/rocket/jwt-authentication/src/claims.rs index bce84a3f..dde34121 100644 --- a/rocket/jwt-authentication/src/claims.rs +++ b/rocket/jwt-authentication/src/claims.rs @@ -44,9 +44,9 @@ impl<'r> FromRequest<'r> for Claims { async fn from_request(request: &'r rocket::Request<'_>) -> Outcome { match request.headers().get_one(AUTHORIZATION) { - None => Outcome::Failure((Status::Forbidden, AuthenticationError::Missing)), + None => Outcome::Error((Status::Forbidden, AuthenticationError::Missing)), Some(value) => match Claims::from_authorization(value) { - Err(e) => Outcome::Failure((Status::Forbidden, e)), + Err(e) => Outcome::Error((Status::Forbidden, e)), Ok(claims) => Outcome::Success(claims), }, } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index de6c5bf2..e96eff44 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -rocket = { version = "0.5.0-rc.2", features = ["json"] } +rocket = { version = "0.5.0-rc.4", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } shuttle-persist = "0.32.0" shuttle-rocket = "0.32.0" diff --git a/rocket/persist/src/main.rs b/rocket/persist/src/main.rs index 52befd69..db0bbb6b 100644 --- a/rocket/persist/src/main.rs +++ b/rocket/persist/src/main.rs @@ -34,7 +34,7 @@ async fn add( format!("weather_{}", &weather.date.as_str()).as_str(), weather.clone(), ) - .map_err(|e| BadRequest(Some(e.to_string())))?; + .map_err(|e| BadRequest(e.to_string()))?; Ok(Json(weather)) } @@ -46,7 +46,7 @@ async fn retrieve( let weather = state .persist .load::(format!("weather_{}", &date).as_str()) - .map_err(|e| BadRequest(Some(e.to_string())))?; + .map_err(|e| BadRequest(e.to_string()))?; Ok(Json(weather)) } diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 349d27ee..14fc471d 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -rocket = { version = "0.5.0-rc.2", features = ["json"] } +rocket = { version = "0.5.0-rc.4", features = ["json"] } serde = "1.0.148" shuttle-shared-db = { version = "0.32.0", features = ["postgres"] } shuttle-rocket = "0.32.0" diff --git a/rocket/postgres/src/main.rs b/rocket/postgres/src/main.rs index c7a3553b..7b851bce 100644 --- a/rocket/postgres/src/main.rs +++ b/rocket/postgres/src/main.rs @@ -14,7 +14,7 @@ async fn retrieve(id: i32, state: &State) -> Result, BadRequ .bind(id) .fetch_one(&state.pool) .await - .map_err(|e| BadRequest(Some(e.to_string())))?; + .map_err(|e| BadRequest(e.to_string()))?; Ok(Json(todo)) } @@ -28,7 +28,7 @@ async fn add( .bind(&data.note) .fetch_one(&state.pool) .await - .map_err(|e| BadRequest(Some(e.to_string())))?; + .map_err(|e| BadRequest(e.to_string()))?; Ok(Json(todo)) } diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 2eb6a454..fcc632b1 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -rocket = "0.5.0-rc.2" +rocket = "0.5.0-rc.4" shuttle-rocket = "0.32.0" shuttle-runtime = "0.32.0" shuttle-secrets = "0.32.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index ed55feb7..5f6bf5e8 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -rocket = "0.5.0-rc.2" +rocket = "0.5.0-rc.4" shuttle-rocket = "0.32.0" shuttle-runtime = "0.32.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 8a16a6e9..4754c6ad 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] nanoid = "0.4.0" -rocket = { version = "0.5.0-rc.2", features = ["json"] } +rocket = { version = "0.5.0-rc.4", features = ["json"] } shuttle-rocket = "0.32.0" shuttle-runtime = "0.32.0" serde = "1.0.148" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 15fc6e23..ceac9e12 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -rocket = "0.5.0-rc.2" +rocket = "0.5.0-rc.4" shared = { path = "../shared", version = "0.1.0" } shuttle-rocket = "0.32.0" shuttle-runtime = "0.32.0" From e7e2d4f7e2588dce8ba5e85e8d8b7b5c5d1a7af1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Thu, 16 Nov 2023 13:52:47 +0100 Subject: [PATCH 112/239] chore: v0.33.0 (#113) --- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 6 +++--- axum/postgres/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/static-next-server/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- axum/with-state/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 8 ++++---- next/hello-world/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 6 +++--- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 43 files changed, 104 insertions(+), 104 deletions(-) diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index 1b797eaa..df00fd2e 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.6.0" actix-session = { version = "0.8.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-actix-web = "0.33.0" +shuttle-runtime = "0.33.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 4572ef26..7294df8f 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-actix-web = "0.33.0" +shuttle-runtime = "0.33.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index d8910537..65fe8ca8 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-actix-web = "0.33.0" +shuttle-runtime = "0.33.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.32.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.33.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index c0390292..fa417e85 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-actix-web = "0.33.0" +shuttle-runtime = "0.33.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 018d2e86..1c92c57d 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-actix-web = "0.33.0" +shuttle-runtime = "0.33.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 20c044b1..656c80b7 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.6.20" -shuttle-axum = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-axum = "0.33.0" +shuttle-runtime = "0.33.0" tokio = "1.28.2" tracing = "0.1.40" diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index edf4aab1..8c4553e1 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -9,7 +9,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-axum = "0.33.0" +shuttle-runtime = "0.33.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index b730f6d2..a35af4fc 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.32.0" -shuttle-runtime = "0.32.0" -shuttle-metadata = "0.32.0" +shuttle-axum = "0.33.0" +shuttle-runtime = "0.33.0" +shuttle-metadata = "0.33.0" tokio = "1.28.2" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 10a9ca49..e9abf393 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.6.18" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.32.0" -shuttle-runtime = "0.32.0" -shuttle-shared-db = { version = "0.32.0", features = ["postgres"] } +shuttle-axum = "0.33.0" +shuttle-runtime = "0.33.0" +shuttle-shared-db = { version = "0.33.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index a1357db6..ef225c47 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-axum = "0.33.0" +shuttle-runtime = "0.33.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 91e2bbf9..67d3a47c 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,6 +7,6 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-axum = "0.33.0" +shuttle-runtime = "0.33.0" tokio = "1.26.0" diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 4737b2c5..93c4bc51 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = { version = "0.6.18" } -shuttle-axum = { version = "0.32.0" } -shuttle-runtime = { version = "0.32.0" } -shuttle-turso = { version = "0.32.0" } +shuttle-axum = { version = "0.33.0" } +shuttle-runtime = { version = "0.33.0" } +shuttle-turso = { version = "0.33.0" } libsql-client = "0.31.0" tokio = { version = "1.26.0" } serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index bb98d6f4..dcba508b 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,7 +11,7 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-axum = "0.33.0" +shuttle-runtime = "0.33.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index 953c5f45..3f7b662b 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-axum = "0.33.0" +shuttle-runtime = "0.33.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 72b2b559..5743b76b 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.6.18" serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.32.0" -shuttle-axum = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-service = "0.33.0" +shuttle-axum = "0.33.0" +shuttle-runtime = "0.33.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index e951a580..5df3070e 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.32.0" +shuttle-runtime = "0.33.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index 2199e998..d8014597 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-persist = "0.33.0" +shuttle-runtime = "0.33.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index b319612e..bece3f2a 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,10 +16,10 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.32.0" -shuttle-runtime = "0.32.0" -shuttle-secrets = "0.32.0" -shuttle-shared-db = { version = "0.32.0", features = ["postgres"] } +shuttle-axum = "0.33.0" +shuttle-runtime = "0.33.0" +shuttle-secrets = "0.33.0" +shuttle-shared-db = { version = "0.33.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index 05644432..8ec2b2bb 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.32.0" +shuttle-next = "0.33.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 3ce10e6b..339825d6 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,7 +15,7 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.6.18" dotenvy = "0.15.7" -shuttle-axum = "0.32.0" -shuttle-runtime = "0.32.0" -shuttle-secrets = "0.32.0" +shuttle-axum = "0.33.0" +shuttle-runtime = "0.33.0" +shuttle-secrets = "0.33.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 81d78e59..acb5932a 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-poem = "0.33.0" +shuttle-runtime = "0.33.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 40f138fa..eb4bc961 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.32.0" -shuttle-shared-db = { version = "0.32.0", features = ["mongodb"] } -shuttle-runtime = "0.32.0" +shuttle-poem = "0.33.0" +shuttle-shared-db = { version = "0.33.0", features = ["mongodb"] } +shuttle-runtime = "0.33.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 06635976..9877ce4c 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.32.0" -shuttle-runtime = "0.32.0" -shuttle-shared-db = { version = "0.32.0", features = ["postgres"] } +shuttle-poem = "0.33.0" +shuttle-runtime = "0.33.0" +shuttle-shared-db = { version = "0.33.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 5cfd790e..d8c17500 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.32.0" -shuttle-runtime = "0.32.0" -shuttle-secrets = "0.32.0" +shuttle-poise = "0.33.0" +shuttle-runtime = "0.33.0" +shuttle-secrets = "0.33.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index ed2a2b07..65d1e3bf 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.4" -shuttle-rocket = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-rocket = "0.33.0" +shuttle-runtime = "0.33.0" rocket_dyn_templates = { version = "0.1.0-rc.4", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index de27d0a9..06ed4880 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.4" -shuttle-rocket = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-rocket = "0.33.0" +shuttle-runtime = "0.33.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 01674a0b..4acbf210 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0-rc.4", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-rocket = "0.33.0" +shuttle-runtime = "0.33.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index e96eff44..bc242ed0 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.4", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.32.0" -shuttle-rocket = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-persist = "0.33.0" +shuttle-rocket = "0.33.0" +shuttle-runtime = "0.33.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 14fc471d..2531e35f 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0-rc.4", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.32.0", features = ["postgres"] } -shuttle-rocket = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-shared-db = { version = "0.33.0", features = ["postgres"] } +shuttle-rocket = "0.33.0" +shuttle-runtime = "0.33.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index fcc632b1..6cd96913 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0-rc.4" -shuttle-rocket = "0.32.0" -shuttle-runtime = "0.32.0" -shuttle-secrets = "0.32.0" +shuttle-rocket = "0.33.0" +shuttle-runtime = "0.33.0" +shuttle-secrets = "0.33.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index 5f6bf5e8..6b51c12a 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.4" -shuttle-rocket = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-rocket = "0.33.0" +shuttle-runtime = "0.33.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 4754c6ad..03869542 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0-rc.4", features = ["json"] } -shuttle-rocket = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-rocket = "0.33.0" +shuttle-runtime = "0.33.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.32.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.33.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index ceac9e12..675ee7cf 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0-rc.4" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-rocket = "0.33.0" +shuttle-runtime = "0.33.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 0c367823..2e19d7a8 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-salvo = "0.33.0" +shuttle-runtime = "0.33.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index de46121a..d0e7322c 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-serenity = "0.33.0" +shuttle-runtime = "0.33.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.32.0" +shuttle-secrets = "0.33.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index f75dcb79..f2e71043 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.32.0" -shuttle-serenity = "0.32.0" -shuttle-runtime = "0.32.0" -shuttle-shared-db = { version = "0.32.0", features = ["postgres"] } +shuttle-secrets = "0.33.0" +shuttle-serenity = "0.33.0" +shuttle-runtime = "0.33.0" +shuttle-shared-db = { version = "0.33.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 7ef09ca2..3186dce2 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-thruster = "0.33.0" +shuttle-runtime = "0.33.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 4c69294f..3308a689 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.32.0", features = ["postgres"] } -shuttle-thruster = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-aws-rds = { version = "0.33.0", features = ["postgres"] } +shuttle-thruster = "0.33.0" +shuttle-runtime = "0.33.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index dd02fc24..8fe08544 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.32.0" -shuttle-runtime = "0.32.0" +shuttle-tide = "0.33.0" +shuttle-runtime = "0.33.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index 2631df84..7429d08e 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.32.0", features = ["postgres"] } -shuttle-runtime = "0.32.0" -shuttle-tide = "0.32.0" +shuttle-aws-rds = { version = "0.33.0", features = ["postgres"] } +shuttle-runtime = "0.33.0" +shuttle-tide = "0.33.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index e1c4f67c..7f487492 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.32.0" -shuttle-tower = "0.32.0" +shuttle-runtime = "0.33.0" +shuttle-tower = "0.33.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 4f155a29..91872a15 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.32.0" +shuttle-actix-web = "0.33.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.32.0", default-features = false } +shuttle-runtime = { version = "0.33.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = "0.3.17" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 6a90d592..4723fd59 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.32.0" -shuttle-warp = "0.32.0" +shuttle-runtime = "0.33.0" +shuttle-warp = "0.33.0" tokio = "1.26.0" warp = "0.3.3" From f8da10517681317b66c919d35e3f8110747d4a56 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Thu, 23 Nov 2023 06:10:06 -0800 Subject: [PATCH 113/239] improvement: rocket 0.5.0 stable (#114) --- rocket/dyn-templates/Cargo.toml | 2 +- rocket/hello-world/Cargo.toml | 2 +- rocket/jwt-authentication/Cargo.toml | 2 +- rocket/persist/Cargo.toml | 2 +- rocket/postgres/Cargo.toml | 2 +- rocket/secrets/Cargo.toml | 2 +- rocket/static-files/Cargo.toml | 2 +- rocket/url-shortener/Cargo.toml | 2 +- rocket/workspace/hello-world/Cargo.toml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 65d1e3bf..5c4881fb 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -rocket = "0.5.0-rc.4" +rocket = "0.5.0" shuttle-rocket = "0.33.0" shuttle-runtime = "0.33.0" rocket_dyn_templates = { version = "0.1.0-rc.4", features = ["handlebars"] } diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 06ed4880..25ad1c25 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -rocket = "0.5.0-rc.4" +rocket = "0.5.0" shuttle-rocket = "0.33.0" shuttle-runtime = "0.33.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 4acbf210..8864027b 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" chrono = "0.4.23" jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" -rocket = { version = "0.5.0-rc.4", features = ["json"] } +rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } shuttle-rocket = "0.33.0" shuttle-runtime = "0.33.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index bc242ed0..556c710d 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -rocket = { version = "0.5.0-rc.4", features = ["json"] } +rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } shuttle-persist = "0.33.0" shuttle-rocket = "0.33.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 2531e35f..a65b0cb0 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -rocket = { version = "0.5.0-rc.4", features = ["json"] } +rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" shuttle-shared-db = { version = "0.33.0", features = ["postgres"] } shuttle-rocket = "0.33.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 6cd96913..ad06db9d 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -rocket = "0.5.0-rc.4" +rocket = "0.5.0" shuttle-rocket = "0.33.0" shuttle-runtime = "0.33.0" shuttle-secrets = "0.33.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index 6b51c12a..293c6b87 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -rocket = "0.5.0-rc.4" +rocket = "0.5.0" shuttle-rocket = "0.33.0" shuttle-runtime = "0.33.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 03869542..b121a865 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] nanoid = "0.4.0" -rocket = { version = "0.5.0-rc.4", features = ["json"] } +rocket = { version = "0.5.0", features = ["json"] } shuttle-rocket = "0.33.0" shuttle-runtime = "0.33.0" serde = "1.0.148" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 675ee7cf..9eb5a214 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -rocket = "0.5.0-rc.4" +rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } shuttle-rocket = "0.33.0" shuttle-runtime = "0.33.0" From 216aa7fe3d667be7cd99816eb382bd12974eba00 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Thu, 23 Nov 2023 15:13:42 +0100 Subject: [PATCH 114/239] chore: v0.34.0 (#115) --- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 6 +++--- axum/postgres/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/static-next-server/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- axum/with-state/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 8 ++++---- next/hello-world/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 6 +++--- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 43 files changed, 104 insertions(+), 104 deletions(-) diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index df00fd2e..a7892b47 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.6.0" actix-session = { version = "0.8.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-actix-web = "0.34.0" +shuttle-runtime = "0.34.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 7294df8f..332e21ea 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-actix-web = "0.34.0" +shuttle-runtime = "0.34.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 65fe8ca8..1e045607 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-actix-web = "0.34.0" +shuttle-runtime = "0.34.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.33.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.34.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index fa417e85..13dffcb8 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-actix-web = "0.34.0" +shuttle-runtime = "0.34.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 1c92c57d..d24e5b42 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-actix-web = "0.34.0" +shuttle-runtime = "0.34.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 656c80b7..3a7296d8 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.6.20" -shuttle-axum = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-axum = "0.34.0" +shuttle-runtime = "0.34.0" tokio = "1.28.2" tracing = "0.1.40" diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index 8c4553e1..fd0c8eac 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -9,7 +9,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-axum = "0.34.0" +shuttle-runtime = "0.34.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index a35af4fc..ce54a236 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.33.0" -shuttle-runtime = "0.33.0" -shuttle-metadata = "0.33.0" +shuttle-axum = "0.34.0" +shuttle-runtime = "0.34.0" +shuttle-metadata = "0.34.0" tokio = "1.28.2" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index e9abf393..80ab1cd3 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.6.18" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.33.0" -shuttle-runtime = "0.33.0" -shuttle-shared-db = { version = "0.33.0", features = ["postgres"] } +shuttle-axum = "0.34.0" +shuttle-runtime = "0.34.0" +shuttle-shared-db = { version = "0.34.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index ef225c47..0d091aa3 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-axum = "0.34.0" +shuttle-runtime = "0.34.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 67d3a47c..614e2636 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,6 +7,6 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-axum = "0.34.0" +shuttle-runtime = "0.34.0" tokio = "1.26.0" diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 93c4bc51..2133545d 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = { version = "0.6.18" } -shuttle-axum = { version = "0.33.0" } -shuttle-runtime = { version = "0.33.0" } -shuttle-turso = { version = "0.33.0" } +shuttle-axum = { version = "0.34.0" } +shuttle-runtime = { version = "0.34.0" } +shuttle-turso = { version = "0.34.0" } libsql-client = "0.31.0" tokio = { version = "1.26.0" } serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index dcba508b..0cc0a6c3 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,7 +11,7 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-axum = "0.34.0" +shuttle-runtime = "0.34.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index 3f7b662b..f8e2cd11 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-axum = "0.34.0" +shuttle-runtime = "0.34.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 5743b76b..412ebc1f 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.6.18" serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.33.0" -shuttle-axum = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-service = "0.34.0" +shuttle-axum = "0.34.0" +shuttle-runtime = "0.34.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 5df3070e..458487d3 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.33.0" +shuttle-runtime = "0.34.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index d8014597..a8a104f7 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-persist = "0.34.0" +shuttle-runtime = "0.34.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index bece3f2a..15452024 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,10 +16,10 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.33.0" -shuttle-runtime = "0.33.0" -shuttle-secrets = "0.33.0" -shuttle-shared-db = { version = "0.33.0", features = ["postgres"] } +shuttle-axum = "0.34.0" +shuttle-runtime = "0.34.0" +shuttle-secrets = "0.34.0" +shuttle-shared-db = { version = "0.34.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index 8ec2b2bb..4cae9b8d 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.33.0" +shuttle-next = "0.34.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 339825d6..2e489031 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,7 +15,7 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.6.18" dotenvy = "0.15.7" -shuttle-axum = "0.33.0" -shuttle-runtime = "0.33.0" -shuttle-secrets = "0.33.0" +shuttle-axum = "0.34.0" +shuttle-runtime = "0.34.0" +shuttle-secrets = "0.34.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index acb5932a..7a8212bc 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-poem = "0.34.0" +shuttle-runtime = "0.34.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index eb4bc961..9437cc50 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.33.0" -shuttle-shared-db = { version = "0.33.0", features = ["mongodb"] } -shuttle-runtime = "0.33.0" +shuttle-poem = "0.34.0" +shuttle-shared-db = { version = "0.34.0", features = ["mongodb"] } +shuttle-runtime = "0.34.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 9877ce4c..dd8ea309 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.33.0" -shuttle-runtime = "0.33.0" -shuttle-shared-db = { version = "0.33.0", features = ["postgres"] } +shuttle-poem = "0.34.0" +shuttle-runtime = "0.34.0" +shuttle-shared-db = { version = "0.34.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index d8c17500..7d173e2c 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.33.0" -shuttle-runtime = "0.33.0" -shuttle-secrets = "0.33.0" +shuttle-poise = "0.34.0" +shuttle-runtime = "0.34.0" +shuttle-secrets = "0.34.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 5c4881fb..7d83f102 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-rocket = "0.34.0" +shuttle-runtime = "0.34.0" rocket_dyn_templates = { version = "0.1.0-rc.4", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 25ad1c25..947c5097 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-rocket = "0.34.0" +shuttle-runtime = "0.34.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 8864027b..4d619ebd 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-rocket = "0.34.0" +shuttle-runtime = "0.34.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 556c710d..f96d8726 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.33.0" -shuttle-rocket = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-persist = "0.34.0" +shuttle-rocket = "0.34.0" +shuttle-runtime = "0.34.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index a65b0cb0..0833304b 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.33.0", features = ["postgres"] } -shuttle-rocket = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-shared-db = { version = "0.34.0", features = ["postgres"] } +shuttle-rocket = "0.34.0" +shuttle-runtime = "0.34.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index ad06db9d..e6115857 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.33.0" -shuttle-runtime = "0.33.0" -shuttle-secrets = "0.33.0" +shuttle-rocket = "0.34.0" +shuttle-runtime = "0.34.0" +shuttle-secrets = "0.34.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index 293c6b87..452f2404 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-rocket = "0.34.0" +shuttle-runtime = "0.34.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index b121a865..7c55f681 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0", features = ["json"] } -shuttle-rocket = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-rocket = "0.34.0" +shuttle-runtime = "0.34.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.33.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.34.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 9eb5a214..b43cad13 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-rocket = "0.34.0" +shuttle-runtime = "0.34.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 2e19d7a8..327bcb76 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-salvo = "0.34.0" +shuttle-runtime = "0.34.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index d0e7322c..14ca92aa 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-serenity = "0.34.0" +shuttle-runtime = "0.34.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.33.0" +shuttle-secrets = "0.34.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index f2e71043..94e5cd45 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.33.0" -shuttle-serenity = "0.33.0" -shuttle-runtime = "0.33.0" -shuttle-shared-db = { version = "0.33.0", features = ["postgres"] } +shuttle-secrets = "0.34.0" +shuttle-serenity = "0.34.0" +shuttle-runtime = "0.34.0" +shuttle-shared-db = { version = "0.34.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 3186dce2..b8786ba3 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-thruster = "0.34.0" +shuttle-runtime = "0.34.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 3308a689..4346da36 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.33.0", features = ["postgres"] } -shuttle-thruster = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-aws-rds = { version = "0.34.0", features = ["postgres"] } +shuttle-thruster = "0.34.0" +shuttle-runtime = "0.34.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 8fe08544..64e33ae3 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.33.0" -shuttle-runtime = "0.33.0" +shuttle-tide = "0.34.0" +shuttle-runtime = "0.34.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index 7429d08e..ed791380 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.33.0", features = ["postgres"] } -shuttle-runtime = "0.33.0" -shuttle-tide = "0.33.0" +shuttle-aws-rds = { version = "0.34.0", features = ["postgres"] } +shuttle-runtime = "0.34.0" +shuttle-tide = "0.34.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 7f487492..a85af4a1 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.33.0" -shuttle-tower = "0.33.0" +shuttle-runtime = "0.34.0" +shuttle-tower = "0.34.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 91872a15..7cf7063c 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.33.0" +shuttle-actix-web = "0.34.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.33.0", default-features = false } +shuttle-runtime = { version = "0.34.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = "0.3.17" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 4723fd59..7b65d7d1 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.33.0" -shuttle-warp = "0.33.0" +shuttle-runtime = "0.34.0" +shuttle-warp = "0.34.0" tokio = "1.26.0" warp = "0.3.3" From 1205ee6b72f07d93523ad058e510b42f6a9bf8eb Mon Sep 17 00:00:00 2001 From: Mahmoud Date: Fri, 24 Nov 2023 19:54:16 +0200 Subject: [PATCH 115/239] add a full stack CRUD template using Yew, Rocket, and Sled (#116) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index aaa57a36..ac5f4364 100644 --- a/README.md +++ b/README.md @@ -119,3 +119,4 @@ Actix Web/Any | [GitHub Login (OAuth)](https://github.com/robjtede/actix-example Axum/Any | [Fullstack Rust](https://github.com/TylerBloom/shuttle-fullstack-rust-example) | A basic project template for fullstack Rust projects | `cargo shuttle init --from TylerBloom/shuttle-fullstack-rust-example` Axum/Yew | [Web App with Yew](https://github.com/sentinel1909/shuttle-template-yew) | A basic project template for a web app using the Yew framework | `cargo shuttle init --from sentinel1909/shuttle-template-yew` | Actix Web | [Web API with Actix Web](https://github.com/sentinel1909/shuttle-template-actix) | A template for starting an API with Actix Web | `cargo shuttle init --from sentinel1909/shuttle-template-actix` +Rocket/Yew | [Web API with Rocket and Sled](https://github.com/wiseaidev/rocket-yew-starter-pack) | A Full Stack CRUD template for starting an API with [Rocket](https://github.com/rwf2/Rocket), [Sled](https://github.com/spacejam/sled) and [Yew](https://github.com/yewstack/yew) | `cargo shuttle init --from wiseaidev/rocket-yew-starter-pack` \ No newline at end of file From 4acc85fde0a367a8bd9e4cad4980a2caa6b2e6e0 Mon Sep 17 00:00:00 2001 From: Joshua Mo <102877324+joshua-mo-143@users.noreply.github.com> Date: Mon, 27 Nov 2023 22:25:50 +0000 Subject: [PATCH 116/239] docs: add Bevy example (#102) --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ac5f4364..e53aab6e 100644 --- a/README.md +++ b/README.md @@ -118,5 +118,6 @@ FRAMEWORK | [NAME](LINK_TO_REPO) | DESCRIPTION | `cargo shuttle init --from USER Actix Web/Any | [GitHub Login (OAuth)](https://github.com/robjtede/actix-examples-oauth-github) | Sample app demonstrating GitHub OAuth login using Actix Web | `cargo shuttle init --from robjtede/actix-examples-oauth-github` Axum/Any | [Fullstack Rust](https://github.com/TylerBloom/shuttle-fullstack-rust-example) | A basic project template for fullstack Rust projects | `cargo shuttle init --from TylerBloom/shuttle-fullstack-rust-example` Axum/Yew | [Web App with Yew](https://github.com/sentinel1909/shuttle-template-yew) | A basic project template for a web app using the Yew framework | `cargo shuttle init --from sentinel1909/shuttle-template-yew` | +Axum/Bevy | [Shuttle with Bevy](https://github.com/joshua-mo-143/shuttle-bevy-ex) | A basic project template for a compiled Bevy WASM "Hello World" webpage | `cargo shuttle init --from joshua-mo-143/shuttle-bevy-ex` | Actix Web | [Web API with Actix Web](https://github.com/sentinel1909/shuttle-template-actix) | A template for starting an API with Actix Web | `cargo shuttle init --from sentinel1909/shuttle-template-actix` -Rocket/Yew | [Web API with Rocket and Sled](https://github.com/wiseaidev/rocket-yew-starter-pack) | A Full Stack CRUD template for starting an API with [Rocket](https://github.com/rwf2/Rocket), [Sled](https://github.com/spacejam/sled) and [Yew](https://github.com/yewstack/yew) | `cargo shuttle init --from wiseaidev/rocket-yew-starter-pack` \ No newline at end of file +Rocket/Yew | [Web API with Rocket and Sled](https://github.com/wiseaidev/rocket-yew-starter-pack) | A Full Stack CRUD template for starting an API with [Rocket](https://github.com/rwf2/Rocket), [Sled](https://github.com/spacejam/sled) and [Yew](https://github.com/yewstack/yew) | `cargo shuttle init --from wiseaidev/rocket-yew-starter-pack` From 20886eafa7c4f03a7b7f50f18c850956d3a30d55 Mon Sep 17 00:00:00 2001 From: Joshua Mo <102877324+joshua-mo-143@users.noreply.github.com> Date: Mon, 27 Nov 2023 22:58:20 +0000 Subject: [PATCH 117/239] fix: allow template to be used with --from flag (#117) --- fullstack-templates/saas/Cargo.toml | 2 ++ fullstack-templates/saas/{backend => }/Shuttle.toml | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 fullstack-templates/saas/Cargo.toml rename fullstack-templates/saas/{backend => }/Shuttle.toml (54%) diff --git a/fullstack-templates/saas/Cargo.toml b/fullstack-templates/saas/Cargo.toml new file mode 100644 index 00000000..ac13fe2f --- /dev/null +++ b/fullstack-templates/saas/Cargo.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["backend"] diff --git a/fullstack-templates/saas/backend/Shuttle.toml b/fullstack-templates/saas/Shuttle.toml similarity index 54% rename from fullstack-templates/saas/backend/Shuttle.toml rename to fullstack-templates/saas/Shuttle.toml index ccf634ae..411cf936 100644 --- a/fullstack-templates/saas/backend/Shuttle.toml +++ b/fullstack-templates/saas/Shuttle.toml @@ -1,4 +1,3 @@ -name = "fullstack-saas" assets = [ "public/*", ] From 58bdd5e8b6d1fe1500b11c0364d8fc2bc332b042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Thu, 7 Dec 2023 15:16:52 +0100 Subject: [PATCH 118/239] chore: v0.35.0 (#118) --- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 6 +++--- axum/postgres/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/static-next-server/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- axum/with-state/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 8 ++++---- next/hello-world/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 6 +++--- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 43 files changed, 104 insertions(+), 104 deletions(-) diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index a7892b47..aa557360 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.6.0" actix-session = { version = "0.8.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-actix-web = "0.35.0" +shuttle-runtime = "0.35.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 332e21ea..bfdf9184 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-actix-web = "0.35.0" +shuttle-runtime = "0.35.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 1e045607..db2b0e17 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-actix-web = "0.35.0" +shuttle-runtime = "0.35.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.34.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.35.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index 13dffcb8..ebc1922b 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-actix-web = "0.35.0" +shuttle-runtime = "0.35.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index d24e5b42..21f3d01f 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-actix-web = "0.35.0" +shuttle-runtime = "0.35.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 3a7296d8..77d2ebd4 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.6.20" -shuttle-axum = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-axum = "0.35.0" +shuttle-runtime = "0.35.0" tokio = "1.28.2" tracing = "0.1.40" diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index fd0c8eac..9ae088f9 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -9,7 +9,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-axum = "0.35.0" +shuttle-runtime = "0.35.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index ce54a236..3434034b 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.6.18" -shuttle-axum = "0.34.0" -shuttle-runtime = "0.34.0" -shuttle-metadata = "0.34.0" +shuttle-axum = "0.35.0" +shuttle-runtime = "0.35.0" +shuttle-metadata = "0.35.0" tokio = "1.28.2" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 80ab1cd3..838cd0c0 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.6.18" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.34.0" -shuttle-runtime = "0.34.0" -shuttle-shared-db = { version = "0.34.0", features = ["postgres"] } +shuttle-axum = "0.35.0" +shuttle-runtime = "0.35.0" +shuttle-shared-db = { version = "0.35.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 0d091aa3..c1e717c7 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.6.18" -shuttle-axum = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-axum = "0.35.0" +shuttle-runtime = "0.35.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 614e2636..7c4421e6 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -7,6 +7,6 @@ publish = false [dependencies] axum = "0.6.10" axum-extra = { version = "0.4.2", features = ["spa"] } -shuttle-axum = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-axum = "0.35.0" +shuttle-runtime = "0.35.0" tokio = "1.26.0" diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 2133545d..2b322503 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = { version = "0.6.18" } -shuttle-axum = { version = "0.34.0" } -shuttle-runtime = { version = "0.34.0" } -shuttle-turso = { version = "0.34.0" } +shuttle-axum = { version = "0.35.0" } +shuttle-runtime = { version = "0.35.0" } +shuttle-turso = { version = "0.35.0" } libsql-client = "0.31.0" tokio = { version = "1.26.0" } serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 0cc0a6c3..e168022e 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -11,7 +11,7 @@ hyper = { version = "0.14.26", features = ["client", "http2"] } hyper-tls = "0.5.0" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-axum = "0.35.0" +shuttle-runtime = "0.35.0" tokio = "1.28.2" tower-http = { version = "0.4.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index f8e2cd11..6acc0d02 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.6.10" -shuttle-axum = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-axum = "0.35.0" +shuttle-runtime = "0.35.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 412ebc1f..901c8968 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.6.18" serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.34.0" -shuttle-axum = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-service = "0.35.0" +shuttle-axum = "0.35.0" +shuttle-runtime = "0.35.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 458487d3..dd534180 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.34.0" +shuttle-runtime = "0.35.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index a8a104f7..b215c9cc 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-persist = "0.35.0" +shuttle-runtime = "0.35.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 15452024..44028cee 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,10 +16,10 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.34.0" -shuttle-runtime = "0.34.0" -shuttle-secrets = "0.34.0" -shuttle-shared-db = { version = "0.34.0", features = ["postgres"] } +shuttle-axum = "0.35.0" +shuttle-runtime = "0.35.0" +shuttle-secrets = "0.35.0" +shuttle-shared-db = { version = "0.35.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index 4cae9b8d..48f78c1f 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.34.0" +shuttle-next = "0.35.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 2e489031..9dd5874a 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,7 +15,7 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.6.18" dotenvy = "0.15.7" -shuttle-axum = "0.34.0" -shuttle-runtime = "0.34.0" -shuttle-secrets = "0.34.0" +shuttle-axum = "0.35.0" +shuttle-runtime = "0.35.0" +shuttle-secrets = "0.35.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 7a8212bc..11bd11f7 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-poem = "0.35.0" +shuttle-runtime = "0.35.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 9437cc50..86a9775d 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.34.0" -shuttle-shared-db = { version = "0.34.0", features = ["mongodb"] } -shuttle-runtime = "0.34.0" +shuttle-poem = "0.35.0" +shuttle-shared-db = { version = "0.35.0", features = ["mongodb"] } +shuttle-runtime = "0.35.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index dd8ea309..7c86dd69 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.34.0" -shuttle-runtime = "0.34.0" -shuttle-shared-db = { version = "0.34.0", features = ["postgres"] } +shuttle-poem = "0.35.0" +shuttle-runtime = "0.35.0" +shuttle-shared-db = { version = "0.35.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 7d173e2c..4bca9c21 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.34.0" -shuttle-runtime = "0.34.0" -shuttle-secrets = "0.34.0" +shuttle-poise = "0.35.0" +shuttle-runtime = "0.35.0" +shuttle-secrets = "0.35.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 7d83f102..4ca74c78 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-rocket = "0.35.0" +shuttle-runtime = "0.35.0" rocket_dyn_templates = { version = "0.1.0-rc.4", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 947c5097..76cb8f97 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-rocket = "0.35.0" +shuttle-runtime = "0.35.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 4d619ebd..bf99b6a1 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-rocket = "0.35.0" +shuttle-runtime = "0.35.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index f96d8726..25fc4b86 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.34.0" -shuttle-rocket = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-persist = "0.35.0" +shuttle-rocket = "0.35.0" +shuttle-runtime = "0.35.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 0833304b..40d8cd24 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.34.0", features = ["postgres"] } -shuttle-rocket = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-shared-db = { version = "0.35.0", features = ["postgres"] } +shuttle-rocket = "0.35.0" +shuttle-runtime = "0.35.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index e6115857..532db26b 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.34.0" -shuttle-runtime = "0.34.0" -shuttle-secrets = "0.34.0" +shuttle-rocket = "0.35.0" +shuttle-runtime = "0.35.0" +shuttle-secrets = "0.35.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index 452f2404..6a012b5f 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-rocket = "0.35.0" +shuttle-runtime = "0.35.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 7c55f681..af2e8868 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0", features = ["json"] } -shuttle-rocket = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-rocket = "0.35.0" +shuttle-runtime = "0.35.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.34.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.35.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index b43cad13..c8c50ab2 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-rocket = "0.35.0" +shuttle-runtime = "0.35.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 327bcb76..833bc039 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.41.0" -shuttle-salvo = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-salvo = "0.35.0" +shuttle-runtime = "0.35.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 14ca92aa..7cace558 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-serenity = "0.35.0" +shuttle-runtime = "0.35.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.34.0" +shuttle-secrets = "0.35.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 94e5cd45..f9da30aa 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.34.0" -shuttle-serenity = "0.34.0" -shuttle-runtime = "0.34.0" -shuttle-shared-db = { version = "0.34.0", features = ["postgres"] } +shuttle-secrets = "0.35.0" +shuttle-serenity = "0.35.0" +shuttle-runtime = "0.35.0" +shuttle-shared-db = { version = "0.35.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index b8786ba3..c3f795a9 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-thruster = "0.35.0" +shuttle-runtime = "0.35.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 4346da36..e8d86691 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.34.0", features = ["postgres"] } -shuttle-thruster = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-aws-rds = { version = "0.35.0", features = ["postgres"] } +shuttle-thruster = "0.35.0" +shuttle-runtime = "0.35.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 64e33ae3..61b65308 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.34.0" -shuttle-runtime = "0.34.0" +shuttle-tide = "0.35.0" +shuttle-runtime = "0.35.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index ed791380..3bbaebb5 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.34.0", features = ["postgres"] } -shuttle-runtime = "0.34.0" -shuttle-tide = "0.34.0" +shuttle-aws-rds = { version = "0.35.0", features = ["postgres"] } +shuttle-runtime = "0.35.0" +shuttle-tide = "0.35.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index a85af4a1..210f5962 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.34.0" -shuttle-tower = "0.34.0" +shuttle-runtime = "0.35.0" +shuttle-tower = "0.35.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 7cf7063c..966518af 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.34.0" +shuttle-actix-web = "0.35.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.34.0", default-features = false } +shuttle-runtime = { version = "0.35.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = "0.3.17" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 7b65d7d1..3c1aba0a 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.34.0" -shuttle-warp = "0.34.0" +shuttle-runtime = "0.35.0" +shuttle-warp = "0.35.0" tokio = "1.26.0" warp = "0.3.3" From 56f235ddca4b036ac365b2856b2b76acdbda4c0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Wed, 20 Dec 2023 11:58:39 +0100 Subject: [PATCH 119/239] chore: remove develop branch suggestion from pr template (#122) --- .github/pull_request_template.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index da45b522..06309ca4 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,9 +1,3 @@ - ## Description of change From 7c2f159cd77939f97284ba888a104de06e167105 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Mon, 8 Jan 2024 18:48:48 +0100 Subject: [PATCH 120/239] chore: update axum examples to axum 0.7 (#123) --- axum/hello-world/Cargo.toml | 2 +- axum/jwt-authentication/Cargo.toml | 3 ++- axum/jwt-authentication/src/main.rs | 7 +++++-- axum/metadata/Cargo.toml | 2 +- axum/postgres/Cargo.toml | 2 +- axum/static-files/Cargo.toml | 4 ++-- axum/static-next-server/Cargo.toml | 4 ++-- axum/static-next-server/src/main.rs | 10 +++++----- axum/turso/Cargo.toml | 10 +++++----- axum/websocket/Cargo.toml | 7 +++---- axum/websocket/src/main.rs | 7 +------ axum/with-state/Cargo.toml | 2 +- custom-resource/pdo/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 +--- custom-service/request-scheduler/src/lib.rs | 15 +++++++++++---- fullstack-templates/saas/backend/Cargo.toml | 10 +++++----- fullstack-templates/saas/backend/src/auth.rs | 19 +++++++++---------- fullstack-templates/saas/backend/src/main.rs | 14 +------------- other/standalone-binary/Cargo.toml | 2 +- other/standalone-binary/src/bin/standalone.rs | 4 ++-- 20 files changed, 60 insertions(+), 70 deletions(-) diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 77d2ebd4..7cca9695 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = "0.6.20" +axum = "0.7.3" shuttle-axum = "0.35.0" shuttle-runtime = "0.35.0" tokio = "1.28.2" diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index 9ae088f9..364f8baf 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -4,7 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = { version = "0.6.18", features = ["headers"] } +axum = "0.7.3" +axum-extra = { version = "0.9.1", features = ["typed-header"] } jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } diff --git a/axum/jwt-authentication/src/main.rs b/axum/jwt-authentication/src/main.rs index bad2f11d..9413efc6 100644 --- a/axum/jwt-authentication/src/main.rs +++ b/axum/jwt-authentication/src/main.rs @@ -1,11 +1,14 @@ use axum::{ async_trait, extract::FromRequestParts, - headers::{authorization::Bearer, Authorization}, http::{request::Parts, StatusCode}, response::{IntoResponse, Response}, routing::{get, post}, - Json, RequestPartsExt, Router, TypedHeader, + Json, RequestPartsExt, Router, +}; +use axum_extra::{ + headers::{authorization::Bearer, Authorization}, + TypedHeader, }; use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation}; use once_cell::sync::Lazy; diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index 3434034b..b47ec123 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = "0.6.18" +axum = "0.7.3" shuttle-axum = "0.35.0" shuttle-runtime = "0.35.0" shuttle-metadata = "0.35.0" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 838cd0c0..d1d2fcff 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = "0.6.18" +axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } shuttle-axum = "0.35.0" shuttle-runtime = "0.35.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index c1e717c7..0f2e1190 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" publish = false [dependencies] -axum = "0.6.18" +axum = "0.7.3" shuttle-axum = "0.35.0" shuttle-runtime = "0.35.0" tokio = "1.28.2" -tower-http = { version = "0.4.0", features = ["fs"] } +tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 7c4421e6..3deba2d9 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" publish = false [dependencies] -axum = "0.6.10" -axum-extra = { version = "0.4.2", features = ["spa"] } +axum = "0.7.3" shuttle-axum = "0.35.0" shuttle-runtime = "0.35.0" tokio = "1.26.0" +tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/static-next-server/src/main.rs b/axum/static-next-server/src/main.rs index 97232acd..c18a384d 100644 --- a/axum/static-next-server/src/main.rs +++ b/axum/static-next-server/src/main.rs @@ -1,12 +1,12 @@ -use std::path::PathBuf; - use axum::Router; -use axum_extra::routing::SpaRouter; +use tower_http::services::{ServeDir, ServeFile}; #[shuttle_runtime::main] async fn axum() -> shuttle_axum::ShuttleAxum { - let router = - Router::new().merge(SpaRouter::new("/", PathBuf::from("static")).index_file("index.html")); + let router = Router::new().nest_service( + "/", + ServeDir::new("static").not_found_service(ServeFile::new("static/index.html")), + ); Ok(router.into()) } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 2b322503..4ef03e6b 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -4,11 +4,11 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = { version = "0.6.18" } -shuttle-axum = { version = "0.35.0" } -shuttle-runtime = { version = "0.35.0" } -shuttle-turso = { version = "0.35.0" } +axum = "0.7.3" +shuttle-axum = "0.35.0" +shuttle-runtime = "0.35.0" +shuttle-turso = "0.35.0" libsql-client = "0.31.0" -tokio = { version = "1.26.0" } +tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } serde_json = "1.0.99" diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index e168022e..779d75e2 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -4,14 +4,13 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = { version = "0.6.18", features = ["ws"] } +axum = { version = "0.7.3", features = ["ws"] } chrono = { version = "0.4.26", features = ["serde"] } futures = "0.3.28" -hyper = { version = "0.14.26", features = ["client", "http2"] } -hyper-tls = "0.5.0" +reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" shuttle-axum = "0.35.0" shuttle-runtime = "0.35.0" tokio = "1.28.2" -tower-http = { version = "0.4.0", features = ["fs"] } +tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/websocket/src/main.rs b/axum/websocket/src/main.rs index 38bbdda7..dac3676f 100644 --- a/axum/websocket/src/main.rs +++ b/axum/websocket/src/main.rs @@ -11,8 +11,6 @@ use axum::{ }; use chrono::{DateTime, Utc}; use futures::{SinkExt, StreamExt}; -use hyper::{Client, Uri}; -use hyper_tls::HttpsConnector; use serde::Serialize; use shuttle_axum::ShuttleAxum; use tokio::{ @@ -50,12 +48,9 @@ async fn axum() -> ShuttleAxum { let state_send = state.clone(); tokio::spawn(async move { let duration = Duration::from_secs(PAUSE_SECS); - let https = HttpsConnector::new(); - let client = Client::builder().build::<_, hyper::Body>(https); - let uri: Uri = STATUS_URI.parse().unwrap(); loop { - let is_up = client.get(uri.clone()).await; + let is_up = reqwest::get(STATUS_URI).await; let is_up = is_up.is_ok(); let response = Response { diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index 6acc0d02..7480f90a 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = "0.6.10" +axum = "0.7.3" shuttle-axum = "0.35.0" shuttle-runtime = "0.35.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 901c8968..5b85f730 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] async-trait = "0.1.56" -axum = "0.6.18" +axum = "0.7.3" serde = { version = "1.0.148", default-features = false, features = ["derive"] } shuttle-service = "0.35.0" shuttle-axum = "0.35.0" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index b215c9cc..82a9fdce 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -4,10 +4,8 @@ version = "0.1.0" edition = "2021" publish = false -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] -axum = "0.6.18" +axum = "0.7.3" chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" diff --git a/custom-service/request-scheduler/src/lib.rs b/custom-service/request-scheduler/src/lib.rs index ff938ca8..172c4b98 100644 --- a/custom-service/request-scheduler/src/lib.rs +++ b/custom-service/request-scheduler/src/lib.rs @@ -153,10 +153,17 @@ impl shuttle_runtime::Service for CrontabService { let router = self.router; let mut runner = self.runner; - let server = axum::Server::bind(&addr); - - let (_runner_hdl, _axum_hdl) = - tokio::join!(runner.run_jobs(), server.serve(router.into_make_service())); + let server = async move { + axum::serve( + shuttle_runtime::tokio::net::TcpListener::bind(addr) + .await + .unwrap(), + router, + ) + .await + }; + + let (_runner_hdl, _axum_hdl) = tokio::join!(runner.run_jobs(), server); Ok(()) } diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 44028cee..a273e7df 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -7,11 +7,11 @@ publish = false [dependencies] async-stripe = { version = "0.21.0", features = ["runtime-tokio-hyper"] } -axum = "0.6.15" -axum-extra = { version = "0.7.3", features = ["cookie-private"] } -axum-macros = "0.3.7" +axum = "0.7.3" +axum-extra = { version = "0.9.1", features = ["cookie-private"] } +axum-macros = "0.4.0" bcrypt = "0.14.0" -http = "0.2.9" +http = "1.0.0" lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" @@ -24,4 +24,4 @@ sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres", time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" tower = "0.4.13" -tower-http = { version = "0.4.0", features = ["cors", "fs"] } +tower-http = { version = "0.5.0", features = ["cors", "fs"] } diff --git a/fullstack-templates/saas/backend/src/auth.rs b/fullstack-templates/saas/backend/src/auth.rs index db3dd674..fe105789 100644 --- a/fullstack-templates/saas/backend/src/auth.rs +++ b/fullstack-templates/saas/backend/src/auth.rs @@ -1,7 +1,7 @@ -use axum::middleware::Next; use axum::{ - extract::State, - http::{Request, StatusCode}, + extract::{Request, State}, + http::StatusCode, + middleware::Next, response::{IntoResponse, Response}, Json, }; @@ -73,13 +73,12 @@ pub async fn login( .await .expect("Couldn't insert session :("); - let cookie = Cookie::build("foo", session_id) + let cookie = Cookie::build(("foo", session_id)) .secure(true) .same_site(SameSite::Strict) .http_only(true) .path("/") - .max_age(Duration::WEEK) - .finish(); + .max_age(Duration::WEEK); Ok((jar.add(cookie), StatusCode::OK)) } @@ -101,16 +100,16 @@ pub async fn logout( .execute(&state.postgres); match query.await { - Ok(_) => Ok(jar.remove(Cookie::named("foo"))), + Ok(_) => Ok(jar.remove(Cookie::build("foo"))), Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR), } } -pub async fn validate_session( +pub async fn validate_session( jar: PrivateCookieJar, State(state): State, - request: Request, - next: Next, + request: Request, + next: Next, ) -> (PrivateCookieJar, Response) { let Some(cookie) = jar.get("foo").map(|cookie| cookie.value().to_owned()) else { println!("Couldn't find a cookie in the jar"); diff --git a/fullstack-templates/saas/backend/src/main.rs b/fullstack-templates/saas/backend/src/main.rs index 030ec99e..36aeb7ce 100644 --- a/fullstack-templates/saas/backend/src/main.rs +++ b/fullstack-templates/saas/backend/src/main.rs @@ -1,11 +1,7 @@ -use axum::body::{boxed, Body}; use axum::extract::FromRef; -use axum::http::{Response, StatusCode}; -use axum::routing::get; use axum::Router; use axum_extra::extract::cookie::Key; use sqlx::PgPool; -use tower::ServiceExt; use tower_http::services::ServeDir; mod auth; @@ -61,15 +57,7 @@ async fn axum( let router = Router::new() .nest("/api", api_router) - .fallback_service(get(|req| async move { - match ServeDir::new("public").oneshot(req).await { - Ok(res) => res.map(boxed), - Err(err) => Response::builder() - .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(boxed(Body::from(format!("error: {err}")))) - .expect("error response"), - } - })); + .nest_service("/", ServeDir::new("public")); Ok(router.into()) } diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 9dd5874a..786e605f 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -13,7 +13,7 @@ name = "standalone" path = "src/bin/standalone.rs" [dependencies] -axum = "0.6.18" +axum = "0.7.3" dotenvy = "0.15.7" shuttle-axum = "0.35.0" shuttle-runtime = "0.35.0" diff --git a/other/standalone-binary/src/bin/standalone.rs b/other/standalone-binary/src/bin/standalone.rs index d0d58641..62c35308 100644 --- a/other/standalone-binary/src/bin/standalone.rs +++ b/other/standalone-binary/src/bin/standalone.rs @@ -10,10 +10,10 @@ async fn main() -> Result<(), Box> { let router = build_router(my_secret); // Do the serving on its own - axum::Server::bind(&"127.0.0.1:8000".parse().unwrap()) - .serve(router.into_make_service()) + let listener = tokio::net::TcpListener::bind("127.0.0.1:8000") .await .unwrap(); + axum::serve(listener, router).await.unwrap(); Ok(()) } From bbaa79f2bb5551ae32c48705239497534019856e Mon Sep 17 00:00:00 2001 From: dalton-oliveira Date: Mon, 8 Jan 2024 14:51:21 -0300 Subject: [PATCH 121/239] chore: bump salvo (#121) Co-authored-by: oddgrd <29732646+oddgrd@users.noreply.github.com> --- salvo/hello-world/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 833bc039..acfee30d 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -salvo = "0.41.0" +salvo = "0.63.0" shuttle-salvo = "0.35.0" shuttle-runtime = "0.35.0" tokio = "1.26.0" From b3dba7a152246af57ad195fce20960e151acb96c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Mon, 8 Jan 2024 18:54:43 +0100 Subject: [PATCH 122/239] chore: v0.36.0 (#125) --- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 6 +++--- axum/postgres/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/static-next-server/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- axum/with-state/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 8 ++++---- next/hello-world/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 6 +++--- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 43 files changed, 104 insertions(+), 104 deletions(-) diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index aa557360..c5dd81c0 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.6.0" actix-session = { version = "0.8.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-actix-web = "0.36.0" +shuttle-runtime = "0.36.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index bfdf9184..be9a0388 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-actix-web = "0.36.0" +shuttle-runtime = "0.36.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index db2b0e17..8b5b5d21 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-actix-web = "0.36.0" +shuttle-runtime = "0.36.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.35.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.36.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index ebc1922b..8b81b824 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-actix-web = "0.36.0" +shuttle-runtime = "0.36.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 21f3d01f..4c8188b5 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-actix-web = "0.36.0" +shuttle-runtime = "0.36.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 7cca9695..f4ddd1b8 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-axum = "0.36.0" +shuttle-runtime = "0.36.0" tokio = "1.28.2" tracing = "0.1.40" diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index 364f8baf..f12fdc05 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-axum = "0.36.0" +shuttle-runtime = "0.36.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index b47ec123..6e474faa 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.35.0" -shuttle-runtime = "0.35.0" -shuttle-metadata = "0.35.0" +shuttle-axum = "0.36.0" +shuttle-runtime = "0.36.0" +shuttle-metadata = "0.36.0" tokio = "1.28.2" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index d1d2fcff..37b42056 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.35.0" -shuttle-runtime = "0.35.0" -shuttle-shared-db = { version = "0.35.0", features = ["postgres"] } +shuttle-axum = "0.36.0" +shuttle-runtime = "0.36.0" +shuttle-shared-db = { version = "0.36.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 0f2e1190..daeab82c 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-axum = "0.36.0" +shuttle-runtime = "0.36.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 3deba2d9..d3d830f7 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-axum = "0.36.0" +shuttle-runtime = "0.36.0" tokio = "1.26.0" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 4ef03e6b..0d4a3546 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.35.0" -shuttle-runtime = "0.35.0" -shuttle-turso = "0.35.0" +shuttle-axum = "0.36.0" +shuttle-runtime = "0.36.0" +shuttle-turso = "0.36.0" libsql-client = "0.31.0" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 779d75e2..95a5a313 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-axum = "0.36.0" +shuttle-runtime = "0.36.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index 7480f90a..1509649a 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-axum = "0.36.0" +shuttle-runtime = "0.36.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 5b85f730..84135d31 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.35.0" -shuttle-axum = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-service = "0.36.0" +shuttle-axum = "0.36.0" +shuttle-runtime = "0.36.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index dd534180..a62cb2c4 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.35.0" +shuttle-runtime = "0.36.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index 82a9fdce..3df5ca96 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -10,7 +10,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-persist = "0.36.0" +shuttle-runtime = "0.36.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index a273e7df..490cf9a9 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,10 +16,10 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.35.0" -shuttle-runtime = "0.35.0" -shuttle-secrets = "0.35.0" -shuttle-shared-db = { version = "0.35.0", features = ["postgres"] } +shuttle-axum = "0.36.0" +shuttle-runtime = "0.36.0" +shuttle-secrets = "0.36.0" +shuttle-shared-db = { version = "0.36.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index 48f78c1f..dd9587fd 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.35.0" +shuttle-next = "0.36.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 786e605f..c7107010 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,7 +15,7 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = "0.35.0" -shuttle-runtime = "0.35.0" -shuttle-secrets = "0.35.0" +shuttle-axum = "0.36.0" +shuttle-runtime = "0.36.0" +shuttle-secrets = "0.36.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 11bd11f7..85756ec7 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "1.3.55" -shuttle-poem = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-poem = "0.36.0" +shuttle-runtime = "0.36.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 86a9775d..462f585f 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "1.3.55" -shuttle-poem = "0.35.0" -shuttle-shared-db = { version = "0.35.0", features = ["mongodb"] } -shuttle-runtime = "0.35.0" +shuttle-poem = "0.36.0" +shuttle-shared-db = { version = "0.36.0", features = ["mongodb"] } +shuttle-runtime = "0.36.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 7c86dd69..080da2b6 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "1.3.55" serde = "1.0.148" -shuttle-poem = "0.35.0" -shuttle-runtime = "0.35.0" -shuttle-shared-db = { version = "0.35.0", features = ["postgres"] } +shuttle-poem = "0.36.0" +shuttle-runtime = "0.36.0" +shuttle-shared-db = { version = "0.36.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 4bca9c21..e7b54cc1 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.35.0" -shuttle-runtime = "0.35.0" -shuttle-secrets = "0.35.0" +shuttle-poise = "0.36.0" +shuttle-runtime = "0.36.0" +shuttle-secrets = "0.36.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 4ca74c78..ffb880f6 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-rocket = "0.36.0" +shuttle-runtime = "0.36.0" rocket_dyn_templates = { version = "0.1.0-rc.4", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 76cb8f97..d334b4ab 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-rocket = "0.36.0" +shuttle-runtime = "0.36.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index bf99b6a1..d478c63a 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-rocket = "0.36.0" +shuttle-runtime = "0.36.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 25fc4b86..b3757d59 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.35.0" -shuttle-rocket = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-persist = "0.36.0" +shuttle-rocket = "0.36.0" +shuttle-runtime = "0.36.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 40d8cd24..e596717e 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.35.0", features = ["postgres"] } -shuttle-rocket = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-shared-db = { version = "0.36.0", features = ["postgres"] } +shuttle-rocket = "0.36.0" +shuttle-runtime = "0.36.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 532db26b..cf494bfb 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.35.0" -shuttle-runtime = "0.35.0" -shuttle-secrets = "0.35.0" +shuttle-rocket = "0.36.0" +shuttle-runtime = "0.36.0" +shuttle-secrets = "0.36.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index 6a012b5f..a3bd473a 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-rocket = "0.36.0" +shuttle-runtime = "0.36.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index af2e8868..9b420c3d 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0", features = ["json"] } -shuttle-rocket = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-rocket = "0.36.0" +shuttle-runtime = "0.36.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.35.0", features = ["postgres"] } +shuttle-shared-db = { version = "0.36.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index c8c50ab2..c07c33ff 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-rocket = "0.36.0" +shuttle-runtime = "0.36.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index acfee30d..a4eef6e2 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.63.0" -shuttle-salvo = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-salvo = "0.36.0" +shuttle-runtime = "0.36.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 7cace558..6878dd9f 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-serenity = "0.36.0" +shuttle-runtime = "0.36.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.35.0" +shuttle-secrets = "0.36.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index f9da30aa..7826e730 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.35.0" -shuttle-serenity = "0.35.0" -shuttle-runtime = "0.35.0" -shuttle-shared-db = { version = "0.35.0", features = ["postgres"] } +shuttle-secrets = "0.36.0" +shuttle-serenity = "0.36.0" +shuttle-runtime = "0.36.0" +shuttle-shared-db = { version = "0.36.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index c3f795a9..f7003cde 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-thruster = "0.36.0" +shuttle-runtime = "0.36.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index e8d86691..e10eae8c 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.35.0", features = ["postgres"] } -shuttle-thruster = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-aws-rds = { version = "0.36.0", features = ["postgres"] } +shuttle-thruster = "0.36.0" +shuttle-runtime = "0.36.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 61b65308..7f3874ea 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.35.0" -shuttle-runtime = "0.35.0" +shuttle-tide = "0.36.0" +shuttle-runtime = "0.36.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index 3bbaebb5..15e55ce9 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.35.0", features = ["postgres"] } -shuttle-runtime = "0.35.0" -shuttle-tide = "0.35.0" +shuttle-aws-rds = { version = "0.36.0", features = ["postgres"] } +shuttle-runtime = "0.36.0" +shuttle-tide = "0.36.0" sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 210f5962..3edaa3cf 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.35.0" -shuttle-tower = "0.35.0" +shuttle-runtime = "0.36.0" +shuttle-tower = "0.36.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 966518af..b2519fb5 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.35.0" +shuttle-actix-web = "0.36.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.35.0", default-features = false } +shuttle-runtime = { version = "0.36.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = "0.3.17" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 3c1aba0a..23e08250 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.35.0" -shuttle-warp = "0.35.0" +shuttle-runtime = "0.36.0" +shuttle-warp = "0.36.0" tokio = "1.26.0" warp = "0.3.3" From 898bda0d3c2b47903050bc209929846b47a55e35 Mon Sep 17 00:00:00 2001 From: paulotten Date: Wed, 17 Jan 2024 03:03:54 -0500 Subject: [PATCH 123/239] chore: update poem to 2.0.0, shuttle-poem to 0.37.0 (#126) --- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 4 ++-- poem/postgres/Cargo.toml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 85756ec7..ff9aec77 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -poem = "1.3.55" -shuttle-poem = "0.36.0" +poem = "2.0.0" +shuttle-poem = "0.37.0" shuttle-runtime = "0.36.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 462f585f..2240facb 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] mongodb = "2.4.0" -poem = "1.3.55" -shuttle-poem = "0.36.0" +poem = "2.0.0" +shuttle-poem = "0.37.0" shuttle-shared-db = { version = "0.36.0", features = ["mongodb"] } shuttle-runtime = "0.36.0" serde = { version = "1.0.148", features = ["derive"] } diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 080da2b6..ef6d5fdf 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -4,9 +4,9 @@ version = "0.1.0" edition = "2021" [dependencies] -poem = "1.3.55" +poem = "2.0.0" serde = "1.0.148" -shuttle-poem = "0.36.0" +shuttle-poem = "0.37.0" shuttle-runtime = "0.36.0" shuttle-shared-db = { version = "0.36.0", features = ["postgres"] } sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } From 37c61359f54129f02bd33b4038f9c493fe84e031 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Mon, 22 Jan 2024 18:38:16 +0100 Subject: [PATCH 124/239] feat: update everything to new ResourceBuilder + feature flags (#127) --- actix-web/postgres/Cargo.toml | 4 +-- axum/postgres/Cargo.toml | 4 +-- custom-resource/pdo/src/lib.rs | 32 +++++++-------------- fullstack-templates/saas/Cargo.toml | 1 + fullstack-templates/saas/backend/Cargo.toml | 4 +-- poem/hello-world/Cargo.toml | 2 +- poem/mongodb/Cargo.toml | 2 +- poem/postgres/Cargo.toml | 6 ++-- rocket/postgres/Cargo.toml | 4 +-- rocket/url-shortener/Cargo.toml | 6 ++-- serenity/postgres/Cargo.toml | 6 ++-- serenity/postgres/src/main.rs | 4 +-- thruster/postgres/Cargo.toml | 6 ++-- tide/postgres/Cargo.toml | 4 +-- 14 files changed, 37 insertions(+), 48 deletions(-) diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 8b5b5d21..bfa6ca9b 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -8,6 +8,6 @@ actix-web = "4.3.1" shuttle-actix-web = "0.36.0" shuttle-runtime = "0.36.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.36.0", features = ["postgres"] } -sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } +shuttle-shared-db = { version = "0.36.0", features = ["postgres", "sqlx"] } +sqlx = "0.7.1" tokio = "1.26.0" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 37b42056..2775d0df 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -8,6 +8,6 @@ axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } shuttle-axum = "0.36.0" shuttle-runtime = "0.36.0" -shuttle-shared-db = { version = "0.36.0", features = ["postgres"] } -sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } +shuttle-shared-db = { version = "0.36.0", features = ["postgres", "sqlx"] } +sqlx = "0.7.1" tokio = "1.28.2" diff --git a/custom-resource/pdo/src/lib.rs b/custom-resource/pdo/src/lib.rs index dac8efe6..def29563 100644 --- a/custom-resource/pdo/src/lib.rs +++ b/custom-resource/pdo/src/lib.rs @@ -1,15 +1,12 @@ use async_trait::async_trait; use serde::Serialize; -use shuttle_service::Factory; -use shuttle_service::ResourceBuilder; -use shuttle_service::Type; +use shuttle_service::{resource::Type, Error, Factory, IntoResource, ResourceBuilder}; -#[derive(Serialize)] +#[derive(Default, Serialize)] pub struct Builder { name: String, } -#[derive(Clone)] pub struct Pdo { pub name: String, } @@ -23,33 +20,24 @@ impl Builder { } #[async_trait] -impl ResourceBuilder for Builder { +impl ResourceBuilder for Builder { const TYPE: Type = Type::Custom; - type Config = Self; - type Output = String; - fn new() -> Self { - Self { - name: String::new(), - } - } - fn config(&self) -> &Self::Config { self } - async fn output( - self, - _factory: &mut dyn Factory, - ) -> Result { + async fn output(self, _factory: &mut dyn Factory) -> Result { + // factory can be used to get resources from Shuttle Ok(self.name) } +} - async fn build(build_data: &Self::Output) -> Result { - Ok(Pdo { - name: build_data.clone(), - }) +#[async_trait] +impl IntoResource for String { + async fn into_resource(self) -> Result { + Ok(Pdo { name: self }) } } diff --git a/fullstack-templates/saas/Cargo.toml b/fullstack-templates/saas/Cargo.toml index ac13fe2f..0147b768 100644 --- a/fullstack-templates/saas/Cargo.toml +++ b/fullstack-templates/saas/Cargo.toml @@ -1,2 +1,3 @@ [workspace] +resolver = "2" members = ["backend"] diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 490cf9a9..d3c3ab9f 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -19,8 +19,8 @@ serde = { version = "1.0.160", features = ["derive"] } shuttle-axum = "0.36.0" shuttle-runtime = "0.36.0" shuttle-secrets = "0.36.0" -shuttle-shared-db = { version = "0.36.0", features = ["postgres"] } -sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres", "time"] } +shuttle-shared-db = { version = "0.36.0", features = ["postgres", "sqlx"] } +sqlx = "0.7.1" time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" tower = "0.4.13" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index ff9aec77..12cd89e8 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "2.0.0" -shuttle-poem = "0.37.0" +shuttle-poem = "0.36.0" shuttle-runtime = "0.36.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 2240facb..08ab9872 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "2.0.0" -shuttle-poem = "0.37.0" +shuttle-poem = "0.36.0" shuttle-shared-db = { version = "0.36.0", features = ["mongodb"] } shuttle-runtime = "0.36.0" serde = { version = "1.0.148", features = ["derive"] } diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index ef6d5fdf..b75274fc 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "2.0.0" serde = "1.0.148" -shuttle-poem = "0.37.0" +shuttle-poem = "0.36.0" shuttle-runtime = "0.36.0" -shuttle-shared-db = { version = "0.36.0", features = ["postgres"] } -sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } +shuttle-shared-db = { version = "0.36.0", features = ["postgres", "sqlx"] } +sqlx = "0.7.1" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index e596717e..fa221421 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-shared-db = { version = "0.36.0", features = ["postgres"] } shuttle-rocket = "0.36.0" shuttle-runtime = "0.36.0" -sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } +shuttle-shared-db = { version = "0.36.0", features = ["postgres", "sqlx"] } +sqlx = "0.7.1" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 9b420c3d..2a6a3f82 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] nanoid = "0.4.0" rocket = { version = "0.5.0", features = ["json"] } +serde = "1.0.148" shuttle-rocket = "0.36.0" shuttle-runtime = "0.36.0" -serde = "1.0.148" -shuttle-shared-db = { version = "0.36.0", features = ["postgres"] } -sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } +shuttle-shared-db = { version = "0.36.0", features = ["postgres", "sqlx"] } +sqlx = "0.7.1" tokio = "1.26.0" url = "2.3.1" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 7826e730..78cfcf58 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } +shuttle-runtime = "0.36.0" shuttle-secrets = "0.36.0" shuttle-serenity = "0.36.0" -shuttle-runtime = "0.36.0" -shuttle-shared-db = { version = "0.36.0", features = ["postgres"] } -sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } +shuttle-shared-db = { version = "0.36.0", features = ["postgres", "sqlx"] } +sqlx = "0.7.1" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/src/main.rs b/serenity/postgres/src/main.rs index c878fb39..39871f42 100644 --- a/serenity/postgres/src/main.rs +++ b/serenity/postgres/src/main.rs @@ -33,10 +33,10 @@ impl EventHandler for Bot { let content = match command.data.name.as_str() { "todo" => { - let command = command.data.options.get(0).expect("Expected command"); + let command = command.data.options.first().expect("Expected command"); // if the todo subcommand has a CommandOption the command is either `add` or `complete` - if let Some(subcommand) = command.options.get(0) { + if let Some(subcommand) = command.options.first() { match subcommand.resolved.as_ref().expect("Valid subcommand") { CommandDataOptionValue::String(note) => { db::add(&self.database, note, user_id).await.unwrap() diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index e10eae8c..ed1a4d37 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.36.0", features = ["postgres"] } -shuttle-thruster = "0.36.0" +shuttle-aws-rds = { version = "0.36.0", features = ["postgres", "sqlx"] } shuttle-runtime = "0.36.0" -sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } +shuttle-thruster = "0.36.0" +sqlx = "0.7.1" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index 15e55ce9..b86f090f 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.36.0", features = ["postgres"] } +shuttle-aws-rds = { version = "0.36.0", features = ["postgres", "sqlx"] } shuttle-runtime = "0.36.0" shuttle-tide = "0.36.0" -sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } +sqlx = "0.7.1" tokio = "1.26.0" tide = "0.16.0" From e2397bb073a037a29e2cc4ddfc275143bca87674 Mon Sep 17 00:00:00 2001 From: paulotten Date: Tue, 23 Jan 2024 06:21:48 -0500 Subject: [PATCH 125/239] feat: qdrant resource example (#64) * feat: qdrant resource example * update qdrant example - `shuttle_qdrant::Qdrant` now returns a `QdrantClient` - pass in `cloud_url` and `api_key`, read from `Secrets.toml` * update versions * fix: filenames * fix: correct shuttle version * docs: add qdrant to readme --------- Co-authored-by: jonaro00 <54029719+jonaro00@users.noreply.github.com> --- README.md | 1 + axum/qdrant/Cargo.toml | 12 ++++++++++++ axum/qdrant/Secrets.toml | 3 +++ axum/qdrant/src/main.rs | 25 +++++++++++++++++++++++++ 4 files changed, 41 insertions(+) create mode 100644 axum/qdrant/Cargo.toml create mode 100644 axum/qdrant/Secrets.toml create mode 100644 axum/qdrant/src/main.rs diff --git a/README.md b/README.md index e53aab6e..d0e8e5f4 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ Actix Web | [websocket-actorless](./actix-web/websocket-actorless/) | Websocket Actix Web | [cookie-authentication](./actix-web/cookie-authentication/) | Use JWT to authenticate API endpoints | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/cookie-authentication` Axum | [hello-world](./axum/hello-world/) | Hello World | `cargo shuttle init --template axum` Axum | [metadata](./axum/metadata/) | Simple app that prints the service information such as Shuttle service name | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/metadata` +Axum | [qdrant](./axum/qdrant/) | Barebones example of the shuttle-qdrant plugin | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/qdrant` Axum | [static-files](./axum/static-files/) | Hello World page that serves static HTML and JS files | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/static-files` Axum | [static-next-server](./axum/static-next-server/) | SPA server for serving a apps from frameworks such as Next.js | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/static-next-server` Axum | [websocket](./axum/websocket/) | Websocket app that checks the status of Shuttle's API | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/websocket` diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml new file mode 100644 index 00000000..3171547e --- /dev/null +++ b/axum/qdrant/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "shuttle-axum-qdrant" +version = "0.1.0" +edition = "2021" + +[dependencies] +axum = "0.7.3" +qdrant-client = "1.7.0" +shuttle-axum = "0.36.0" +shuttle-qdrant = "0.36.0" +shuttle-runtime = "0.36.0" +tokio = "1.26.0" diff --git a/axum/qdrant/Secrets.toml b/axum/qdrant/Secrets.toml new file mode 100644 index 00000000..651f7b7a --- /dev/null +++ b/axum/qdrant/Secrets.toml @@ -0,0 +1,3 @@ +# Note that we use gRPC (port 6334) to talk to Qdrant. +CLOUD_URL = 'https://xyz-example.eu-central.aws.cloud.qdrant.io:6334' +API_KEY = 'your_api_key' diff --git a/axum/qdrant/src/main.rs b/axum/qdrant/src/main.rs new file mode 100644 index 00000000..7b87f778 --- /dev/null +++ b/axum/qdrant/src/main.rs @@ -0,0 +1,25 @@ +use axum::{extract::State, routing::get, Router}; +use qdrant_client::prelude::*; +use std::sync::Arc; + +struct AppState { + qdrant: QdrantClient, +} + +async fn list_collections(State(state): State>) -> String { + format!("{:?}\n", state.qdrant.list_collections().await) +} + +#[shuttle_runtime::main] +async fn axum( + #[shuttle_qdrant::Qdrant(cloud_url = "{secrets.CLOUD_URL}", api_key = "{secrets.API_KEY}")] + qdrant: QdrantClient, +) -> shuttle_axum::ShuttleAxum { + let state = Arc::new(AppState { qdrant }); + + let router = Router::new() + .route("/", get(list_collections)) + .with_state(state); + + Ok(router.into()) +} From 420080fff0c4be75bfba163e88d38e465d33d3d5 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Tue, 23 Jan 2024 15:09:13 +0100 Subject: [PATCH 126/239] chore: v0.37.0 --- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 6 +++--- axum/postgres/Cargo.toml | 6 +++--- axum/qdrant/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/static-next-server/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- axum/with-state/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 8 ++++---- next/hello-world/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 6 +++--- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 44 files changed, 107 insertions(+), 107 deletions(-) diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index c5dd81c0..fa578273 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.6.0" actix-session = { version = "0.8.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-actix-web = "0.37.0" +shuttle-runtime = "0.37.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index be9a0388..e8bed756 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-actix-web = "0.37.0" +shuttle-runtime = "0.37.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index bfa6ca9b..ef5aefba 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-actix-web = "0.37.0" +shuttle-runtime = "0.37.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.36.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.37.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index 8b81b824..80cf2a1b 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-actix-web = "0.37.0" +shuttle-runtime = "0.37.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 4c8188b5..2c7761ed 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-actix-web = "0.37.0" +shuttle-runtime = "0.37.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index f4ddd1b8..2acfaa0e 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-axum = "0.37.0" +shuttle-runtime = "0.37.0" tokio = "1.28.2" tracing = "0.1.40" diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index f12fdc05..a98e1724 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-axum = "0.37.0" +shuttle-runtime = "0.37.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index 6e474faa..78d07289 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.36.0" -shuttle-runtime = "0.36.0" -shuttle-metadata = "0.36.0" +shuttle-axum = "0.37.0" +shuttle-runtime = "0.37.0" +shuttle-metadata = "0.37.0" tokio = "1.28.2" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 2775d0df..7ee3fe9f 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.36.0" -shuttle-runtime = "0.36.0" -shuttle-shared-db = { version = "0.36.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.37.0" +shuttle-runtime = "0.37.0" +shuttle-shared-db = { version = "0.37.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index 3171547e..2f43d36c 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.7.0" -shuttle-axum = "0.36.0" -shuttle-qdrant = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-axum = "0.37.0" +shuttle-qdrant = "0.37.0" +shuttle-runtime = "0.37.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index daeab82c..7b67c21f 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-axum = "0.37.0" +shuttle-runtime = "0.37.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index d3d830f7..dd1d5f32 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-axum = "0.37.0" +shuttle-runtime = "0.37.0" tokio = "1.26.0" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 0d4a3546..0c444645 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.36.0" -shuttle-runtime = "0.36.0" -shuttle-turso = "0.36.0" +shuttle-axum = "0.37.0" +shuttle-runtime = "0.37.0" +shuttle-turso = "0.37.0" libsql-client = "0.31.0" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 95a5a313..3c46b5ec 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-axum = "0.37.0" +shuttle-runtime = "0.37.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index 1509649a..b01a6565 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-axum = "0.37.0" +shuttle-runtime = "0.37.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 84135d31..d0671f6a 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.36.0" -shuttle-axum = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-service = "0.37.0" +shuttle-axum = "0.37.0" +shuttle-runtime = "0.37.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index a62cb2c4..4153900c 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.36.0" +shuttle-runtime = "0.37.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index 3df5ca96..1b06f081 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -10,7 +10,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-persist = "0.37.0" +shuttle-runtime = "0.37.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index d3c3ab9f..85e8fd5d 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,10 +16,10 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.36.0" -shuttle-runtime = "0.36.0" -shuttle-secrets = "0.36.0" -shuttle-shared-db = { version = "0.36.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.37.0" +shuttle-runtime = "0.37.0" +shuttle-secrets = "0.37.0" +shuttle-shared-db = { version = "0.37.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index dd9587fd..a12c380a 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.36.0" +shuttle-next = "0.37.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index c7107010..c081af8d 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,7 +15,7 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = "0.36.0" -shuttle-runtime = "0.36.0" -shuttle-secrets = "0.36.0" +shuttle-axum = "0.37.0" +shuttle-runtime = "0.37.0" +shuttle-secrets = "0.37.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 12cd89e8..8ae6a3c3 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "2.0.0" -shuttle-poem = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-poem = "0.37.0" +shuttle-runtime = "0.37.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 08ab9872..e80a1d63 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "2.0.0" -shuttle-poem = "0.36.0" -shuttle-shared-db = { version = "0.36.0", features = ["mongodb"] } -shuttle-runtime = "0.36.0" +shuttle-poem = "0.37.0" +shuttle-shared-db = { version = "0.37.0", features = ["mongodb"] } +shuttle-runtime = "0.37.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index b75274fc..3183a76f 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "2.0.0" serde = "1.0.148" -shuttle-poem = "0.36.0" -shuttle-runtime = "0.36.0" -shuttle-shared-db = { version = "0.36.0", features = ["postgres", "sqlx"] } +shuttle-poem = "0.37.0" +shuttle-runtime = "0.37.0" +shuttle-shared-db = { version = "0.37.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index e7b54cc1..ef8601c6 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.5.2" -shuttle-poise = "0.36.0" -shuttle-runtime = "0.36.0" -shuttle-secrets = "0.36.0" +shuttle-poise = "0.37.0" +shuttle-runtime = "0.37.0" +shuttle-secrets = "0.37.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index ffb880f6..d9ca469d 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-rocket = "0.37.0" +shuttle-runtime = "0.37.0" rocket_dyn_templates = { version = "0.1.0-rc.4", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index d334b4ab..ce7724ca 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-rocket = "0.37.0" +shuttle-runtime = "0.37.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index d478c63a..1a48e25c 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-rocket = "0.37.0" +shuttle-runtime = "0.37.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index b3757d59..af3127e7 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.36.0" -shuttle-rocket = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-persist = "0.37.0" +shuttle-rocket = "0.37.0" +shuttle-runtime = "0.37.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index fa221421..03f3e91a 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.36.0" -shuttle-runtime = "0.36.0" -shuttle-shared-db = { version = "0.36.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.37.0" +shuttle-runtime = "0.37.0" +shuttle-shared-db = { version = "0.37.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index cf494bfb..0171e106 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.36.0" -shuttle-runtime = "0.36.0" -shuttle-secrets = "0.36.0" +shuttle-rocket = "0.37.0" +shuttle-runtime = "0.37.0" +shuttle-secrets = "0.37.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index a3bd473a..55157c27 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-rocket = "0.37.0" +shuttle-runtime = "0.37.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 2a6a3f82..f720259a 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" nanoid = "0.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.36.0" -shuttle-runtime = "0.36.0" -shuttle-shared-db = { version = "0.36.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.37.0" +shuttle-runtime = "0.37.0" +shuttle-shared-db = { version = "0.37.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index c07c33ff..07f462d4 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-rocket = "0.37.0" +shuttle-runtime = "0.37.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index a4eef6e2..7402a7f7 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.63.0" -shuttle-salvo = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-salvo = "0.37.0" +shuttle-runtime = "0.37.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 6878dd9f..16df0c75 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-serenity = "0.37.0" +shuttle-runtime = "0.37.0" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-secrets = "0.36.0" +shuttle-secrets = "0.37.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 78cfcf58..711688c1 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.36.0" -shuttle-secrets = "0.36.0" -shuttle-serenity = "0.36.0" -shuttle-shared-db = { version = "0.36.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.37.0" +shuttle-secrets = "0.37.0" +shuttle-serenity = "0.37.0" +shuttle-shared-db = { version = "0.37.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index f7003cde..a98b921c 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-thruster = "0.37.0" +shuttle-runtime = "0.37.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index ed1a4d37..0281d839 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.36.0", features = ["postgres", "sqlx"] } -shuttle-runtime = "0.36.0" -shuttle-thruster = "0.36.0" +shuttle-aws-rds = { version = "0.37.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.37.0" +shuttle-thruster = "0.37.0" sqlx = "0.7.1" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 7f3874ea..5f6f7308 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.36.0" -shuttle-runtime = "0.36.0" +shuttle-tide = "0.37.0" +shuttle-runtime = "0.37.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index b86f090f..d5c26450 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.36.0", features = ["postgres", "sqlx"] } -shuttle-runtime = "0.36.0" -shuttle-tide = "0.36.0" +shuttle-aws-rds = { version = "0.37.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.37.0" +shuttle-tide = "0.37.0" sqlx = "0.7.1" tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 3edaa3cf..f58c44b8 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.36.0" -shuttle-tower = "0.36.0" +shuttle-runtime = "0.37.0" +shuttle-tower = "0.37.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index b2519fb5..fb91b460 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.36.0" +shuttle-actix-web = "0.37.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.36.0", default-features = false } +shuttle-runtime = { version = "0.37.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = "0.3.17" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 23e08250..c14d91e7 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.36.0" -shuttle-warp = "0.36.0" +shuttle-runtime = "0.37.0" +shuttle-warp = "0.37.0" tokio = "1.26.0" warp = "0.3.3" From cd956609f7114d93dd29bb1d71445107589862eb Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Tue, 23 Jan 2024 20:29:21 +0100 Subject: [PATCH 127/239] feat: update serenity and poise examples to use serenity 0.12 (#129) * feat: update serenity and poise examples to use serenity 0.12 * fix: cargo deps * docs: comment --- poise/hello-world/Cargo.toml | 7 +- poise/hello-world/Shuttle.toml | 1 - poise/hello-world/src/main.rs | 15 ++-- serenity/hello-world/Cargo.toml | 6 +- serenity/hello-world/Shuttle.toml | 1 - serenity/postgres/Cargo.toml | 4 +- serenity/postgres/Shuttle.toml | 1 - serenity/postgres/src/main.rs | 145 +++++++++++++++--------------- 8 files changed, 90 insertions(+), 90 deletions(-) delete mode 100644 poise/hello-world/Shuttle.toml delete mode 100644 serenity/hello-world/Shuttle.toml delete mode 100644 serenity/postgres/Shuttle.toml diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index ef8601c6..7a119b21 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -1,14 +1,15 @@ [package] -name = "hello-world" +name = "hello-world-poise-bot" version = "0.1.0" edition = "2021" publish = false [dependencies] anyhow = "1.0.68" -poise = "0.5.2" -shuttle-poise = "0.37.0" +poise = "0.6.1" shuttle-runtime = "0.37.0" shuttle-secrets = "0.37.0" +# Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity +shuttle-serenity = "0.37.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/poise/hello-world/Shuttle.toml b/poise/hello-world/Shuttle.toml deleted file mode 100644 index 4ebb812b..00000000 --- a/poise/hello-world/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "hello-world-poise-bot" diff --git a/poise/hello-world/src/main.rs b/poise/hello-world/src/main.rs index 1219db60..64abe991 100644 --- a/poise/hello-world/src/main.rs +++ b/poise/hello-world/src/main.rs @@ -1,7 +1,7 @@ use anyhow::Context as _; -use poise::serenity_prelude as serenity; -use shuttle_poise::ShuttlePoise; +use poise::serenity_prelude::{ClientBuilder, GatewayIntents}; use shuttle_secrets::SecretStore; +use shuttle_serenity::ShuttleSerenity; struct Data {} // User data, which is stored and accessible in all command invocations type Error = Box; @@ -15,7 +15,7 @@ async fn hello(ctx: Context<'_>) -> Result<(), Error> { } #[shuttle_runtime::main] -async fn poise(#[shuttle_secrets::Secrets] secret_store: SecretStore) -> ShuttlePoise { +async fn main(#[shuttle_secrets::Secrets] secret_store: SecretStore) -> ShuttleSerenity { // Get the discord token set in `Secrets.toml` let discord_token = secret_store .get("DISCORD_TOKEN") @@ -26,17 +26,18 @@ async fn poise(#[shuttle_secrets::Secrets] secret_store: SecretStore) -> Shuttle commands: vec![hello()], ..Default::default() }) - .token(discord_token) - .intents(serenity::GatewayIntents::non_privileged()) .setup(|ctx, _ready, framework| { Box::pin(async move { poise::builtins::register_globally(ctx, &framework.options().commands).await?; Ok(Data {}) }) }) - .build() + .build(); + + let client = ClientBuilder::new(discord_token, GatewayIntents::non_privileged()) + .framework(framework) .await .map_err(shuttle_runtime::CustomError::new)?; - Ok(framework.into()) + Ok(client.into()) } diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 16df0c75..e06204f3 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -1,13 +1,13 @@ [package] -name = "hello-world" +name = "hello-world-serenity-bot" version = "0.1.0" edition = "2021" [dependencies] anyhow = "1.0.66" -shuttle-serenity = "0.37.0" +serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } shuttle-runtime = "0.37.0" -serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } shuttle-secrets = "0.37.0" +shuttle-serenity = "0.37.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/hello-world/Shuttle.toml b/serenity/hello-world/Shuttle.toml deleted file mode 100644 index 39fe0983..00000000 --- a/serenity/hello-world/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "hello-world-serenity-bot" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 711688c1..d8ea5012 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -1,12 +1,12 @@ [package] -name = "serenity-postgres" +name = "postgres-serenity-bot" version = "0.1.0" edition = "2021" [dependencies] anyhow = "1.0.66" serde = "1.0.148" -serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } +serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } shuttle-runtime = "0.37.0" shuttle-secrets = "0.37.0" shuttle-serenity = "0.37.0" diff --git a/serenity/postgres/Shuttle.toml b/serenity/postgres/Shuttle.toml deleted file mode 100644 index bc686807..00000000 --- a/serenity/postgres/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "postgres-serenity-bot" diff --git a/serenity/postgres/src/main.rs b/serenity/postgres/src/main.rs index 39871f42..d908ebff 100644 --- a/serenity/postgres/src/main.rs +++ b/serenity/postgres/src/main.rs @@ -1,8 +1,9 @@ use anyhow::Context as _; use serenity::async_trait; -use serenity::model::application::command::CommandOptionType; -use serenity::model::application::interaction::application_command::CommandDataOptionValue; -use serenity::model::application::interaction::{Interaction, InteractionResponseType}; +use serenity::builder::{ + CreateCommand, CreateCommandOption, CreateInteractionResponse, CreateInteractionResponseMessage, +}; +use serenity::model::application::{CommandDataOptionValue, CommandOptionType, Interaction}; use serenity::model::gateway::Ready; use serenity::model::id::GuildId; use serenity::prelude::*; @@ -20,54 +21,52 @@ struct Bot { #[async_trait] impl EventHandler for Bot { async fn interaction_create(&self, ctx: Context, interaction: Interaction) { - let user_id: i64 = interaction - .clone() - .application_command() - .unwrap() - .user - .id - .into(); - - if let Interaction::ApplicationCommand(command) = interaction { + if let Interaction::Command(command) = interaction { info!("Received command interaction: {:#?}", command); + let user_id: i64 = command.user.id.into(); + let content = match command.data.name.as_str() { "todo" => { let command = command.data.options.first().expect("Expected command"); - // if the todo subcommand has a CommandOption the command is either `add` or `complete` - if let Some(subcommand) = command.options.first() { - match subcommand.resolved.as_ref().expect("Valid subcommand") { - CommandDataOptionValue::String(note) => { + match command.name.as_str() { + "add" => match &command.value { + CommandDataOptionValue::SubCommand(opts) => { + let note = opts.first().unwrap().value.as_str().unwrap(); db::add(&self.database, note, user_id).await.unwrap() } - CommandDataOptionValue::Integer(index) => { - db::complete(&self.database, index, user_id) + _ => "Command not implemented".to_string(), + }, + "complete" => match &command.value { + CommandDataOptionValue::SubCommand(opts) => { + let index = opts.first().unwrap().value.as_i64().unwrap(); + db::complete(&self.database, &index, user_id) .await .unwrap_or_else(|_| { "Please submit a valid index from your todo list" .to_string() }) } - _ => "Please enter a valid todo".to_string(), - } - // if the todo subcommand doesn't have a CommandOption the command is `list` - } else { - db::list(&self.database, user_id).await.unwrap() + _ => "Command not implemented".to_string(), + }, + "list" => db::list(&self.database, user_id).await.unwrap(), + _ => "Command not implemented".to_string(), } } _ => "Command not implemented".to_string(), }; if let Err(why) = command - .create_interaction_response(&ctx.http, |response| { - response - .kind(InteractionResponseType::ChannelMessageWithSource) - .interaction_response_data(|message| message.content(content)) - }) + .create_response( + &ctx.http, + CreateInteractionResponse::Message( + CreateInteractionResponseMessage::new().content(content), + ), + ) .await { - error!("Cannot respond to slash command: {}", why); + error!("Cannot respond to slash command: {why}"); } } } @@ -75,51 +74,53 @@ impl EventHandler for Bot { async fn ready(&self, ctx: Context, ready: Ready) { info!("{} is connected!", ready.user.name); - let guild_id = GuildId(self.guild_id.parse().unwrap()); + let guild_id = GuildId::new(self.guild_id.parse().unwrap()); - let _ = GuildId::set_application_commands(&guild_id, &ctx.http, |commands| { - commands.create_application_command(|command| { - command - .name("todo") + let _ = guild_id + .set_commands( + &ctx.http, + vec![CreateCommand::new("todo") .description("Add, list and complete todos") - .create_option(|option| { - option - .name("add") - .description("Add a new todo") - .kind(CommandOptionType::SubCommand) - .create_sub_option(|option| { - option - .name("note") - .description("The todo note to add") - .kind(CommandOptionType::String) - .min_length(2) - .max_length(100) - .required(true) - }) - }) - .create_option(|option| { - option - .name("complete") - .description("The todo to complete") - .kind(CommandOptionType::SubCommand) - .create_sub_option(|option| { - option - .name("index") - .description("The index of the todo to complete") - .kind(CommandOptionType::Integer) - .min_int_value(1) - .required(true) - }) - }) - .create_option(|option| { - option - .name("list") - .description("List your todos") - .kind(CommandOptionType::SubCommand) - }) - }) - }) - .await; + .add_option( + CreateCommandOption::new( + CommandOptionType::SubCommand, + "add", + "Add a new todo", + ) + .add_sub_option( + CreateCommandOption::new( + CommandOptionType::String, + "note", + "The todo note to add", + ) + .min_length(2) + .max_length(100) + .required(true), + ), + ) + .add_option( + CreateCommandOption::new( + CommandOptionType::SubCommand, + "complete", + "The todo to complete", + ) + .add_sub_option( + CreateCommandOption::new( + CommandOptionType::Integer, + "index", + "The index of the todo to complete", + ) + .min_int_value(1) + .required(true), + ), + ) + .add_option(CreateCommandOption::new( + CommandOptionType::SubCommand, + "list", + "List your todos", + ))], + ) + .await; } } From 3a41ef91060da8efeb4144172fe03dce026e98d6 Mon Sep 17 00:00:00 2001 From: Joshua Mo <102877324+joshua-mo-143@users.noreply.github.com> Date: Wed, 24 Jan 2024 15:37:42 +0000 Subject: [PATCH 128/239] feat: cron example with apalis (#131) * refactor: cron example * refactor: amendments * refactor: amendments * refactor: amendments * refactor: amendments * refactor: change crate name * refactor: amendments to match article --- README.md | 1 + shuttle-cron/.gitignore | 3 ++ shuttle-cron/Cargo.toml | 15 ++++++ shuttle-cron/README.md | 18 +++++++ shuttle-cron/src/main.rs | 100 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 137 insertions(+) create mode 100644 shuttle-cron/.gitignore create mode 100644 shuttle-cron/Cargo.toml create mode 100644 shuttle-cron/README.md create mode 100644 shuttle-cron/src/main.rs diff --git a/README.md b/README.md index d0e8e5f4..26f27064 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ Tower | [hello-world](./tower/hello-world/) | Hello World | `cargo shuttle init Tracing | [custom-tracing-subscriber](./tracing/custom-tracing-subscriber/) | Hello world with a custom tracing setup | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder tracing/custom-tracing-subscriber` Warp | [hello-world](./warp/hello-world/) | Hello World | `cargo shuttle init --template warp` *Custom Service* | [none](./custom-service/none/) | Empty service - A barebones implementation of Shuttle Service trait that does nothing | `cargo shuttle init --template none` +*Custom Service* | [shuttle-cron](./shuttle-cron/) | A custom service that runs a cron job server using Apalis | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder shuttle-cron` *Custom Service* | [request-scheduler](./custom-service/request-scheduler/) | A custom *Request Scheduler* service | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder custom-service/request-scheduler` *Custom Resource* | [pdo](./custom-resource/pdo/) | Custom Shuttle resource that holds a Plain Data Object (PDO), shown in the context of an Axum app | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder custom-resource/pdo` *Other* | [standalone-binary](./other/standalone-binary/) | How to split a project to allow it to run both with Shuttle and standalone | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder other/standalone-binary` diff --git a/shuttle-cron/.gitignore b/shuttle-cron/.gitignore new file mode 100644 index 00000000..e8541fe9 --- /dev/null +++ b/shuttle-cron/.gitignore @@ -0,0 +1,3 @@ +/target +.shuttle-storage +Secrets*.toml diff --git a/shuttle-cron/Cargo.toml b/shuttle-cron/Cargo.toml new file mode 100644 index 00000000..973652ab --- /dev/null +++ b/shuttle-cron/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "shuttle-cron" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +apalis = { version = "0.4.9", features = ["cron", "postgres", "extensions", "retry"] } +chrono = { version = "0.4.32", features = ["clock", "serde"] } +serde = { version = "1.0.195", features = ["derive"] } +shuttle-runtime = "0.37.0" +shuttle-shared-db = { version = "0.37.0", features = ["postgres"] } +sqlx = { version = "0.7.3", features = ["runtime-tokio-native-tls", "postgres"] } +tokio = "1" +tower = { version = "0.4.13" } diff --git a/shuttle-cron/README.md b/shuttle-cron/README.md new file mode 100644 index 00000000..e4c55764 --- /dev/null +++ b/shuttle-cron/README.md @@ -0,0 +1,18 @@ +## Shuttle Cron Template +This repository is an example of how you can deploy a cronjob to [Shuttle](https://www.shuttle.rs), the Rust-native dev cloud platform. + +### Usage +Make sure you have `cargo-shuttle` installed! If not, you can use `cargo install cargo-shuttle` to do so. Requires Rust 1.70+ installed. + +Run the following to initialise this project: +```bash +cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder shuttle-cron +``` + +Follow the prompt, then make any changes you want. Once done, you can deploy: +```bash +cargo shuttle deploy + +# use this if on a dirty Git branch +cargo shuttle deploy --allow-dirty +``` diff --git a/shuttle-cron/src/main.rs b/shuttle-cron/src/main.rs new file mode 100644 index 00000000..3143a415 --- /dev/null +++ b/shuttle-cron/src/main.rs @@ -0,0 +1,100 @@ +use apalis::cron::CronStream; +use apalis::cron::Schedule; +use apalis::layers::{DefaultRetryPolicy, Extension, RetryLayer}; +use apalis::postgres::PostgresStorage; +use apalis::prelude::*; +use chrono::{DateTime, Utc}; +use serde::{Deserialize, Serialize}; +use sqlx::{postgres::PgPoolOptions, PgPool}; +use std::str::FromStr; +use tower::ServiceBuilder; + +#[derive(Clone)] +struct CronjobData { + message: String, +} +impl CronjobData { + fn execute(&self, _item: Reminder) { + println!("{} from CronjobData::execute()!", &self.message); + } +} + +#[derive(Default, Debug, Clone, Serialize, Deserialize)] +struct Reminder(DateTime); +impl From> for Reminder { + fn from(t: DateTime) -> Self { + Reminder(t) + } +} + +impl Job for Reminder { + const NAME: &'static str = "reminder::DailyReminder"; +} + +async fn say_hello_world(job: Reminder, ctx: JobContext) { + println!("Hello world from send_reminder()!"); + // this lets you use variables stored in the CronjobData struct + let svc = ctx.data_opt::().unwrap(); + // this executes CronjobData::execute() + svc.execute(job); +} + +#[shuttle_runtime::main] +async fn shuttle_main( + #[shuttle_shared_db::Postgres] conn_string: String, +) -> Result { + let db = PgPoolOptions::new() + .min_connections(5) + .max_connections(5) + .connect(&conn_string) + .await + .unwrap(); + + Ok(MyService { db }) +} + +// Customize this struct with things from `shuttle_main` needed in `bind`, +// such as secrets or database connections +struct MyService { + db: PgPool, +} + +#[shuttle_runtime::async_trait] +impl shuttle_runtime::Service for MyService { + async fn bind(self, _addr: std::net::SocketAddr) -> Result<(), shuttle_runtime::Error> { + let storage = PostgresStorage::new(self.db); + // set up storage + storage.setup().await.expect("Unable to run migrations :("); + + let schedule = Schedule::from_str("* * * * * *").expect("Couldn't start the scheduler!"); + + let cron_service_ext = CronjobData { + message: "Hello world".to_string(), + }; + + // create a servicebuilder for the cronjob + let service = ServiceBuilder::new() + .layer(RetryLayer::new(DefaultRetryPolicy)) + .layer(Extension(cron_service_ext)) + .service(job_fn(say_hello_world)); + + // create a worker that uses the service created from the cronjob + let worker = WorkerBuilder::new("morning-cereal") + .with_storage(storage.clone()) + .stream( + CronStream::new(schedule.clone()) + .timer(apalis::prelude::timer::TokioTimer) + .to_stream(), + ) + .build(service.clone()); + + // start your worker up + Monitor::new() + .register(worker) + .run() + .await + .expect("Unable to start worker"); + + Ok(()) + } +} From 7836b78c169be725f5ed9686dc3f8908be5292e9 Mon Sep 17 00:00:00 2001 From: Maurice Van Wassenhove Date: Fri, 26 Jan 2024 16:31:19 +0100 Subject: [PATCH 129/239] feat(shuttle-turso): update turso example to use libsql (#132) --- axum/turso/Cargo.toml | 2 +- axum/turso/src/main.rs | 50 ++++++++++++++++++++---------------------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 0c444645..831440b9 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -8,7 +8,7 @@ axum = "0.7.3" shuttle-axum = "0.37.0" shuttle-runtime = "0.37.0" shuttle-turso = "0.37.0" -libsql-client = "0.31.0" +libsql = "0.2.0" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } serde_json = "1.0.99" diff --git a/axum/turso/src/main.rs b/axum/turso/src/main.rs index bcf86e25..e4f67e26 100644 --- a/axum/turso/src/main.rs +++ b/axum/turso/src/main.rs @@ -1,26 +1,21 @@ use std::sync::Arc; -use axum::{extract, extract::State, response::IntoResponse, routing::get, Json, Router}; -use libsql_client::{args, Client, Row, Statement, Value}; +use axum::{extract::State, response::IntoResponse, routing::get, Json, Router}; +use libsql::Connection; use serde::{Deserialize, Serialize}; -fn row_string_field(r: &Row, index: usize) -> String { - match r.values.get(index).unwrap() { - Value::Text { value } => value.clone(), - _ => unreachable!(), +async fn get_posts(State(client): State>) -> Json> { + let mut rows = client + .query("select * from example_users", ()) + .await + .unwrap(); + let mut users = vec![]; + while let Some(row) = rows.next().unwrap() { + users.push(User { + uid: row.get::(0).unwrap(), + email: row.get::(1).unwrap(), + }); } -} - -async fn get_posts(State(client): State>) -> Json> { - let rows = client.execute("select * from example_users").await.unwrap(); - let users: Vec<_> = rows - .rows - .iter() - .map(|r| User { - uid: row_string_field(r, 0), - email: row_string_field(r, 1), - }) - .collect(); Json(users) } @@ -31,14 +26,14 @@ struct User { } async fn create_users( - State(client): State>, - extract::Json(user): extract::Json, + State(client): State>, + Json(user): Json, ) -> impl IntoResponse { client - .execute(Statement::with_args( - "insert into example_users values (?, ?)", - args!(user.uid, user.email), - )) + .execute( + "insert into example_users (uid, email) values (?1, ?2)", + [user.uid, user.email], + ) .await .unwrap(); @@ -48,12 +43,15 @@ async fn create_users( #[shuttle_runtime::main] async fn axum( #[shuttle_turso::Turso(addr = "libsql://your-db.turso.io", token = "{secrets.TURSO_DB_TOKEN}")] - client: Client, + client: Connection, ) -> shuttle_axum::ShuttleAxum { let client = Arc::new(client); client - .execute("create table if not exists example_users ( uid text primary key, email text );") + .execute( + "create table if not exists example_users ( uid text primary key, email text );", + (), + ) .await .unwrap(); From 5ed37305b7e87efe1563cfa51d0d5d0fc16b8193 Mon Sep 17 00:00:00 2001 From: Joshua Mo <102877324+joshua-mo-143@users.noreply.github.com> Date: Mon, 29 Jan 2024 22:31:16 +0000 Subject: [PATCH 130/239] fix: move static files to proper directory (#119) * fix: static files * chore: update dependencies * refactor: satisfy CI * refactor: revert deps --- fullstack-templates/saas/.gitignore | 1 + fullstack-templates/saas/Shuttle.toml | 2 +- fullstack-templates/saas/backend/Cargo.toml | 2 +- fullstack-templates/saas/backend/src/auth.rs | 5 +++-- fullstack-templates/saas/backend/src/main.rs | 10 ++++++---- fullstack-templates/saas/next.config.js | 2 +- fullstack-templates/saas/package-lock.json | 2 +- 7 files changed, 14 insertions(+), 10 deletions(-) diff --git a/fullstack-templates/saas/.gitignore b/fullstack-templates/saas/.gitignore index 8f322f0d..5bb6b914 100644 --- a/fullstack-templates/saas/.gitignore +++ b/fullstack-templates/saas/.gitignore @@ -11,6 +11,7 @@ # next.js /.next/ /out/ +dist # production /build diff --git a/fullstack-templates/saas/Shuttle.toml b/fullstack-templates/saas/Shuttle.toml index 411cf936..69125769 100644 --- a/fullstack-templates/saas/Shuttle.toml +++ b/fullstack-templates/saas/Shuttle.toml @@ -1,3 +1,3 @@ assets = [ - "public/*", + "dist/*", ] diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 85e8fd5d..4aa3f7c7 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -20,7 +20,7 @@ shuttle-axum = "0.37.0" shuttle-runtime = "0.37.0" shuttle-secrets = "0.37.0" shuttle-shared-db = { version = "0.37.0", features = ["postgres", "sqlx"] } -sqlx = "0.7.1" +sqlx = { version = "0.7.1", features = ["runtime-tokio-rustls", "postgres", "time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" tower = "0.4.13" diff --git a/fullstack-templates/saas/backend/src/auth.rs b/fullstack-templates/saas/backend/src/auth.rs index fe105789..74f5cca3 100644 --- a/fullstack-templates/saas/backend/src/auth.rs +++ b/fullstack-templates/saas/backend/src/auth.rs @@ -78,7 +78,8 @@ pub async fn login( .same_site(SameSite::Strict) .http_only(true) .path("/") - .max_age(Duration::WEEK); + .max_age(Duration::WEEK) + .build(); Ok((jar.add(cookie), StatusCode::OK)) } @@ -100,7 +101,7 @@ pub async fn logout( .execute(&state.postgres); match query.await { - Ok(_) => Ok(jar.remove(Cookie::build("foo"))), + Ok(_) => Ok(jar.remove(Cookie::from("foo"))), Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR), } } diff --git a/fullstack-templates/saas/backend/src/main.rs b/fullstack-templates/saas/backend/src/main.rs index 36aeb7ce..5608c175 100644 --- a/fullstack-templates/saas/backend/src/main.rs +++ b/fullstack-templates/saas/backend/src/main.rs @@ -2,7 +2,8 @@ use axum::extract::FromRef; use axum::Router; use axum_extra::extract::cookie::Key; use sqlx::PgPool; -use tower_http::services::ServeDir; + +use tower_http::services::{ServeDir, ServeFile}; mod auth; mod customers; @@ -55,9 +56,10 @@ async fn axum( let api_router = create_api_router(state); - let router = Router::new() - .nest("/api", api_router) - .nest_service("/", ServeDir::new("public")); + let router = Router::new().nest("/api", api_router).nest_service( + "/", + ServeDir::new("dist").not_found_service(ServeFile::new("dist/index.html")), + ); Ok(router.into()) } diff --git a/fullstack-templates/saas/next.config.js b/fullstack-templates/saas/next.config.js index 7951173e..45cc315c 100644 --- a/fullstack-templates/saas/next.config.js +++ b/fullstack-templates/saas/next.config.js @@ -3,7 +3,7 @@ const nextConfig = { reactStrictMode: true, output: "export", trailingSlash: true, - distDir: "./backend/public", + distDir: "./dist", images: { unoptimized: true, }, diff --git a/fullstack-templates/saas/package-lock.json b/fullstack-templates/saas/package-lock.json index 2bd0188a..5e734fb4 100644 --- a/fullstack-templates/saas/package-lock.json +++ b/fullstack-templates/saas/package-lock.json @@ -3530,7 +3530,7 @@ "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", "dependencies": { "loose-envify": "^1.1.0", - "scheduler": "^0.24.0" + "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" From f09baac0d8f61c2479293a61ab28e78658df1977 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 31 Jan 2024 12:04:57 +0100 Subject: [PATCH 131/239] chore: v0.38.0 (#134) --- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 6 +++--- axum/postgres/Cargo.toml | 6 +++--- axum/qdrant/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/static-next-server/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- axum/with-state/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 8 ++++---- next/hello-world/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 6 +++--- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 44 files changed, 107 insertions(+), 107 deletions(-) diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index fa578273..e278cd50 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.6.0" actix-session = { version = "0.8.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-actix-web = "0.38.0" +shuttle-runtime = "0.38.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index e8bed756..f5ce9f57 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-actix-web = "0.38.0" +shuttle-runtime = "0.38.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index ef5aefba..3b4bc1da 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-actix-web = "0.38.0" +shuttle-runtime = "0.38.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.37.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.38.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index 80cf2a1b..f07b28d2 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-actix-web = "0.38.0" +shuttle-runtime = "0.38.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 2c7761ed..7584fb5e 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-actix-web = "0.38.0" +shuttle-runtime = "0.38.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 2acfaa0e..c59c0d16 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-axum = "0.38.0" +shuttle-runtime = "0.38.0" tokio = "1.28.2" tracing = "0.1.40" diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index a98e1724..ab9cf97f 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-axum = "0.38.0" +shuttle-runtime = "0.38.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index 78d07289..307a3ba5 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.37.0" -shuttle-runtime = "0.37.0" -shuttle-metadata = "0.37.0" +shuttle-axum = "0.38.0" +shuttle-runtime = "0.38.0" +shuttle-metadata = "0.38.0" tokio = "1.28.2" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 7ee3fe9f..ecb3d577 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.37.0" -shuttle-runtime = "0.37.0" -shuttle-shared-db = { version = "0.37.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.38.0" +shuttle-runtime = "0.38.0" +shuttle-shared-db = { version = "0.38.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index 2f43d36c..800018c7 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.7.0" -shuttle-axum = "0.37.0" -shuttle-qdrant = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-axum = "0.38.0" +shuttle-qdrant = "0.38.0" +shuttle-runtime = "0.38.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 7b67c21f..bae240d3 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-axum = "0.38.0" +shuttle-runtime = "0.38.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index dd1d5f32..969d8f96 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-axum = "0.38.0" +shuttle-runtime = "0.38.0" tokio = "1.26.0" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 831440b9..c4fff21d 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.37.0" -shuttle-runtime = "0.37.0" -shuttle-turso = "0.37.0" +shuttle-axum = "0.38.0" +shuttle-runtime = "0.38.0" +shuttle-turso = "0.38.0" libsql = "0.2.0" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 3c46b5ec..1333d97d 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-axum = "0.38.0" +shuttle-runtime = "0.38.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index b01a6565..d12b7f28 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-axum = "0.38.0" +shuttle-runtime = "0.38.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index d0671f6a..810ec546 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.37.0" -shuttle-axum = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-service = "0.38.0" +shuttle-axum = "0.38.0" +shuttle-runtime = "0.38.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 4153900c..2ad16ec2 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.37.0" +shuttle-runtime = "0.38.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index 1b06f081..a3f8e48e 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -10,7 +10,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-persist = "0.38.0" +shuttle-runtime = "0.38.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 85e8fd5d..4637cad9 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,10 +16,10 @@ lettre = "0.10.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.37.0" -shuttle-runtime = "0.37.0" -shuttle-secrets = "0.37.0" -shuttle-shared-db = { version = "0.37.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.38.0" +shuttle-runtime = "0.38.0" +shuttle-secrets = "0.38.0" +shuttle-shared-db = { version = "0.38.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index a12c380a..4689e4cd 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.37.0" +shuttle-next = "0.38.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index c081af8d..73a59d30 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,7 +15,7 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = "0.37.0" -shuttle-runtime = "0.37.0" -shuttle-secrets = "0.37.0" +shuttle-axum = "0.38.0" +shuttle-runtime = "0.38.0" +shuttle-secrets = "0.38.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 8ae6a3c3..c9e662fc 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "2.0.0" -shuttle-poem = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-poem = "0.38.0" +shuttle-runtime = "0.38.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index e80a1d63..d00a6725 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "2.0.0" -shuttle-poem = "0.37.0" -shuttle-shared-db = { version = "0.37.0", features = ["mongodb"] } -shuttle-runtime = "0.37.0" +shuttle-poem = "0.38.0" +shuttle-shared-db = { version = "0.38.0", features = ["mongodb"] } +shuttle-runtime = "0.38.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 3183a76f..8bf9f4da 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "2.0.0" serde = "1.0.148" -shuttle-poem = "0.37.0" -shuttle-runtime = "0.37.0" -shuttle-shared-db = { version = "0.37.0", features = ["postgres", "sqlx"] } +shuttle-poem = "0.38.0" +shuttle-runtime = "0.38.0" +shuttle-shared-db = { version = "0.38.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 7a119b21..eb8543d6 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,9 +7,9 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.6.1" -shuttle-runtime = "0.37.0" -shuttle-secrets = "0.37.0" +shuttle-runtime = "0.38.0" +shuttle-secrets = "0.38.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity -shuttle-serenity = "0.37.0" +shuttle-serenity = "0.38.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index d9ca469d..b7a69e94 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-rocket = "0.38.0" +shuttle-runtime = "0.38.0" rocket_dyn_templates = { version = "0.1.0-rc.4", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index ce7724ca..07e8e07d 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-rocket = "0.38.0" +shuttle-runtime = "0.38.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 1a48e25c..40ef9b33 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-rocket = "0.38.0" +shuttle-runtime = "0.38.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index af3127e7..f06247b6 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.37.0" -shuttle-rocket = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-persist = "0.38.0" +shuttle-rocket = "0.38.0" +shuttle-runtime = "0.38.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 03f3e91a..6163e3b5 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.37.0" -shuttle-runtime = "0.37.0" -shuttle-shared-db = { version = "0.37.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.38.0" +shuttle-runtime = "0.38.0" +shuttle-shared-db = { version = "0.38.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 0171e106..9b61cb8f 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.37.0" -shuttle-runtime = "0.37.0" -shuttle-secrets = "0.37.0" +shuttle-rocket = "0.38.0" +shuttle-runtime = "0.38.0" +shuttle-secrets = "0.38.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index 55157c27..a482e89b 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-rocket = "0.38.0" +shuttle-runtime = "0.38.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index f720259a..458737e8 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" nanoid = "0.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.37.0" -shuttle-runtime = "0.37.0" -shuttle-shared-db = { version = "0.37.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.38.0" +shuttle-runtime = "0.38.0" +shuttle-shared-db = { version = "0.38.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 07f462d4..021ff731 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-rocket = "0.38.0" +shuttle-runtime = "0.38.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 7402a7f7..bcc9fa4d 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.63.0" -shuttle-salvo = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-salvo = "0.38.0" +shuttle-runtime = "0.38.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index e06204f3..621a995e 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.37.0" -shuttle-secrets = "0.37.0" -shuttle-serenity = "0.37.0" +shuttle-runtime = "0.38.0" +shuttle-secrets = "0.38.0" +shuttle-serenity = "0.38.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index d8ea5012..28c3d45c 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.37.0" -shuttle-secrets = "0.37.0" -shuttle-serenity = "0.37.0" -shuttle-shared-db = { version = "0.37.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.38.0" +shuttle-secrets = "0.38.0" +shuttle-serenity = "0.38.0" +shuttle-shared-db = { version = "0.38.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index a98b921c..a6696f9c 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-thruster = "0.38.0" +shuttle-runtime = "0.38.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 0281d839..4c8e6da8 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.37.0", features = ["postgres", "sqlx"] } -shuttle-runtime = "0.37.0" -shuttle-thruster = "0.37.0" +shuttle-aws-rds = { version = "0.38.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.38.0" +shuttle-thruster = "0.38.0" sqlx = "0.7.1" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 5f6f7308..69637f71 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.37.0" -shuttle-runtime = "0.37.0" +shuttle-tide = "0.38.0" +shuttle-runtime = "0.38.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index d5c26450..161f0244 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.37.0", features = ["postgres", "sqlx"] } -shuttle-runtime = "0.37.0" -shuttle-tide = "0.37.0" +shuttle-aws-rds = { version = "0.38.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.38.0" +shuttle-tide = "0.38.0" sqlx = "0.7.1" tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index f58c44b8..f97a3c86 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.37.0" -shuttle-tower = "0.37.0" +shuttle-runtime = "0.38.0" +shuttle-tower = "0.38.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index fb91b460..51c690b5 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.37.0" +shuttle-actix-web = "0.38.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.37.0", default-features = false } +shuttle-runtime = { version = "0.38.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = "0.3.17" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index c14d91e7..16092892 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.37.0" -shuttle-warp = "0.37.0" +shuttle-runtime = "0.38.0" +shuttle-warp = "0.38.0" tokio = "1.26.0" warp = "0.3.3" From d1441fa9a26ab5904ee0bf0ffeb5b5ad4259e237 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Fri, 2 Feb 2024 11:40:35 +0100 Subject: [PATCH 132/239] fix: saas template local run recommendation, npm update (#136) --- fullstack-templates/saas/README.md | 54 +- fullstack-templates/saas/package-lock.json | 2199 +++++++++++--------- fullstack-templates/saas/package.json | 19 +- 3 files changed, 1265 insertions(+), 1007 deletions(-) diff --git a/fullstack-templates/saas/README.md b/fullstack-templates/saas/README.md index 2c735c33..66cc3a54 100644 --- a/fullstack-templates/saas/README.md +++ b/fullstack-templates/saas/README.md @@ -1,45 +1,43 @@ -## Shuttle SaaS Example -### Introduction -This repo is meant to serve as a SaaS template with a Next.js Typescript frontend and a Rust backend. The design of the template internally is based on a sales-oriented Customer Relationship Management (CRM) tool where users will be able to view their customers, sales records as well as some analytics. +# Shuttle SaaS Example + +## Introduction + +This template is a SaaS template with a Next.js Typescript frontend and a Rust backend. +The design of the template internally is based on a sales-oriented Customer Relationship Management (CRM) tool where users will be able to view their customers, sales records as well as some analytics. + +## Features -### Features - Take subscription payments with Stripe - Email session-based login - Mailgun (email subscription, welcome email etc) - Pre-configured frontend routes for easy transition - Examples of how to implement simple dashboard analytics -### Pre-requisites - -* Rust - -* Node.js/NPM. - -* Typescript. +## Pre-requisites -* [cargo-shuttle](https://www.shuttle.rs) +- Rust +- Node.js/NPM. +- Typescript. +- [cargo-shuttle](https://www.shuttle.rs) -### Instructions for Usage +## Instructions for Usage -* Fork or clone the repo, then navigate to the folder where you cloned the repo: +- Initialize the template with +```sh +cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder fullstack-templates/saas ``` - git clone https://github.com/joshua-mo-143/shuttle-saas-example.git - cd shuttle-saas-example -``` - -* Run `npm i` to install the dependencies on the frontend. - -* Set your secrets in the Secrets.toml file at the `Cargo.toml` level of your backend folder (any that are unset will default to "None" to stop the web service from automatically crashing but some services may not work!) -* Run `npm run dev` and go to [http://localhost:8000](http://localhost:8000) once the app has built and you should see the following: +- cd into the folder +- Run `npm i` to install the dependencies on the frontend. +- Set your secrets in the Secrets.toml file at the `Cargo.toml` level of your backend folder (any that are unset will default to "None" to stop the web service from automatically crashing but some services may not work!) +- Run `npm run dev` and go to [http://localhost:8000](http://localhost:8000) once the app has built and you should see the following: +- You can also use `cargo-watch` with `cargo watch -- npm run dev` for reload-on-save (but not hot reload of the frontend). ![Main page for Next.js + Shuttle Saas Template](./Mainpage.png) -### Troubleshooting - -* If you change the migrations after running locally or deploying, you will need to go into the database itself and delete the tables. You can do this easily with something like [psql](https://www.postgresql.org/docs/current/app-psql.html) or [pgAdmin](https://www.pgadmin.org/). - -* If connecting to external services like Stripe doesn't work, try checking your Secrets.toml file. +## Troubleshooting -* Shuttle connects by default to port 8000 - if you're currently already using something at port 8000, you can add the `--port ` to the `cargo shuttle run` command to change this. \ No newline at end of file +- If you change the migrations after running locally or deploying, you will need to go into the database itself and delete the tables. You can do this easily with something like [psql](https://www.postgresql.org/docs/current/app-psql.html) or [pgAdmin](https://www.pgadmin.org/). +- If connecting to external services like Stripe doesn't work, try checking your Secrets.toml file. +- Shuttle connects by default to port 8000 - if you're currently already using something at port 8000, you can add the `--port ` to the `cargo shuttle run` command to change this. diff --git a/fullstack-templates/saas/package-lock.json b/fullstack-templates/saas/package-lock.json index 5e734fb4..ddf3633f 100644 --- a/fullstack-templates/saas/package-lock.json +++ b/fullstack-templates/saas/package-lock.json @@ -16,9 +16,8 @@ "@types/react-dom": "18.0.11", "autoprefixer": "10.4.14", "chart.js": "^4.3.0", - "concurrently": "^8.0.1", - "next": "13.3.0", - "postcss": "8.4.21", + "next": "13.5.6", + "postcss": "8.4.33", "react": "18.2.0", "react-chartjs-2": "^5.2.0", "react-dom": "18.2.0", @@ -31,12 +30,22 @@ "eslint-config-next": "13.3.0" } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@babel/runtime": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", - "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", + "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", + "dev": true, "dependencies": { - "regenerator-runtime": "^0.13.11" + "regenerator-runtime": "^0.14.0" }, "engines": { "node": ">=6.9.0" @@ -58,23 +67,23 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.0.tgz", - "integrity": "sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", - "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.1", + "espree": "^9.6.0", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -108,34 +117,34 @@ } }, "node_modules/@fortawesome/fontawesome-common-types": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz", - "integrity": "sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.1.tgz", + "integrity": "sha512-GkWzv+L6d2bI5f/Vk6ikJ9xtl7dfXtoRu3YGE6nq0p/FFqA1ebMOAWg3XgRyb0I6LYyYkiAo+3/KrwuBp8xG7A==", "hasInstallScript": true, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/fontawesome-svg-core": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.0.tgz", - "integrity": "sha512-Bertv8xOiVELz5raB2FlXDPKt+m94MQ3JgDfsVbrqNpLU9+UE2E18GKjLKw+d3XbeYPqg1pzyQKGsrzbw+pPaw==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.1.tgz", + "integrity": "sha512-MfRCYlQPXoLlpem+egxjfkEuP9UQswTrlCOsknus/NcMoblTH2g0jPrapbcIb04KGA7E2GZxbAccGZfWoYgsrQ==", "hasInstallScript": true, "peer": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "6.4.0" + "@fortawesome/fontawesome-common-types": "6.5.1" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-solid-svg-icons": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz", - "integrity": "sha512-kutPeRGWm8V5dltFP1zGjQOEAzaLZj4StdQhWVZnfGFCvAPVvHh8qk5bRrU4KXnRRRNni5tKQI9PBAdI6MP8nQ==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.1.tgz", + "integrity": "sha512-S1PPfU3mIJa59biTtXJz1oI0+KAXW6bkAb31XKhxdxtuXDiUIFsih4JR1v5BbxY7hVHsD1RKq+jRkVRaf773NQ==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "6.4.0" + "@fortawesome/fontawesome-common-types": "6.5.1" }, "engines": { "node": ">=6" @@ -154,13 +163,13 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { @@ -181,11 +190,52 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", @@ -200,9 +250,9 @@ } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", "engines": { "node": ">=6.0.0" } @@ -221,28 +271,23 @@ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", + "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" - }, "node_modules/@kurkle/color": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" }, "node_modules/@next/env": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.3.0.tgz", - "integrity": "sha512-AjppRV4uG3No7L1plinoTQETH+j2F10TEnrMfzbTUYwze5sBUPveeeBAPZPm8OkJZ1epq9OyYKhZrvbD6/9HCQ==" + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.6.tgz", + "integrity": "sha512-Yac/bV5sBGkkEXmAX5FWPS9Mmo2rthrOPRQQNfycJPkjUAUclomCPH7QFVCDQ4Mp2k2K1SSM6m0zrxYrOwtFQw==" }, "node_modules/@next/eslint-plugin-next": { "version": "13.3.0", @@ -253,30 +298,10 @@ "glob": "7.1.7" } }, - "node_modules/@next/eslint-plugin-next/node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@next/swc-darwin-arm64": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.3.0.tgz", - "integrity": "sha512-DmIQCNq6JtccLPPBzf0dgh2vzMWt5wjxbP71pCi5EWpWYE3MsP6FcRXi4MlAmFNDQOfcFXR2r7kBeG1LpZUh1w==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.6.tgz", + "integrity": "sha512-5nvXMzKtZfvcu4BhtV0KH1oGv4XEW+B+jOfmBdpFI3C7FrB/MfujRpWYSBBO64+qbW8pkZiSyQv9eiwnn5VIQA==", "cpu": [ "arm64" ], @@ -289,9 +314,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.3.0.tgz", - "integrity": "sha512-oQoqFa88OGgwnYlnAGHVct618FRI/749se0N3S8t9Bzdv5CRbscnO0RcX901+YnNK4Q6yeiizfgO3b7kogtsZg==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.6.tgz", + "integrity": "sha512-6cgBfxg98oOCSr4BckWjLLgiVwlL3vlLj8hXg2b+nDgm4bC/qVXXLfpLB9FHdoDu4057hzywbxKvmYGmi7yUzA==", "cpu": [ "x64" ], @@ -304,9 +329,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.3.0.tgz", - "integrity": "sha512-Wzz2p/WqAJUqTVoLo6H18WMeAXo3i+9DkPDae4oQG8LMloJ3if4NEZTnOnTUlro6cq+S/W4pTGa97nWTrOjbGw==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.6.tgz", + "integrity": "sha512-txagBbj1e1w47YQjcKgSU4rRVQ7uF29YpnlHV5xuVUsgCUf2FmyfJ3CPjZUvpIeXCJAoMCFAoGnbtX86BK7+sg==", "cpu": [ "arm64" ], @@ -319,9 +344,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.3.0.tgz", - "integrity": "sha512-xPVrIQOQo9WXJYgmoTlMnAD/HlR/1e1ZIWGbwIzEirXBVBqMARUulBEIKdC19zuvoJ477qZJgBDCKtKEykCpyQ==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.6.tgz", + "integrity": "sha512-cGd+H8amifT86ZldVJtAKDxUqeFyLWW+v2NlBULnLAdWsiuuN8TuhVBt8ZNpCqcAuoruoSWynvMWixTFcroq+Q==", "cpu": [ "arm64" ], @@ -334,9 +359,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.3.0.tgz", - "integrity": "sha512-jOFlpGuPD7W2tuXVJP4wt9a3cpNxWAPcloq5EfMJRiXsBBOjLVFZA7boXYxEBzSVgUiVVr1V9T0HFM7pULJ1qA==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.6.tgz", + "integrity": "sha512-Mc2b4xiIWKXIhBy2NBTwOxGD3nHLmq4keFk+d4/WL5fMsB8XdJRdtUlL87SqVCTSaf1BRuQQf1HvXZcy+rq3Nw==", "cpu": [ "x64" ], @@ -349,9 +374,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.3.0.tgz", - "integrity": "sha512-2OwKlzaBgmuet9XYHc3KwsEilzb04F540rlRXkAcjMHL7eCxB7uZIGtsVvKOnQLvC/elrUegwSw1+5f7WmfyOw==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.6.tgz", + "integrity": "sha512-CFHvP9Qz98NruJiUnCe61O6GveKKHpJLloXbDSWRhqhkJdZD2zU5hG+gtVJR//tyW897izuHpM6Gtf6+sNgJPQ==", "cpu": [ "x64" ], @@ -364,9 +389,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.3.0.tgz", - "integrity": "sha512-OeHiA6YEvndxT46g+rzFK/MQTfftKxJmzslERMu9LDdC6Kez0bdrgEYed5eXFK2Z1viKZJCGRlhd06rBusyztA==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.6.tgz", + "integrity": "sha512-aFv1ejfkbS7PUa1qVPwzDHjQWQtknzAZWGTKYIAaS4NMtBlk3VyA6AYn593pqNanlicewqyl2jUhQAaFV/qXsg==", "cpu": [ "arm64" ], @@ -379,9 +404,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.3.0.tgz", - "integrity": "sha512-4aB7K9mcVK1lYEzpOpqWrXHEZympU3oK65fnNcY1Qc4HLJFLJj8AViuqQd4jjjPNuV4sl8jAwTz3gN5VNGWB7w==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.6.tgz", + "integrity": "sha512-XqqpHgEIlBHvzwG8sp/JXMFkLAfGLqkbVsyN+/Ih1mR8INb6YCc2x/Mbwi6hsAgUnqQztz8cvEbHJUbSl7RHDg==", "cpu": [ "ia32" ], @@ -394,9 +419,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.3.0.tgz", - "integrity": "sha512-Reer6rkLLcoOvB0dd66+Y7WrWVFH7sEEkF/4bJCIfsSKnTStTYaHtwIJAwbqnt9I392Tqvku0KkoqZOryWV9LQ==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.6.tgz", + "integrity": "sha512-Cqfe1YmOS7k+5mGu92nl5ULkzpKuxJrP3+4AEuPmrpFZ3BHxTY3TnHmU1On3bFmFFs6FbTcdF58CCUProGpIGQ==", "cpu": [ "x64" ], @@ -440,36 +465,25 @@ "node": ">= 8" } }, - "node_modules/@pkgr/utils": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.3.1.tgz", - "integrity": "sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "is-glob": "^4.0.3", - "open": "^8.4.0", - "picocolors": "^1.0.0", - "tiny-glob": "^0.2.9", - "tslib": "^2.4.0" - }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" + "node": ">=14" } }, "node_modules/@rushstack/eslint-patch": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", - "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.7.2.tgz", + "integrity": "sha512-RbhOOTCNoCrbfkRyoXODZp75MlpiHMgbE5MEBZAnnnLyQNgrigEj4p0lzsMDyc1zVsJDLrivB58tgg3emX0eEA==", "dev": true }, "node_modules/@swc/helpers": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", - "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz", + "integrity": "sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==", "dependencies": { "tslib": "^2.4.0" } @@ -486,9 +500,9 @@ "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==" }, "node_modules/@types/prop-types": { - "version": "15.7.5", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", - "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + "version": "15.7.11", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", + "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" }, "node_modules/@types/react": { "version": "18.0.35", @@ -509,19 +523,19 @@ } }, "node_modules/@types/scheduler": { - "version": "0.16.3", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", - "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" }, "node_modules/@typescript-eslint/parser": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.0.tgz", - "integrity": "sha512-qK9TZ70eJtjojSUMrrEwA9ZDQ4N0e/AuoOIgXuNBorXYcBDk397D2r5MIe1B3cok/oCtdNC5j+lUUpVB+Dpb+w==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.59.0", - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/typescript-estree": "5.59.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", "debug": "^4.3.4" }, "engines": { @@ -541,13 +555,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.0.tgz", - "integrity": "sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/visitor-keys": "5.59.0" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -558,9 +572,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", - "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -571,13 +585,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.0.tgz", - "integrity": "sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/visitor-keys": "5.59.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -598,12 +612,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", - "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/types": "5.62.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -615,9 +629,9 @@ } }, "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -702,12 +716,12 @@ "dev": true }, "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", "dev": true, "dependencies": { - "deep-equal": "^2.0.5" + "dequal": "^2.0.3" } }, "node_modules/array-buffer-byte-length": { @@ -724,15 +738,15 @@ } }, "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", + "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", "is-string": "^1.0.7" }, "engines": { @@ -751,15 +765,34 @@ "node": ">=8" } }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", + "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -770,14 +803,14 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -788,24 +821,54 @@ } }, "node_modules/array.prototype.tosorted": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", - "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz", + "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.1.3" + "get-intrinsic": "^1.2.1" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", "dev": true }, + "node_modules/asynciterator.prototype": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", + "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + } + }, "node_modules/autoprefixer": { "version": "10.4.14", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", @@ -860,12 +923,12 @@ } }, "node_modules/axobject-query": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", - "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", + "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", "dev": true, "dependencies": { - "deep-equal": "^2.0.5" + "dequal": "^2.0.3" } }, "node_modules/balanced-match": { @@ -885,6 +948,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -902,9 +966,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "version": "4.22.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", + "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", "funding": [ { "type": "opencollective", @@ -913,13 +977,17 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" + "caniuse-lite": "^1.0.30001580", + "electron-to-chromium": "^1.4.648", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" }, "bin": { "browserslist": "cli.js" @@ -940,13 +1008,14 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -970,9 +1039,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001478", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001478.tgz", - "integrity": "sha512-gMhDyXGItTHipJj2ApIvR+iVB5hd0KP3svMWWXDvZOmjzJJassGLMfxRkQCSYgGd2gtdL/ReeiyvMSFD1Ss6Mw==", + "version": "1.0.30001581", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001581.tgz", + "integrity": "sha512-whlTkwhqV2tUmP3oYhtNfaWGYHDdS3JYFQBKXxcUR9qqPWsRhFHhoISO2Xnl/g0xyKzht9mI1LZpiNWfMzHixQ==", "funding": [ { "type": "opencollective", @@ -992,6 +1061,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -1004,9 +1074,9 @@ } }, "node_modules/chart.js": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.3.0.tgz", - "integrity": "sha512-ynG0E79xGfMaV2xAHdbhwiPLczxnNNnasrmPEXriXsPJGjmhOBYzFVEsB65w2qMDz+CaBJJuJD0inE/ab/h36g==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.1.tgz", + "integrity": "sha512-C74QN1bxwV1v2PEujhmKjOZ7iUM4w6BWs23Md/6aOZZSlwMzeCIDGuZay++rBgChYru7/+QFeoQW0fQoP534Dg==", "dependencies": { "@kurkle/color": "^0.3.0" }, @@ -1056,19 +1126,6 @@ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1096,53 +1153,13 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/concurrently": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.0.1.tgz", - "integrity": "sha512-Sh8bGQMEL0TAmAm2meAXMjcASHZa7V0xXQVDBLknCPa9TPtkY9yYs+0cnGGgfdkW0SV1Mlg+hVGfXcoI8d3MJA==", - "dependencies": { - "chalk": "^4.1.2", - "date-fns": "^2.29.3", - "lodash": "^4.17.21", - "rxjs": "^7.8.0", - "shell-quote": "^1.8.0", - "spawn-command": "0.0.2-1", - "supports-color": "^8.1.1", - "tree-kill": "^1.2.2", - "yargs": "^17.7.1" - }, - "bin": { - "conc": "dist/bin/concurrently.js", - "concurrently": "dist/bin/concurrently.js" - }, - "engines": { - "node": "^14.13.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" - } - }, - "node_modules/concurrently/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1164,9 +1181,9 @@ } }, "node_modules/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/damerau-levenshtein": { "version": "1.0.8", @@ -1174,21 +1191,6 @@ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true }, - "node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "dependencies": { - "@babel/runtime": "^7.21.0" - }, - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -1206,55 +1208,33 @@ } } }, - "node_modules/deep-equal": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", - "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.2", - "get-intrinsic": "^1.1.3", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.1", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -1265,6 +1245,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -1299,21 +1288,25 @@ "node": ">=6.0.0" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, "node_modules/electron-to-chromium": { - "version": "1.4.365", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.365.tgz", - "integrity": "sha512-FRHZO+1tUNO4TOPXmlxetkoaIY8uwHzd1kKopK/Gx2SKn1L47wJXWD44wxP5CGRyyP98z/c8e1eBzJrgPeiBOg==" + "version": "1.4.651", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.651.tgz", + "integrity": "sha512-jjks7Xx+4I7dslwsbaFocSwqBbGHQmuXBJUK9QBZTIrzPq3pzn6Uf2szFSP728FtLYE3ldiccmlkOM/zhGKCpA==" }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "node_modules/enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -1324,25 +1317,26 @@ } }, "node_modules/es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "call-bind": "^1.0.5", "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.2", "get-symbol-description": "^1.0.0", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has": "^1.0.3", "has-property-descriptors": "^1.0.0", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", + "hasown": "^2.0.0", "internal-slot": "^1.0.5", "is-array-buffer": "^3.0.2", "is-callable": "^1.2.7", @@ -1350,19 +1344,23 @@ "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", + "is-typed-array": "^1.1.12", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", "typed-array-length": "^1.0.4", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" + "which-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -1371,47 +1369,49 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "node_modules/es-iterator-helpers": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz", + "integrity": "sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==", "dev": true, "dependencies": { + "asynciterator.prototype": "^1.0.0", "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.1", + "es-set-tostringtag": "^2.0.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "internal-slot": "^1.0.5", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.0.1" } }, "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" } }, "node_modules/es-to-primitive": { @@ -1535,14 +1535,14 @@ } }, "node_modules/eslint-import-resolver-node": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", - "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, "dependencies": { "debug": "^3.2.7", - "is-core-module": "^2.11.0", - "resolve": "^1.22.1" + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, "node_modules/eslint-import-resolver-node/node_modules/debug": { @@ -1555,19 +1555,18 @@ } }, "node_modules/eslint-import-resolver-typescript": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.5.tgz", - "integrity": "sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", "dev": true, "dependencies": { "debug": "^4.3.4", "enhanced-resolve": "^5.12.0", "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", "get-tsconfig": "^4.5.0", - "globby": "^13.1.3", "is-core-module": "^2.11.0", - "is-glob": "^4.0.3", - "synckit": "^0.8.5" + "is-glob": "^4.0.3" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -1580,37 +1579,6 @@ "eslint-plugin-import": "*" } }, - "node_modules/eslint-import-resolver-typescript/node_modules/globby": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.4.tgz", - "integrity": "sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==", - "dev": true, - "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.11", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-import-resolver-typescript/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint-module-utils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", @@ -1638,26 +1606,28 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.27.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", - "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", "dev": true, "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.7.4", - "has": "^1.0.3", - "is-core-module": "^2.11.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.values": "^1.1.6", - "resolve": "^1.22.1", - "semver": "^6.3.0", - "tsconfig-paths": "^3.14.1" + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" @@ -1688,36 +1658,36 @@ } }, "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", - "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.20.7", - "aria-query": "^5.1.3", - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "ast-types-flow": "^0.0.7", - "axe-core": "^4.6.2", - "axobject-query": "^3.1.1", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", + "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.23.2", + "aria-query": "^5.3.0", + "array-includes": "^3.1.7", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "=4.7.0", + "axobject-query": "^3.2.1", "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", - "has": "^1.0.3", - "jsx-ast-utils": "^3.3.3", - "language-tags": "=1.0.5", + "es-iterator-helpers": "^1.0.15", + "hasown": "^2.0.0", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "semver": "^6.3.0" + "object.entries": "^1.1.7", + "object.fromentries": "^2.0.7" }, "engines": { "node": ">=4.0" @@ -1726,25 +1696,17 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/eslint-plugin-react": { - "version": "7.32.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", - "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", + "version": "7.33.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", + "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", "dev": true, "dependencies": { "array-includes": "^3.1.6", "array.prototype.flatmap": "^1.3.1", "array.prototype.tosorted": "^1.1.1", "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.12", "estraverse": "^5.3.0", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", @@ -1754,7 +1716,7 @@ "object.values": "^1.1.6", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.4", - "semver": "^6.3.0", + "semver": "^6.3.1", "string.prototype.matchall": "^4.0.8" }, "engines": { @@ -1789,12 +1751,12 @@ } }, "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", - "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", "dev": true, "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -1806,18 +1768,18 @@ } }, "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -1831,9 +1793,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", - "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1843,14 +1805,14 @@ } }, "node_modules/espree": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", - "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "dependencies": { - "acorn": "^8.8.0", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.0" + "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1908,9 +1870,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -1946,9 +1908,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz", + "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==", "dependencies": { "reusify": "^1.0.4" } @@ -1993,12 +1955,13 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "dependencies": { - "flatted": "^3.1.0", + "flatted": "^3.2.9", + "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { @@ -2006,9 +1969,9 @@ } }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, "node_modules/for-each": { @@ -2020,27 +1983,43 @@ "is-callable": "^1.1.3" } }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/fraction.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", "engines": { "node": "*" }, "funding": { "type": "patreon", - "url": "https://www.patreon.com/infusion" + "url": "https://github.com/sponsors/rawify" } }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "hasInstallScript": true, "optional": true, "os": [ @@ -2051,20 +2030,23 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" }, "engines": { "node": ">= 0.4" @@ -2082,23 +2064,16 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2121,18 +2096,22 @@ } }, "node_modules/get-tsconfig": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.5.0.tgz", - "integrity": "sha512-MjhiaIWCJ1sAU4pIQ5i5OfOuHHxVo1oYeNsWTON7jxYkod8pHocXeh+SSbmu5OZZZK73B6cbJ2XADzXehLyovQ==", + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", + "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, "funding": { "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2159,10 +2138,15 @@ "node": ">=10.13.0" } }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, "node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -2189,12 +2173,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/globalyzer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", - "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==", - "dev": true - }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -2215,12 +2193,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globrex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", - "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", - "dev": true - }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -2236,8 +2208,7 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/grapheme-splitter": { "version": "1.0.4", @@ -2245,17 +2216,6 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -2269,17 +2229,18 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "get-intrinsic": "^1.2.2" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2324,10 +2285,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true, "engines": { "node": ">= 4" @@ -2362,6 +2334,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -2370,47 +2343,47 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "get-intrinsic": "^1.2.2", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { "node": ">= 0.4" } }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2468,11 +2441,11 @@ } }, "node_modules/is-core-module": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", - "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2493,21 +2466,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2516,6 +2474,18 @@ "node": ">=0.10.0" } }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -2524,6 +2494,21 @@ "node": ">=8" } }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -2656,16 +2641,12 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "which-typed-array": "^1.1.11" }, "engines": { "node": ">= 0.4" @@ -2708,18 +2689,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", @@ -2729,21 +2698,50 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } }, "node_modules/jiti": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.18.2.tgz", - "integrity": "sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", "bin": { "jiti": "bin/jiti.js" } }, "node_modules/js-sdsl": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", - "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.2.tgz", + "integrity": "sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==", "dev": true, "funding": { "type": "opencollective", @@ -2767,6 +2765,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -2792,18 +2796,29 @@ } }, "node_modules/jsx-ast-utils": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", - "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", "dev": true, "dependencies": { - "array-includes": "^3.1.5", - "object.assign": "^4.1.3" + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" }, "engines": { "node": ">=4.0" } }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/language-subtag-registry": { "version": "0.3.22", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", @@ -2811,12 +2826,15 @@ "dev": true }, "node_modules/language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", "dev": true, "dependencies": { - "language-subtag-registry": "~0.3.2" + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" } }, "node_modules/levn": { @@ -2860,11 +2878,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -2918,6 +2931,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2934,6 +2948,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -2951,9 +2973,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "funding": [ { "type": "github", @@ -2974,38 +2996,37 @@ "dev": true }, "node_modules/next": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/next/-/next-13.3.0.tgz", - "integrity": "sha512-OVTw8MpIPa12+DCUkPqRGPS3thlJPcwae2ZL4xti3iBff27goH024xy4q2lhlsdoYiKOi8Kz6uJoLW/GXwgfOA==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/next/-/next-13.5.6.tgz", + "integrity": "sha512-Y2wTcTbO4WwEsVb4A8VSnOsG1I9ok+h74q0ZdxkwM3EODqrs4pasq7O0iUxbcS9VtWMicG7f3+HAj0r1+NtKSw==", "dependencies": { - "@next/env": "13.3.0", - "@swc/helpers": "0.4.14", + "@next/env": "13.5.6", + "@swc/helpers": "0.5.2", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", - "postcss": "8.4.14", - "styled-jsx": "5.1.1" + "postcss": "8.4.31", + "styled-jsx": "5.1.1", + "watchpack": "2.4.0" }, "bin": { "next": "dist/bin/next" }, "engines": { - "node": ">=14.6.0" + "node": ">=16.14.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "13.3.0", - "@next/swc-darwin-x64": "13.3.0", - "@next/swc-linux-arm64-gnu": "13.3.0", - "@next/swc-linux-arm64-musl": "13.3.0", - "@next/swc-linux-x64-gnu": "13.3.0", - "@next/swc-linux-x64-musl": "13.3.0", - "@next/swc-win32-arm64-msvc": "13.3.0", - "@next/swc-win32-ia32-msvc": "13.3.0", - "@next/swc-win32-x64-msvc": "13.3.0" + "@next/swc-darwin-arm64": "13.5.6", + "@next/swc-darwin-x64": "13.5.6", + "@next/swc-linux-arm64-gnu": "13.5.6", + "@next/swc-linux-arm64-musl": "13.5.6", + "@next/swc-linux-x64-gnu": "13.5.6", + "@next/swc-linux-x64-musl": "13.5.6", + "@next/swc-win32-arm64-msvc": "13.5.6", + "@next/swc-win32-ia32-msvc": "13.5.6", + "@next/swc-win32-x64-msvc": "13.5.6" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", - "fibers": ">= 3.1.0", - "node-sass": "^6.0.0 || ^7.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", "sass": "^1.3.0" @@ -3014,21 +3035,15 @@ "@opentelemetry/api": { "optional": true }, - "fibers": { - "optional": true - }, - "node-sass": { - "optional": true - }, "sass": { "optional": true } } }, "node_modules/next/node_modules/postcss": { - "version": "8.4.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", - "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "funding": [ { "type": "opencollective", @@ -3037,10 +3052,14 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -3049,9 +3068,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" }, "node_modules/normalize-path": { "version": "3.0.0", @@ -3086,26 +3105,10 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3120,13 +3123,13 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -3138,28 +3141,28 @@ } }, "node_modules/object.entries": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", - "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", + "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" } }, "node_modules/object.fromentries": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", - "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", + "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" @@ -3168,28 +3171,40 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object.groupby": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", + "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1" + } + }, "node_modules/object.hasown": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", - "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz", + "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==", "dev": true, "dependencies": { - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" @@ -3202,39 +3217,23 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", "dev": true, "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "wrappy": "1" } }, "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "type-check": "^0.4.0" }, "engines": { "node": ">= 0.8.0" @@ -3295,6 +3294,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -3303,7 +3303,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -3313,6 +3312,29 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "engines": { + "node": "14 || >=16.14" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -3347,17 +3369,17 @@ } }, "node_modules/pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "engines": { "node": ">= 6" } }, "node_modules/postcss": { - "version": "8.4.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", - "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "version": "8.4.33", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", + "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", "funding": [ { "type": "opencollective", @@ -3366,10 +3388,14 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -3411,28 +3437,56 @@ "postcss": "^8.4.21" } }, - "node_modules/postcss-nested": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz", - "integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==", + "node_modules/postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", "dependencies": { - "postcss-selector-parser": "^6.0.10" + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" }, "engines": { - "node": ">=12.0" + "node": ">= 10" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/postcss/" }, "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", - "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz", + "integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.15", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", + "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -3466,9 +3520,9 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" @@ -3560,20 +3614,18 @@ "node": ">=8.10.0" } }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, - "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "node_modules/reflect.getprototypeof": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", + "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" }, "engines": { "node": ">= 0.4" @@ -3582,20 +3634,35 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/resolve": { - "version": "1.22.3", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.3.tgz", - "integrity": "sha512-P8ur/gp/AmbEzjr729bZnLjXK5Z+4P0zhIJgBgzqRih7hL7BOukHGtSTA3ACMY467GRFz3duQsi0bDZdR7DKdw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dependencies": { - "is-core-module": "^2.12.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -3615,6 +3682,15 @@ "node": ">=4" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -3661,24 +3737,37 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "node_modules/safe-array-concat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", + "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", + "dev": true, "dependencies": { - "tslib": "^2.1.0" + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.2.tgz", + "integrity": "sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", "is-regex": "^1.1.4" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3692,9 +3781,9 @@ } }, "node_modules/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -3706,11 +3795,40 @@ "node": ">=10" } }, + "node_modules/set-function-length": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", + "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.1", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.2", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -3722,19 +3840,10 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } }, - "node_modules/shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -3749,6 +3858,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -3766,23 +3886,6 @@ "node": ">=0.10.0" } }, - "node_modules/spawn-command": { - "version": "0.0.2-1", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", - "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==" - }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, - "dependencies": { - "internal-slot": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -3792,6 +3895,23 @@ } }, "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", @@ -3804,24 +3924,50 @@ "node": ">=8" } }, - "node_modules/string-width/node_modules/emoji-regex": { + "node_modules/string-width-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/string.prototype.matchall": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", - "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", + "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.3", + "internal-slot": "^1.0.5", + "regexp.prototype.flags": "^1.5.0", + "set-function-name": "^2.0.0", "side-channel": "^1.0.4" }, "funding": { @@ -3829,14 +3975,14 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" @@ -3846,28 +3992,28 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3884,6 +4030,18 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -3928,13 +4086,13 @@ } }, "node_modules/sucrase": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.32.0.tgz", - "integrity": "sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==", + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", - "glob": "7.1.6", + "glob": "^10.3.10", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", @@ -3945,13 +4103,57 @@ "sucrase-node": "bin/sucrase-node" }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sucrase/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -3970,22 +4172,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/synckit": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", - "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", - "dev": true, - "dependencies": { - "@pkgr/utils": "^2.3.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, "node_modules/tailwindcss": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.1.tgz", @@ -4027,34 +4213,6 @@ "postcss": "^8.0.9" } }, - "node_modules/tailwindcss/node_modules/postcss-load-config": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", - "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", - "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" - }, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -4089,16 +4247,6 @@ "node": ">=0.8" } }, - "node_modules/tiny-glob": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", - "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", - "dev": true, - "dependencies": { - "globalyzer": "0.1.0", - "globrex": "^0.1.2" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -4110,23 +4258,15 @@ "node": ">=8.0" } }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "bin": { - "tree-kill": "cli.js" - } - }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" }, "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "dependencies": { "@types/json5": "^0.0.29", @@ -4136,9 +4276,9 @@ } }, "node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -4185,6 +4325,57 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typed-array-length": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", @@ -4227,9 +4418,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "funding": [ { "type": "opencollective", @@ -4277,11 +4468,22 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -4308,6 +4510,32 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/which-collection": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", @@ -4324,17 +4552,16 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", "dev": true, "dependencies": { "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "call-bind": "^1.0.4", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -4343,16 +4570,24 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi": { + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", @@ -4368,19 +4603,66 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "engines": { - "node": ">=10" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -4395,31 +4677,6 @@ "node": ">= 6" } }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "engines": { - "node": ">=12" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -4433,9 +4690,9 @@ } }, "node_modules/zustand": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.3.7.tgz", - "integrity": "sha512-dY8ERwB9Nd21ellgkBZFhudER8KVlelZm8388B5nDAXhO/+FZDhYMuRnqDgu5SYyRgz/iaf8RKnbUs/cHfOGlQ==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.0.tgz", + "integrity": "sha512-zlVFqS5TQ21nwijjhJlx4f9iGrXSL0o/+Dpy4txAP22miJ8Ti6c1Ol1RLNN98BMib83lmDH/2KmLwaNXpjrO1A==", "dependencies": { "use-sync-external-store": "1.2.0" }, @@ -4443,10 +4700,14 @@ "node": ">=12.7.0" }, "peerDependencies": { - "immer": ">=9.0", + "@types/react": ">=16.8", + "immer": ">=9.0.6", "react": ">=16.8" }, "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, "immer": { "optional": true }, diff --git a/fullstack-templates/saas/package.json b/fullstack-templates/saas/package.json index 641b3dc4..e23a1f65 100644 --- a/fullstack-templates/saas/package.json +++ b/fullstack-templates/saas/package.json @@ -3,13 +3,13 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "npm run build && concurrently --names 'next, shuttle' --kill-others 'next dev' 'cargo shuttle run --working-directory ./backend/'", - "build": "next build && cargo build --manifest-path ./backend/Cargo.toml", - "shuttle-login": "cargo shuttle login --working-directory ./backend/", - "full": "cargo shuttle run --working-directory backend --port 8001", - "start": "cargo shuttle project start --working-directory ./backend/", - "stop": "cargo shuttle project stop --working-directory ./backend/", - "deploy": "npm run build && cargo shuttle deploy --working-directory ./backend/ --allow-dirty", + "dev": "next build && cargo shuttle run", + "build": "next build && cargo build", + "shuttle-login": "cargo shuttle login", + "full": "cargo shuttle run --port 8001", + "start": "cargo shuttle project start", + "stop": "cargo shuttle project stop", + "deploy": "npm run build && cargo shuttle deploy --allow-dirty", "lint": "next lint" }, "dependencies": { @@ -21,9 +21,8 @@ "@types/react-dom": "18.0.11", "autoprefixer": "10.4.14", "chart.js": "^4.3.0", - "concurrently": "^8.0.1", - "next": "13.3.0", - "postcss": "8.4.21", + "next": "13.5.6", + "postcss": "8.4.33", "react": "18.2.0", "react-chartjs-2": "^5.2.0", "react-dom": "18.2.0", From a37ef6287a9e4a5b4eab20f86f3f614546258279 Mon Sep 17 00:00:00 2001 From: Marvin Juraschka Date: Thu, 8 Feb 2024 12:37:51 +0100 Subject: [PATCH 133/239] SaaS: NextJS14, Turbowatch, Bundle Anaylzer (#137) * NextJS updated to version 14, also Turbowatch was added which should create a similar function as concurrently before. This is a response to the implementation of https://github.com/shuttle-hq/shuttle-examples/pull/136 * Added comment for .secure(!cfg!(debug_assertions)) and removed --working-directory since it's not needed in a workspace * Added cross-env for windows support * Added cross-env for windows support * Updated filter * Added npm exec to the command * turbowatch.ts script updated and tested under Windows * turbowatch.ts script updated and tested under Windows * turbowatch.ts script updated and tested under Windows * Clippy fix? * Renamed runtime to cli since shuttle runtime is a different thing * Explanations for new functions in the README.md * Added missing retry limit for frontend trigger --------- Co-authored-by: Marvin Juraschka --- fullstack-templates/saas/README.md | 41 +- fullstack-templates/saas/backend/Cargo.toml | 6 +- fullstack-templates/saas/backend/src/auth.rs | 2 +- fullstack-templates/saas/next.config.js | 24 +- fullstack-templates/saas/package-lock.json | 1349 ++++++++++++++--- fullstack-templates/saas/package.json | 21 +- .../saas/src/components/AuthedLayout.tsx | 2 +- .../src/components/CustomerSingleModal.tsx | 128 +- .../src/components/DealSingleModal copy.tsx | 106 +- .../saas/src/components/Layout.tsx | 2 +- .../saas/src/components/navbar.tsx | 2 +- .../src/pages/dashboard/customers/[id].tsx | 167 +- .../src/pages/dashboard/customers/create.tsx | 2 +- .../src/pages/dashboard/customers/index.tsx | 2 +- .../saas/src/pages/dashboard/deals/create.tsx | 2 +- .../saas/src/pages/dashboard/deals/index.tsx | 2 +- .../saas/src/pages/dashboard/index.tsx | 2 +- .../dashboard/upgrade/checkout/index.tsx | 329 ++-- fullstack-templates/saas/src/pages/login.tsx | 212 +-- .../saas/src/{ => stores}/zustandStore.ts | 0 fullstack-templates/saas/turbowatch.ts | 121 ++ 21 files changed, 1769 insertions(+), 753 deletions(-) rename fullstack-templates/saas/src/{ => stores}/zustandStore.ts (100%) create mode 100644 fullstack-templates/saas/turbowatch.ts diff --git a/fullstack-templates/saas/README.md b/fullstack-templates/saas/README.md index 66cc3a54..f11521b0 100644 --- a/fullstack-templates/saas/README.md +++ b/fullstack-templates/saas/README.md @@ -3,7 +3,8 @@ ## Introduction This template is a SaaS template with a Next.js Typescript frontend and a Rust backend. -The design of the template internally is based on a sales-oriented Customer Relationship Management (CRM) tool where users will be able to view their customers, sales records as well as some analytics. +The design of the template internally is based on a sales-oriented Customer Relationship Management (CRM) tool where +users will be able to view their customers, sales records as well as some analytics. ## Features @@ -22,22 +23,42 @@ The design of the template internally is based on a sales-oriented Customer Rela ## Instructions for Usage -- Initialize the template with +- Initialize the template with: -```sh -cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder fullstack-templates/saas -``` + ```sh + cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder fullstack-templates/saas + ``` - cd into the folder - Run `npm i` to install the dependencies on the frontend. -- Set your secrets in the Secrets.toml file at the `Cargo.toml` level of your backend folder (any that are unset will default to "None" to stop the web service from automatically crashing but some services may not work!) -- Run `npm run dev` and go to [http://localhost:8000](http://localhost:8000) once the app has built and you should see the following: -- You can also use `cargo-watch` with `cargo watch -- npm run dev` for reload-on-save (but not hot reload of the frontend). +- Set your secrets in the Secrets.toml file at the `Cargo.toml` level of your backend folder. Unset secrets will default + to "None" to prevent automatic crashing of the web service, but some services may not work. + +## Development Scripts + +- **Using `dev` for Development:** + - Run `npm run dev` to start your application with live reload capabilities. This script uses `turbowatch` to + monitor changes in both the frontend and backend. + - Visit [http://localhost:8000](http://localhost:8000) once the app has built. + - If you prefer using `cargo-watch` instead of `turbowatch`, the watch feature can be disabled in + the `turbowatch.ts` file. +- **Frontend-Focused Development with `next-dev`:** + - For a frontend-specific development workflow, use `npm run next-dev`. + - This script runs Next.js in a development mode optimized for faster builds and reloads, enhancing your frontend + development experience. +- **Analyzing Bundle Size with `analyze`:** + - The `analyze` script is designed to provide insights into the bundle size of your Next.js application. + - Run `npm run analyze` to generate a detailed report of the size of each component and dependency in your bundle. + - This is particularly useful for identifying large dependencies or components that could be optimized for better + performance. ![Main page for Next.js + Shuttle Saas Template](./Mainpage.png) ## Troubleshooting -- If you change the migrations after running locally or deploying, you will need to go into the database itself and delete the tables. You can do this easily with something like [psql](https://www.postgresql.org/docs/current/app-psql.html) or [pgAdmin](https://www.pgadmin.org/). +- If you change the migrations after running locally or deploying, you will need to go into the database itself and + delete the tables. You can do this easily with something + like [psql](https://www.postgresql.org/docs/current/app-psql.html) or [pgAdmin](https://www.pgadmin.org/). - If connecting to external services like Stripe doesn't work, try checking your Secrets.toml file. -- Shuttle connects by default to port 8000 - if you're currently already using something at port 8000, you can add the `--port ` to the `cargo shuttle run` command to change this. +- Shuttle connects by default to port 8000 - if you're currently already using something at port 8000, you can add + the `--port ` to the `cargo shuttle run` command to change this. diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 8f85c327..cf6bbeef 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -6,13 +6,13 @@ publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -async-stripe = { version = "0.21.0", features = ["runtime-tokio-hyper"] } +async-stripe = { version = "0.31.0", features = ["runtime-tokio-hyper"] } axum = "0.7.3" axum-extra = { version = "0.9.1", features = ["cookie-private"] } axum-macros = "0.4.0" -bcrypt = "0.14.0" +bcrypt = "0.15.0" http = "1.0.0" -lettre = "0.10.4" +lettre = "0.11.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } diff --git a/fullstack-templates/saas/backend/src/auth.rs b/fullstack-templates/saas/backend/src/auth.rs index 74f5cca3..46b516fb 100644 --- a/fullstack-templates/saas/backend/src/auth.rs +++ b/fullstack-templates/saas/backend/src/auth.rs @@ -74,7 +74,7 @@ pub async fn login( .expect("Couldn't insert session :("); let cookie = Cookie::build(("foo", session_id)) - .secure(true) + .secure(!cfg!(debug_assertions)) // Only send the cookie over HTTPS in production .same_site(SameSite::Strict) .http_only(true) .path("/") diff --git a/fullstack-templates/saas/next.config.js b/fullstack-templates/saas/next.config.js index 45cc315c..fd110d53 100644 --- a/fullstack-templates/saas/next.config.js +++ b/fullstack-templates/saas/next.config.js @@ -1,12 +1,22 @@ /** @type {import('next').NextConfig} */ const nextConfig = { - reactStrictMode: true, - output: "export", - trailingSlash: true, - distDir: "./dist", + reactStrictMode: true, + trailingSlash: true, + + // Export settings + output: "export", + distDir: "./dist", + + // Optimization settings images: { - unoptimized: true, - }, + unoptimized: true, + }, } -module.exports = nextConfig +// Bundle analyzer settings +const withBundleAnalyzer = require('@next/bundle-analyzer')({ + enabled: process.env.ANALYZE === 'true', +}); + +// Export the configuration +module.exports = withBundleAnalyzer(nextConfig); diff --git a/fullstack-templates/saas/package-lock.json b/fullstack-templates/saas/package-lock.json index ddf3633f..15fe87db 100644 --- a/fullstack-templates/saas/package-lock.json +++ b/fullstack-templates/saas/package-lock.json @@ -10,24 +10,27 @@ "dependencies": { "@faker-js/faker": "^7.6.0", "@fortawesome/free-solid-svg-icons": "^6.4.0", - "@fortawesome/react-fontawesome": "github:fortawesome/react-fontawesome", + "@fortawesome/react-fontawesome": "^0.2.0", "@types/node": "18.15.11", - "@types/react": "18.0.35", - "@types/react-dom": "18.0.11", + "@types/react": "^18.2.53", + "@types/react-dom": "^18.2.18", "autoprefixer": "10.4.14", "chart.js": "^4.3.0", - "next": "13.5.6", + "next": "^14.1.0", "postcss": "8.4.33", - "react": "18.2.0", + "react": "^18.2.0", "react-chartjs-2": "^5.2.0", - "react-dom": "18.2.0", + "react-dom": "^18.2.0", "tailwindcss": "3.3.1", + "turbowatch": "^2.29.4", "typescript": "5.0.4", "zustand": "^4.3.7" }, "devDependencies": { + "@next/bundle-analyzer": "^14.1.0", + "cross-env": "^7.0.3", "eslint": "8.38.0", - "eslint-config-next": "13.3.0" + "eslint-config-next": "^14.1.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -51,6 +54,15 @@ "node": ">=6.9.0" } }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -152,8 +164,8 @@ }, "node_modules/@fortawesome/react-fontawesome": { "version": "0.2.0", - "resolved": "git+ssh://git@github.com/fortawesome/react-fontawesome.git#976c1adc59934b34e52b11c03dda4bd69831a6df", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz", + "integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==", "dependencies": { "prop-types": "^15.8.1" }, @@ -284,24 +296,33 @@ "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" }, + "node_modules/@next/bundle-analyzer": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-14.1.0.tgz", + "integrity": "sha512-RJWjnlMp/1WSW0ahAdawV22WgJiC6BVaFS5Xfhw6gP7NJEX3cAJjh4JqSHKGr8GnLNRaFCVTQdDPoX84E421BA==", + "dev": true, + "dependencies": { + "webpack-bundle-analyzer": "4.10.1" + } + }, "node_modules/@next/env": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.6.tgz", - "integrity": "sha512-Yac/bV5sBGkkEXmAX5FWPS9Mmo2rthrOPRQQNfycJPkjUAUclomCPH7QFVCDQ4Mp2k2K1SSM6m0zrxYrOwtFQw==" + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.1.0.tgz", + "integrity": "sha512-Py8zIo+02ht82brwwhTg36iogzFqGLPXlRGKQw5s+qP/kMNc4MAyDeEwBKDijk6zTIbegEgu8Qy7C1LboslQAw==" }, "node_modules/@next/eslint-plugin-next": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.3.0.tgz", - "integrity": "sha512-wuGN5qSEjSgcq9fVkH0Y/qIPFjnZtW3ZPwfjJOn7l/rrf6y8J24h/lo61kwqunTyzZJm/ETGfGVU9PUs8cnzEA==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.1.0.tgz", + "integrity": "sha512-x4FavbNEeXx/baD/zC/SdrvkjSby8nBn8KcCREqk6UuwvwoAPZmaV8TFCAuo/cpovBRTIY67mHhe86MQQm/68Q==", "dev": true, "dependencies": { - "glob": "7.1.7" + "glob": "10.3.10" } }, "node_modules/@next/swc-darwin-arm64": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.6.tgz", - "integrity": "sha512-5nvXMzKtZfvcu4BhtV0KH1oGv4XEW+B+jOfmBdpFI3C7FrB/MfujRpWYSBBO64+qbW8pkZiSyQv9eiwnn5VIQA==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.0.tgz", + "integrity": "sha512-nUDn7TOGcIeyQni6lZHfzNoo9S0euXnu0jhsbMOmMJUBfgsnESdjN97kM7cBqQxZa8L/bM9om/S5/1dzCrW6wQ==", "cpu": [ "arm64" ], @@ -314,9 +335,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.6.tgz", - "integrity": "sha512-6cgBfxg98oOCSr4BckWjLLgiVwlL3vlLj8hXg2b+nDgm4bC/qVXXLfpLB9FHdoDu4057hzywbxKvmYGmi7yUzA==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.0.tgz", + "integrity": "sha512-1jgudN5haWxiAl3O1ljUS2GfupPmcftu2RYJqZiMJmmbBT5M1XDffjUtRUzP4W3cBHsrvkfOFdQ71hAreNQP6g==", "cpu": [ "x64" ], @@ -329,9 +350,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.6.tgz", - "integrity": "sha512-txagBbj1e1w47YQjcKgSU4rRVQ7uF29YpnlHV5xuVUsgCUf2FmyfJ3CPjZUvpIeXCJAoMCFAoGnbtX86BK7+sg==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.0.tgz", + "integrity": "sha512-RHo7Tcj+jllXUbK7xk2NyIDod3YcCPDZxj1WLIYxd709BQ7WuRYl3OWUNG+WUfqeQBds6kvZYlc42NJJTNi4tQ==", "cpu": [ "arm64" ], @@ -344,9 +365,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.6.tgz", - "integrity": "sha512-cGd+H8amifT86ZldVJtAKDxUqeFyLWW+v2NlBULnLAdWsiuuN8TuhVBt8ZNpCqcAuoruoSWynvMWixTFcroq+Q==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.0.tgz", + "integrity": "sha512-v6kP8sHYxjO8RwHmWMJSq7VZP2nYCkRVQ0qolh2l6xroe9QjbgV8siTbduED4u0hlk0+tjS6/Tuy4n5XCp+l6g==", "cpu": [ "arm64" ], @@ -359,9 +380,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.6.tgz", - "integrity": "sha512-Mc2b4xiIWKXIhBy2NBTwOxGD3nHLmq4keFk+d4/WL5fMsB8XdJRdtUlL87SqVCTSaf1BRuQQf1HvXZcy+rq3Nw==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.0.tgz", + "integrity": "sha512-zJ2pnoFYB1F4vmEVlb/eSe+VH679zT1VdXlZKX+pE66grOgjmKJHKacf82g/sWE4MQ4Rk2FMBCRnX+l6/TVYzQ==", "cpu": [ "x64" ], @@ -374,9 +395,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.6.tgz", - "integrity": "sha512-CFHvP9Qz98NruJiUnCe61O6GveKKHpJLloXbDSWRhqhkJdZD2zU5hG+gtVJR//tyW897izuHpM6Gtf6+sNgJPQ==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.0.tgz", + "integrity": "sha512-rbaIYFt2X9YZBSbH/CwGAjbBG2/MrACCVu2X0+kSykHzHnYH5FjHxwXLkcoJ10cX0aWCEynpu+rP76x0914atg==", "cpu": [ "x64" ], @@ -389,9 +410,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.6.tgz", - "integrity": "sha512-aFv1ejfkbS7PUa1qVPwzDHjQWQtknzAZWGTKYIAaS4NMtBlk3VyA6AYn593pqNanlicewqyl2jUhQAaFV/qXsg==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.0.tgz", + "integrity": "sha512-o1N5TsYc8f/HpGt39OUQpQ9AKIGApd3QLueu7hXk//2xq5Z9OxmV6sQfNp8C7qYmiOlHYODOGqNNa0e9jvchGQ==", "cpu": [ "arm64" ], @@ -404,9 +425,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.6.tgz", - "integrity": "sha512-XqqpHgEIlBHvzwG8sp/JXMFkLAfGLqkbVsyN+/Ih1mR8INb6YCc2x/Mbwi6hsAgUnqQztz8cvEbHJUbSl7RHDg==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.0.tgz", + "integrity": "sha512-XXIuB1DBRCFwNO6EEzCTMHT5pauwaSj4SWs7CYnME57eaReAKBXCnkUE80p/pAZcewm7hs+vGvNqDPacEXHVkw==", "cpu": [ "ia32" ], @@ -419,9 +440,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.6.tgz", - "integrity": "sha512-Cqfe1YmOS7k+5mGu92nl5ULkzpKuxJrP3+4AEuPmrpFZ3BHxTY3TnHmU1On3bFmFFs6FbTcdF58CCUProGpIGQ==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.0.tgz", + "integrity": "sha512-9WEbVRRAqJ3YFVqEZIxUqkiO8l1nool1LmNxygr5HWF8AcSYsEpneUDhmjUVJEzO2A04+oPtZdombzzPPkTtgg==", "cpu": [ "x64" ], @@ -474,6 +495,12 @@ "node": ">=14" } }, + "node_modules/@polka/url": { + "version": "1.0.0-next.24", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.24.tgz", + "integrity": "sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ==", + "dev": true + }, "node_modules/@rushstack/eslint-patch": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.7.2.tgz", @@ -488,12 +515,34 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/fs-extra": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", + "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==", + "dependencies": { + "@types/jsonfile": "*", + "@types/node": "*" + } + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/jsonfile": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", + "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==" + }, "node_modules/@types/node": { "version": "18.15.11", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", @@ -504,10 +553,15 @@ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" }, + "node_modules/@types/ps-tree": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@types/ps-tree/-/ps-tree-1.1.6.tgz", + "integrity": "sha512-PtrlVaOaI44/3pl3cvnlK+GxOM3re2526TJvPvh7W+keHIXdV4TE0ylpPBAcvFQCbGitaTXwL9u+RF7qtVeazQ==" + }, "node_modules/@types/react": { - "version": "18.0.35", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.35.tgz", - "integrity": "sha512-6Laome31HpetaIUGFWl1VQ3mdSImwxtFZ39rh059a1MNnKGqBpC88J6NJ8n/Is3Qx7CefDGLgf/KhN/sYCf7ag==", + "version": "18.2.53", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.53.tgz", + "integrity": "sha512-52IHsMDT8qATp9B9zoOyobW8W3/0QhaJQTw1HwRj0UY2yBpCAQ7+S/CqHYQ8niAm3p4ji+rWUQ9UCib0GxQ60w==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -515,9 +569,9 @@ } }, "node_modules/@types/react-dom": { - "version": "18.0.11", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz", - "integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==", + "version": "18.2.18", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz", + "integrity": "sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==", "dependencies": { "@types/react": "*" } @@ -527,6 +581,11 @@ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" }, + "node_modules/@types/which": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/which/-/which-3.0.3.tgz", + "integrity": "sha512-2C1+XoY0huExTbs8MQv1DuS5FS86+SEjdM9F/+GS61gg5Hqbtj8ZiDSx8MfWcyei907fIPbfPGCOrNUTnVHY1g==" + }, "node_modules/@typescript-eslint/parser": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", @@ -649,6 +708,15 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -725,13 +793,16 @@ } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -765,6 +836,25 @@ "node": ">=8" } }, + "node_modules/array.prototype.filter": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz", + "integrity": "sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array.prototype.findlastindex": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", @@ -821,30 +911,31 @@ } }, "node_modules/array.prototype.tosorted": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz", - "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", + "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.1.0", + "es-shim-unscopables": "^1.0.2" } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", "is-shared-array-buffer": "^1.0.2" }, "engines": { @@ -902,9 +993,9 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz", + "integrity": "sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==", "dev": true, "engines": { "node": ">= 0.4" @@ -944,6 +1035,11 @@ "node": ">=8" } }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1039,9 +1135,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001581", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001581.tgz", - "integrity": "sha512-whlTkwhqV2tUmP3oYhtNfaWGYHDdS3JYFQBKXxcUR9qqPWsRhFHhoISO2Xnl/g0xyKzht9mI1LZpiNWfMzHixQ==", + "version": "1.0.30001584", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001584.tgz", + "integrity": "sha512-LOz7CCQ9M1G7OjJOF9/mzmqmj3jE/7VOmrfw6Mgs0E8cjOsbRXQJHsPBfmBOXDskXKrHLyyW3n7kpDW/4BsfpQ==", "funding": [ { "type": "opencollective", @@ -1061,7 +1157,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -1126,6 +1221,53 @@ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1156,6 +1298,24 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1191,11 +1351,24 @@ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "dev": true + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -1263,7 +1436,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, "dependencies": { "path-type": "^4.0.0" }, @@ -1288,15 +1460,20 @@ "node": ">=6.0.0" } }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "node_modules/electron-to-chromium": { - "version": "1.4.651", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.651.tgz", - "integrity": "sha512-jjks7Xx+4I7dslwsbaFocSwqBbGHQmuXBJUK9QBZTIrzPq3pzn6Uf2szFSP728FtLYE3ldiccmlkOM/zhGKCpA==" + "version": "1.4.656", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.656.tgz", + "integrity": "sha512-9AQB5eFTHyR3Gvt2t/NwR0le2jBSUNwCnMbUCejFWHD+so4tH40/dRLgoE+jxlPeWS43XJewyvCv+I8LPMl49Q==" }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -1369,6 +1546,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-iterator-helpers": { "version": "1.0.15", "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz", @@ -1509,20 +1701,20 @@ } }, "node_modules/eslint-config-next": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.3.0.tgz", - "integrity": "sha512-6YEwmFBX0VjBd3ODGW9df0Is0FLaRFdMN8eAahQG9CN6LjQ28J8AFr19ngxqMSg7Qv6Uca/3VeeBosJh1bzu0w==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.1.0.tgz", + "integrity": "sha512-SBX2ed7DoRFXC6CQSLc/SbLY9Ut6HxNB2wPTcoIWjUMd7aF7O/SIE7111L8FdZ9TXsNV4pulUDnfthpyPtbFUg==", "dev": true, "dependencies": { - "@next/eslint-plugin-next": "13.3.0", - "@rushstack/eslint-patch": "^1.1.3", - "@typescript-eslint/parser": "^5.42.0", + "@next/eslint-plugin-next": "14.1.0", + "@rushstack/eslint-patch": "^1.3.3", + "@typescript-eslint/parser": "^5.4.2 || ^6.0.0", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-react": "^7.31.7", - "eslint-plugin-react-hooks": "^4.5.0" + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" }, "peerDependencies": { "eslint": "^7.23.0 || ^8.0.0", @@ -1863,6 +2055,20 @@ "node": ">=0.10.0" } }, + "node_modules/event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", + "dependencies": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -1907,6 +2113,17 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-printf": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz", + "integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==", + "dependencies": { + "boolean": "^3.1.4" + }, + "engines": { + "node": ">=10.0" + } + }, "node_modules/fastq": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz", @@ -1915,6 +2132,28 @@ "reusify": "^1.0.4" } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -1938,6 +2177,27 @@ "node": ">=8" } }, + "node_modules/find-process": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/find-process/-/find-process-1.4.7.tgz", + "integrity": "sha512-/U4CYp1214Xrp3u3Fqr9yNynUrr5Le4y0SsJh2lMDDSbpwYSz3M2SMWQC+wqcx79cN8PQtHQIL8KnuY9M66fdg==", + "dependencies": { + "chalk": "^4.0.0", + "commander": "^5.1.0", + "debug": "^4.1.1" + }, + "bin": { + "find-process": "bin/find-process.js" + } + }, + "node_modules/find-process/node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "engines": { + "node": ">= 6" + } + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -1998,6 +2258,17 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -2010,11 +2281,28 @@ "url": "https://github.com/sponsors/rawify" } }, + "node_modules/from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==" + }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/fsevents": { "version": "2.3.3", @@ -2064,17 +2352,37 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/fx": { + "version": "31.0.0", + "resolved": "https://registry.npmjs.org/fx/-/fx-31.0.0.tgz", + "integrity": "sha512-OoeYSPKqNKmfnH4s+rGYI0c8OZmqqOOXsUtqy0YyHqQQoQSDiDs3m3M9uXKx5OQR+jDx7/FhYqpO3kl/As/xgg==", + "bin": { + "fx": "index.js" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.3.tgz", + "integrity": "sha512-JIcZczvcMVE7AUOP+X72bh8HqHBRxFdz5PDHYtNG/lE3yk9b3KZBJlwFcTyPYjg3L4RLLmZJzvjxhaZVapxFrQ==", "dev": true, "dependencies": { + "es-errors": "^1.0.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -2108,20 +2416,21 @@ } }, "node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -2138,10 +2447,27 @@ "node": ">=10.13.0" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/globals": { "version": "13.24.0", @@ -2216,12 +2542,27 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", "dev": true, - "funding": { + "dependencies": { + "duplexer": "^0.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { "url": "https://github.com/sponsors/ljharb" } }, @@ -2229,7 +2570,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -2271,12 +2611,12 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -2296,11 +2636,16 @@ "node": ">= 0.4" } }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", - "dev": true, + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "engines": { "node": ">= 4" } @@ -2361,14 +2706,16 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2573,6 +2920,15 @@ "node": ">=8" } }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -2641,12 +2997,12 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, "dependencies": { - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -2795,6 +3151,17 @@ "json5": "lib/cli.js" } }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -2896,17 +3263,18 @@ } }, "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", "engines": { - "node": ">=10" + "node": "14 || >=16.14" } }, + "node_modules/map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==" + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -2943,7 +3311,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -2956,11 +3323,19 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/mrmime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", + "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/mz": { "version": "2.7.0", @@ -2996,34 +3371,34 @@ "dev": true }, "node_modules/next": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/next/-/next-13.5.6.tgz", - "integrity": "sha512-Y2wTcTbO4WwEsVb4A8VSnOsG1I9ok+h74q0ZdxkwM3EODqrs4pasq7O0iUxbcS9VtWMicG7f3+HAj0r1+NtKSw==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/next/-/next-14.1.0.tgz", + "integrity": "sha512-wlzrsbfeSU48YQBjZhDzOwhWhGsy+uQycR8bHAOt1LY1bn3zZEcDyHQOEoN3aWzQ8LHCAJ1nqrWCc9XF2+O45Q==", "dependencies": { - "@next/env": "13.5.6", + "@next/env": "14.1.0", "@swc/helpers": "0.5.2", "busboy": "1.6.0", - "caniuse-lite": "^1.0.30001406", + "caniuse-lite": "^1.0.30001579", + "graceful-fs": "^4.2.11", "postcss": "8.4.31", - "styled-jsx": "5.1.1", - "watchpack": "2.4.0" + "styled-jsx": "5.1.1" }, "bin": { "next": "dist/bin/next" }, "engines": { - "node": ">=16.14.0" + "node": ">=18.17.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "13.5.6", - "@next/swc-darwin-x64": "13.5.6", - "@next/swc-linux-arm64-gnu": "13.5.6", - "@next/swc-linux-arm64-musl": "13.5.6", - "@next/swc-linux-x64-gnu": "13.5.6", - "@next/swc-linux-x64-musl": "13.5.6", - "@next/swc-win32-arm64-msvc": "13.5.6", - "@next/swc-win32-ia32-msvc": "13.5.6", - "@next/swc-win32-x64-msvc": "13.5.6" + "@next/swc-darwin-arm64": "14.1.0", + "@next/swc-darwin-x64": "14.1.0", + "@next/swc-linux-arm64-gnu": "14.1.0", + "@next/swc-linux-arm64-musl": "14.1.0", + "@next/swc-linux-x64-gnu": "14.1.0", + "@next/swc-linux-x64-musl": "14.1.0", + "@next/swc-win32-arm64-msvc": "14.1.0", + "@next/swc-win32-ia32-msvc": "14.1.0", + "@next/swc-win32-x64-msvc": "14.1.0" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -3067,6 +3442,41 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", + "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/node-releases": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", @@ -3172,15 +3582,16 @@ } }, "node_modules/object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz", + "integrity": "sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1" + "array.prototype.filter": "^1.0.3", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.0.0" } }, "node_modules/object.hasown": { @@ -3222,6 +3633,15 @@ "wrappy": "1" } }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true, + "bin": { + "opener": "bin/opener-bin.js" + } + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -3327,23 +3747,22 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", - "engines": { - "node": "14 || >=16.14" - } - }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, "engines": { "node": ">=8" } }, + "node_modules/pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", + "dependencies": { + "through": "~2.3" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -3360,6 +3779,17 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -3519,6 +3949,20 @@ "react-is": "^16.13.1" } }, + "node_modules/ps-tree": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", + "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", + "dependencies": { + "event-stream": "=3.3.4" + }, + "bin": { + "ps-tree": "bin/ps-tree.js" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -3558,6 +4002,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/randomcolor": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/randomcolor/-/randomcolor-0.6.2.tgz", + "integrity": "sha512-Mn6TbyYpFgwFuQ8KJKqf3bqqY9O1y37/0jgSK/61PUxV4QfIMv0+K2ioq8DfOjkBslcjwSzRfIDEXfzA9aCx7A==" + }, "node_modules/react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", @@ -3615,15 +4064,16 @@ } }, "node_modules/reflect.getprototypeof": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", - "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.5.tgz", + "integrity": "sha512-62wgfC8dJWrmxv44CA36pLDnP6KKl3Vhxb7PL+8+qrrFMMoJij4vgiMP8zV4O8+CBMXY1mHxI5fITGHXFHVmQQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.0.0", + "get-intrinsic": "^1.2.3", "globalthis": "^1.0.3", "which-builtin-type": "^1.1.3" }, @@ -3657,6 +4107,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -3715,6 +4173,39 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/roarr": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-7.21.0.tgz", + "integrity": "sha512-d1rPLcHmQID3GsA3p9d5vKSZYlvrTWhjbmeg9DT5DcPoLpH85VzPmkLkGKhQv376+dfkApaHwNbpYEwDB77Ibg==", + "dependencies": { + "fast-printf": "^1.6.9", + "safe-stable-stringify": "^2.4.3", + "semver-compare": "^1.0.0" + }, + "engines": { + "node": ">=18.0" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -3772,6 +4263,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "engines": { + "node": ">=10" + } + }, "node_modules/scheduler": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", @@ -3784,7 +4283,6 @@ "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -3795,6 +4293,47 @@ "node": ">=10" } }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==" + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-error": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-11.0.3.tgz", + "integrity": "sha512-2G2y++21dhj2R7iHAdd0FIzjGwuKZld+7Pl/bTU6YIkrC2ZMbVUjm+luj6A6V34Rv9XfKJDKpTWu9W4Gse1D9g==", + "dependencies": { + "type-fest": "^2.12.2" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/serialize-error/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/set-function-length": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", @@ -3869,6 +4408,20 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "dev": true, + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -3886,6 +4439,25 @@ "node": ">=0.10.0" } }, + "node_modules/split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", + "dependencies": { + "duplexer": "~0.1.1" + } + }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -4106,54 +4678,10 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/sucrase/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/sucrase/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/sucrase/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -4247,6 +4775,19 @@ "node": ">=0.8" } }, + "node_modules/throttle-debounce": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.0.tgz", + "integrity": "sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==", + "engines": { + "node": ">=12.22" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -4258,6 +4799,23 @@ "node": ">=8.0" } }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ts-custom-error": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/ts-custom-error/-/ts-custom-error-3.3.1.tgz", + "integrity": "sha512-5OX1tzOjxWEgsr/YEUWSuPrQ00deKLh6D7OTWcvNHm12/7QPyRh8SYpyWvA4IZv8H/+GQWQEh/kwo95Q9OVW1A==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", @@ -4301,6 +4859,81 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, + "node_modules/turbowatch": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/turbowatch/-/turbowatch-2.29.4.tgz", + "integrity": "sha512-cdfH1nzLfduhE5iVCAnojtoTzPwNva/TBDrMJBI4Y8SBjBDjMBj2rQqLGqT7qkVk+xDnJrMxgP4c5+Z/GGVFsA==", + "dependencies": { + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "find-process": "^1.4.7", + "glob": "^9.3.1", + "jiti": "^1.18.2", + "micromatch": "^4.0.5", + "pidtree": "^0.6.0", + "randomcolor": "^0.6.2", + "roarr": "^7.15.0", + "semver": "^7.3.8", + "serialize-error": "^11.0.0", + "throttle-debounce": "^5.0.0", + "ts-custom-error": "^3.3.1", + "yargs": "^17.7.1", + "zx": "^7.2.1" + }, + "bin": { + "turbowatch": "dist/bin/turbowatch.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/turbowatch/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/turbowatch/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/turbowatch/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/turbowatch/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -4417,6 +5050,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", @@ -4468,16 +5114,56 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "node_modules/web-streams-polyfill": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.2.tgz", + "integrity": "sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/webpack-bundle-analyzer": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.1.tgz", + "integrity": "sha512-s3P7pgexgT/HTUSYgxJyn28A+99mmLq4HsJepMPzu0R8ImJc52QNqaFYW1Z2z2uIb1/J3eYgaAWVpaC+v/1aAQ==", + "dev": true, "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" + "@discoveryjs/json-ext": "0.5.7", + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "commander": "^7.2.0", + "debounce": "^1.2.1", + "escape-string-regexp": "^4.0.0", + "gzip-size": "^6.0.0", + "html-escaper": "^2.0.2", + "is-plain-object": "^5.0.0", + "opener": "^1.5.2", + "picocolors": "^1.0.0", + "sirv": "^2.0.3", + "ws": "^7.3.1" + }, + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" }, "engines": { - "node": ">=10.13.0" + "node": ">= 10.13.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpod": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/webpod/-/webpod-0.0.2.tgz", + "integrity": "sha512-cSwwQIeg8v4i3p4ajHhwgR7N6VyxAf+KYSSsY6Pd3aETE+xEU4vbitz7qQkB0I321xnhDdgtxuiSfk5r/FVtjg==", + "bin": { + "webpod": "dist/index.js" } }, "node_modules/which": { @@ -4552,16 +5238,16 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", - "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", + "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.4", + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.5", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "has-tostringtag": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -4663,11 +5349,39 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "dev": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yaml": { "version": "1.10.2", @@ -4677,6 +5391,49 @@ "node": ">= 6" } }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -4715,6 +5472,104 @@ "optional": true } } + }, + "node_modules/zx": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/zx/-/zx-7.2.3.tgz", + "integrity": "sha512-QODu38nLlYXg/B/Gw7ZKiZrvPkEsjPN3LQ5JFXM7h0JvwhEdPNNl+4Ao1y4+o3CLNiDUNcwzQYZ4/Ko7kKzCMA==", + "dependencies": { + "@types/fs-extra": "^11.0.1", + "@types/minimist": "^1.2.2", + "@types/node": "^18.16.3", + "@types/ps-tree": "^1.1.2", + "@types/which": "^3.0.0", + "chalk": "^5.2.0", + "fs-extra": "^11.1.1", + "fx": "*", + "globby": "^13.1.4", + "minimist": "^1.2.8", + "node-fetch": "3.3.1", + "ps-tree": "^1.2.0", + "webpod": "^0", + "which": "^3.0.0", + "yaml": "^2.2.2" + }, + "bin": { + "zx": "build/cli.js" + }, + "engines": { + "node": ">= 16.0.0" + } + }, + "node_modules/zx/node_modules/@types/node": { + "version": "18.19.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.14.tgz", + "integrity": "sha512-EnQ4Us2rmOS64nHDWr0XqAD8DsO6f3XR6lf9UIIrZQpUzPVdN/oPuEzfDWNHSyXLvoGgjuEm/sPwFGSSs35Wtg==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/zx/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/zx/node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zx/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zx/node_modules/which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/zx/node_modules/yaml": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "engines": { + "node": ">= 14" + } } } } diff --git a/fullstack-templates/saas/package.json b/fullstack-templates/saas/package.json index e23a1f65..5fd9ee3e 100644 --- a/fullstack-templates/saas/package.json +++ b/fullstack-templates/saas/package.json @@ -3,7 +3,9 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "next build && cargo shuttle run", + "dev": "cross-env ROARR_LOG=true npm exec turbowatch ./turbowatch.ts", + "next-dev": "next dev --turbo", + "analyze": "cross-env ANALYZE=true next build", "build": "next build && cargo build", "shuttle-login": "cargo shuttle login", "full": "cargo shuttle run --port 8001", @@ -15,23 +17,26 @@ "dependencies": { "@faker-js/faker": "^7.6.0", "@fortawesome/free-solid-svg-icons": "^6.4.0", - "@fortawesome/react-fontawesome": "github:fortawesome/react-fontawesome", + "@fortawesome/react-fontawesome": "^0.2.0", "@types/node": "18.15.11", - "@types/react": "18.0.35", - "@types/react-dom": "18.0.11", + "@types/react": "^18.2.53", + "@types/react-dom": "^18.2.18", "autoprefixer": "10.4.14", "chart.js": "^4.3.0", - "next": "13.5.6", + "next": "^14.1.0", "postcss": "8.4.33", - "react": "18.2.0", + "react": "^18.2.0", "react-chartjs-2": "^5.2.0", - "react-dom": "18.2.0", + "react-dom": "^18.2.0", "tailwindcss": "3.3.1", + "turbowatch": "^2.29.4", "typescript": "5.0.4", "zustand": "^4.3.7" }, "devDependencies": { + "@next/bundle-analyzer": "^14.1.0", + "cross-env": "^7.0.3", "eslint": "8.38.0", - "eslint-config-next": "13.3.0" + "eslint-config-next": "^14.1.0" } } diff --git a/fullstack-templates/saas/src/components/AuthedLayout.tsx b/fullstack-templates/saas/src/components/AuthedLayout.tsx index f01e936e..8b6ea29f 100644 --- a/fullstack-templates/saas/src/components/AuthedLayout.tsx +++ b/fullstack-templates/saas/src/components/AuthedLayout.tsx @@ -1,7 +1,7 @@ import Navbar from './navbar'; import React from 'react'; import Head from 'next/head'; -import { accountStore } from '@/zustandStore'; +import { accountStore } from '@/stores/zustandStore'; import { useRouter } from 'next/router'; type Props = { diff --git a/fullstack-templates/saas/src/components/CustomerSingleModal.tsx b/fullstack-templates/saas/src/components/CustomerSingleModal.tsx index bfba560e..d3456556 100644 --- a/fullstack-templates/saas/src/components/CustomerSingleModal.tsx +++ b/fullstack-templates/saas/src/components/CustomerSingleModal.tsx @@ -1,86 +1,86 @@ -import Layout from '@/components/Layout'; import React from 'react'; import { useRouter } from 'next/router'; -import { accountStore } from '@/zustandStore'; -import Link from 'next/link'; +import { accountStore } from '@/stores/zustandStore'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faMultiply } from '@fortawesome/free-solid-svg-icons'; interface Customer { - id: number; - firstname: string; - lastname: string; - email: string; - phone: string; + id: number; + firstname: string; + lastname: string; + email: string; + phone: string; } type Props = { - id: number; - data: Customer[]; - vis: boolean; - setVis: React.Dispatch>; + id: number; + data: Customer[]; + vis: boolean; + setVis: React.Dispatch>; }; -export default function CustomerSingle({ data, id, vis, setVis }: Props) { - const { email } = accountStore(); +export default function CustomerSingle({data, id, vis, setVis}: Props) { + const {email} = accountStore(); - let router = useRouter(); + let router = useRouter(); - const handleDelete = async (e: React.SyntheticEvent) => { - e.preventDefault(); - const url = `//${window.location.host}/api/customers/${id}`; + const handleDelete = async (e: React.SyntheticEvent) => { + e.preventDefault(); + const url = `//${window.location.host}/api/customers/${id}`; - try { - const res = await fetch(url, { - mode: 'cors', - method: 'DELETE', - headers: new Headers({ - 'Content-Type': 'application/json', - }), - body: JSON.stringify({ - email: email, - }), - }); + try { + const res = await fetch(url, { + mode: 'cors', + method: 'DELETE', + headers: new Headers({ + 'Content-Type': 'application/json', + }), + body: JSON.stringify({ + email: email, + }), + }); - if (res.ok) { - router.reload(); - } - } catch (e: any) { - console.log(`Error: ${e}`); - } - }; + if (res.ok) { + router.reload(); + } + } catch (e: any) { + console.log(`Error: ${e}`); + } + }; - if (!vis) return null; + if (!vis) return null; - const customer = data.find((a) => a.id == id); + const customer = data.find((a) => a.id == id); - if (!customer) return

    Customer does not exist :(

    ; + if (!customer) return

    Customer does not exist :(

    ; - return ( -
    -
    -
    -

    Customer details

    + return ( +
    +
    +
    +

    Customer + details

    - + +
    +
    +

    + Name: {customer.firstname} {customer.lastname} +

    +

    Email: {customer.email}

    +

    Phone: {customer.phone}

    +
    + +
    -
    -

    - Name: {customer.firstname} {customer.lastname} -

    -

    Email: {customer.email}

    -

    Phone: {customer.phone}

    -
    - -
    -
    - ); + ); } diff --git a/fullstack-templates/saas/src/components/DealSingleModal copy.tsx b/fullstack-templates/saas/src/components/DealSingleModal copy.tsx index 3f9a3e6a..c2087f12 100644 --- a/fullstack-templates/saas/src/components/DealSingleModal copy.tsx +++ b/fullstack-templates/saas/src/components/DealSingleModal copy.tsx @@ -1,75 +1,75 @@ -import Layout from "@/components/Layout" import React from "react" import { useRouter } from 'next/router' -import {accountStore} from "@/zustandStore" -import Link from 'next/link' +import { accountStore } from '@/stores/zustandStore' interface Customer { - id: number, - firstname: string, - lastname: string, - email: string, - phone: string + id: number, + firstname: string, + lastname: string, + email: string, + phone: string } type Props = { - id: number, - data: Customer[], - vis: boolean, - setVis: React.Dispatch> + id: number, + data: Customer[], + vis: boolean, + setVis: React.Dispatch> } export default function CustomerSingle({data, id, vis, setVis}: Props) { - const {email} = accountStore(); - - let router = useRouter(); + const {email} = accountStore(); - const handleDelete = async (e: React.SyntheticEvent) => { - e.preventDefault() + let router = useRouter(); + + const handleDelete = async (e: React.SyntheticEvent) => { + e.preventDefault() const url = `//${window.location.host}/api/customers/${id}` - try { - -const res = await fetch(url, { - mode: 'cors', - method: 'DELETE', - headers: new Headers({ - "Content-Type": "application/json" - }), - body: JSON.stringify({ - email: email - }) - }); + try { + + const res = await fetch(url, { + mode: 'cors', + method: 'DELETE', + headers: new Headers({ + "Content-Type": "application/json" + }), + body: JSON.stringify({ + email: email + }) + }); + + if (res.ok) { + router.reload() + } + } catch (e: any) { + console.log(`Error: ${e}`) + } - if (res.ok) { - router.reload() - } - } catch (e: any) { - console.log(`Error: ${e}`) } - - } return ( - <> - {vis ? -
    -
    - {data ? - data.filter(a => a.id == id).map((item) => ( -
    -

    {item.firstname} {item.lastname}

    -

    Email: {item.email}

    -

    Phone: {item.phone}

    - -
    )) - : -

    Customer does not exist :(

    } + <> + {vis ? +
    +
    + {data ? + data.filter(a => a.id == id).map((item) => ( +
    +

    {item.firstname} {item.lastname}

    +

    Email: {item.email}

    +

    Phone: {item.phone}

    + +
    )) + : +

    Customer does not exist :(

    } -
    -
    :null } - +
    +
    : null} + ) } diff --git a/fullstack-templates/saas/src/components/Layout.tsx b/fullstack-templates/saas/src/components/Layout.tsx index f5da8c0c..13993be1 100644 --- a/fullstack-templates/saas/src/components/Layout.tsx +++ b/fullstack-templates/saas/src/components/Layout.tsx @@ -1,7 +1,7 @@ import Navbar from './navbar'; import React from 'react'; import Head from 'next/head'; -import { accountStore } from '@/zustandStore'; +import { accountStore } from '@/stores/zustandStore'; type Props = { children: React.ReactNode | React.ReactNode[]; diff --git a/fullstack-templates/saas/src/components/navbar.tsx b/fullstack-templates/saas/src/components/navbar.tsx index d1b9b635..cf1109c5 100644 --- a/fullstack-templates/saas/src/components/navbar.tsx +++ b/fullstack-templates/saas/src/components/navbar.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; import Link from 'next/link'; -import { accountStore } from '@/zustandStore'; +import { accountStore } from '@/stores/zustandStore'; import { useRouter } from 'next/router'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { diff --git a/fullstack-templates/saas/src/pages/dashboard/customers/[id].tsx b/fullstack-templates/saas/src/pages/dashboard/customers/[id].tsx index 99abcfb6..408936b7 100644 --- a/fullstack-templates/saas/src/pages/dashboard/customers/[id].tsx +++ b/fullstack-templates/saas/src/pages/dashboard/customers/[id].tsx @@ -1,104 +1,103 @@ import Layout from "@/components/Layout" import React from "react" import { useRouter } from 'next/router' -import {accountStore} from "@/zustandStore" -import Link from 'next/link' +import { accountStore } from "@/stores/zustandStore" interface Customer { - id: number, - firstname: string, - lastname: string, - email: string, - phone: string + id: number, + firstname: string, + lastname: string, + email: string, + phone: string } export default function CustomerSingle() { - const [data, setData] = React.useState(); - const {email} = accountStore(); - - let router = useRouter(); - const {id} = router.query; + const [data, setData] = React.useState(); + const {email} = accountStore(); - const handleDelete = async (e: React.SyntheticEvent) => { - e.preventDefault() + let router = useRouter(); + const {id} = router.query; + + const handleDelete = async (e: React.SyntheticEvent) => { + e.preventDefault() const url = `//${window.location.host}/api/customers/${id}` - try { - -const res = await fetch(url, { - mode: 'cors', - method: 'DELETE', - headers: new Headers({ - "Content-Type": "application/json" - }), - body: JSON.stringify({ - email: email - }) - }); - - if (res.ok) { - router.push("/dashboard/customers"); - } - } catch (e: any) { - console.log(`Error: ${e}`) - } - - } - -React.useEffect(() => { - const fetchData = async () => { - - const url = `//${window.location.host}/api/customers/${id}` - - try { - const res = await fetch(url, - { - method: "POST", - mode: "cors", - headers: new Headers({ - "Content-Type": "application/json" - }), - - body: JSON.stringify({ - email: email - }) - }, - ); - - if (res.status == 403) { - return router.push("/login"); + try { + + const res = await fetch(url, { + mode: 'cors', + method: 'DELETE', + headers: new Headers({ + "Content-Type": "application/json" + }), + body: JSON.stringify({ + email: email + }) + }); + + if (res.ok) { + router.push("/dashboard/customers"); + } + } catch (e: any) { + console.log(`Error: ${e}`) } - - const data: Customer = await res.json() - setData(data); + } + + React.useEffect(() => { + const fetchData = async () => { + + const url = `//${window.location.host}/api/customers/${id}` + + try { + const res = await fetch(url, + { + method: "POST", + mode: "cors", + headers: new Headers({ + "Content-Type": "application/json" + }), + + body: JSON.stringify({ + email: email + }) + }, + ); + + if (res.status == 403) { + return router.push("/login"); + } + + const data: Customer = await res.json() + + setData(data); + + } catch (e: any) { + console.log(`Error: ${e}`); + } + }; + fetchData() + }, [email, router, id]); - } catch (e: any) { - console.log(`Error: ${e}`); - } - }; - fetchData() - }, [email, router, id]); - return ( - -
    - {data ? -
    -

    {data.firstname} {data.lastname}

    -

    Email: {data.email}

    -

    Phone: {data.phone}

    - -
    - : -

    User does not exist :(

    } - -
    - -
    - ) + +
    + {data ? +
    +

    {data.firstname} {data.lastname}

    +

    Email: {data.email}

    +

    Phone: {data.phone}

    + +
    + : +

    User does not exist :(

    } + +
    + +
    + ) } diff --git a/fullstack-templates/saas/src/pages/dashboard/customers/create.tsx b/fullstack-templates/saas/src/pages/dashboard/customers/create.tsx index 81d5e714..69696b06 100644 --- a/fullstack-templates/saas/src/pages/dashboard/customers/create.tsx +++ b/fullstack-templates/saas/src/pages/dashboard/customers/create.tsx @@ -1,7 +1,7 @@ import Layout from '../../../components/Layout'; import React from 'react'; import { useRouter } from 'next/router'; -import { accountStore } from '@/zustandStore'; +import { accountStore } from '@/stores/zustandStore'; export default function CreateCustomer() { const [firstName, setFirstName] = React.useState(''); diff --git a/fullstack-templates/saas/src/pages/dashboard/customers/index.tsx b/fullstack-templates/saas/src/pages/dashboard/customers/index.tsx index 597a5284..814907f4 100644 --- a/fullstack-templates/saas/src/pages/dashboard/customers/index.tsx +++ b/fullstack-templates/saas/src/pages/dashboard/customers/index.tsx @@ -1,7 +1,7 @@ import Layout from '../../../components/Layout'; import React from 'react'; import { useRouter } from 'next/router'; -import { accountStore } from '../../../zustandStore'; +import { accountStore } from '@/stores/zustandStore'; import Link from 'next/link'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faPlus, faTrash } from '@fortawesome/free-solid-svg-icons'; diff --git a/fullstack-templates/saas/src/pages/dashboard/deals/create.tsx b/fullstack-templates/saas/src/pages/dashboard/deals/create.tsx index c89aab80..70682d56 100644 --- a/fullstack-templates/saas/src/pages/dashboard/deals/create.tsx +++ b/fullstack-templates/saas/src/pages/dashboard/deals/create.tsx @@ -1,7 +1,7 @@ import Layout from '../../../components/Layout'; import React from 'react'; import { useRouter } from 'next/router'; -import { accountStore } from '@/zustandStore'; +import { accountStore } from '@/stores/zustandStore'; type Custname = { id: number; diff --git a/fullstack-templates/saas/src/pages/dashboard/deals/index.tsx b/fullstack-templates/saas/src/pages/dashboard/deals/index.tsx index 4510ef47..5e8b504e 100644 --- a/fullstack-templates/saas/src/pages/dashboard/deals/index.tsx +++ b/fullstack-templates/saas/src/pages/dashboard/deals/index.tsx @@ -1,7 +1,7 @@ import Layout from '../../../components/Layout'; import React from 'react'; import { useRouter } from 'next/router'; -import { accountStore } from '../../../zustandStore'; +import { accountStore } from '@/stores/zustandStore'; import Link from 'next/link'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faPlus } from '@fortawesome/free-solid-svg-icons'; diff --git a/fullstack-templates/saas/src/pages/dashboard/index.tsx b/fullstack-templates/saas/src/pages/dashboard/index.tsx index a2d4f877..fca679a7 100644 --- a/fullstack-templates/saas/src/pages/dashboard/index.tsx +++ b/fullstack-templates/saas/src/pages/dashboard/index.tsx @@ -1,7 +1,7 @@ import Layout from '../../components/Layout'; import React from 'react'; import { useRouter } from 'next/router'; -import { accountStore } from '@/zustandStore'; +import { accountStore } from '@/stores/zustandStore'; import SalesChart from '@/components/SalesChart'; import RecentSales from '@/components/RecentSales'; import TopClients from '@/components/TopClients'; diff --git a/fullstack-templates/saas/src/pages/dashboard/upgrade/checkout/index.tsx b/fullstack-templates/saas/src/pages/dashboard/upgrade/checkout/index.tsx index 3d5fc051..7af98d5b 100644 --- a/fullstack-templates/saas/src/pages/dashboard/upgrade/checkout/index.tsx +++ b/fullstack-templates/saas/src/pages/dashboard/upgrade/checkout/index.tsx @@ -3,50 +3,51 @@ import React from 'react'; import { useRouter } from 'next/router'; export default function CreateCustomer() { - const [name, setName] = React.useState(''); - const [email, setEmail] = React.useState(''); - const [card, setCard] = React.useState(''); - const [year, setYear] = React.useState(''); - const [month, setMonth] = React.useState(''); - const [cvc, setCvc] = React.useState(''); + const [name, setName] = React.useState(''); + const [email, setEmail] = React.useState(''); + const [card, setCard] = React.useState(''); + const [year, setYear] = React.useState(''); + const [month, setMonth] = React.useState(''); + const [cvc, setCvc] = React.useState(''); - let router = useRouter(); + let router = useRouter(); - const handleSubmit = async (e: React.SyntheticEvent) => { - e.preventDefault(); + const handleSubmit = async (e: React.SyntheticEvent) => { + e.preventDefault(); - const url = `//${window.location.host}/api/payments/pay`; + const url = `//${window.location.host}/api/payments/pay`; - try { - let res = await fetch(url, { - method: 'POST', - mode: 'cors', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - name: name, - email: email, - card: card, - expyear: parseInt(year), - expmonth: parseInt(month), - cvc: cvc, - }), - }); + try { + let res = await fetch(url, { + method: 'POST', + mode: 'cors', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + name: name, + email: email, + card: card, + expyear: parseInt(year), + expmonth: parseInt(month), + cvc: cvc, + }), + }); - if (res.ok) { - router.push('/dashboard/upgrade/checkout/success'); - } - } catch (e: any) { - console.log(`Error: ${e}`); - } - }; + if (res.ok) { + router.push('/dashboard/upgrade/checkout/success'); + } + } catch (e: any) { + console.log(`Error: ${e}`); + } + }; - return ( - -
    -
    +
    -

    Checkout

    + > +

    Checkout

    -
    - - + + setName((e.target as HTMLInputElement).value)} - placeholder="Enter your full name" - /> - - + + setEmail((e.target as HTMLInputElement).value)} - placeholder="Enter your email" - /> - - + + setCard((e.target as HTMLInputElement).value)} - placeholder="Enter your card number" - /> - + maxLength={16} + minLength={16} + value={card} + onInput={(e) => setCard((e.target as HTMLInputElement).value)} + placeholder="Enter your card number" + /> + - + id="year" + name="exp_year" + required + onChange={(e) => setYear((e.target as HTMLSelectElement).value)} + > + + + + + + + + + + + + + + + + + + + + + + + - + - - - + Select month + + + + + + + + + + + + + + + + setCvc((e.target as HTMLInputElement).value)} - placeholder="Enter your card CVC" - /> + value={cvc} + onInput={(e) => setCvc((e.target as HTMLInputElement).value)} + placeholder="Enter your card CVC" + /> -
    - -
    -
    -
    - - - ); + > + Submit → + +
    + +
    + + + ); } diff --git a/fullstack-templates/saas/src/pages/login.tsx b/fullstack-templates/saas/src/pages/login.tsx index 1f74b94c..3b33179c 100644 --- a/fullstack-templates/saas/src/pages/login.tsx +++ b/fullstack-templates/saas/src/pages/login.tsx @@ -1,64 +1,64 @@ import Layout from '../components/Layout'; import React from 'react'; import { useRouter } from 'next/router'; -import { accountStore } from '../zustandStore'; +import { accountStore } from '@/stores/zustandStore'; import Link from 'next/link'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faAt, faEye, faEyeSlash, faLock } from '@fortawesome/free-solid-svg-icons'; export default function Home() { - const [loginEmail, setLoginEmail] = React.useState(''); - const [pw, setPw] = React.useState(''); - const [pwVis, setPwVis] = React.useState(false); + const [loginEmail, setLoginEmail] = React.useState(''); + const [pw, setPw] = React.useState(''); + const [pwVis, setPwVis] = React.useState(false); - const { email, changeEmail } = accountStore(); + const {email, changeEmail} = accountStore(); - let router = useRouter(); + let router = useRouter(); - const handleSubmit = async (e: React.SyntheticEvent) => { - e.preventDefault(); + const handleSubmit = async (e: React.SyntheticEvent) => { + e.preventDefault(); - const url = `//${window.location.host}/api/auth/login`; + const url = `//${window.location.host}/api/auth/login`; - try { - let res = await fetch(url, { - method: 'POST', - mode: 'cors', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - email: loginEmail, - password: pw, - }), - }); + try { + let res = await fetch(url, { + method: 'POST', + mode: 'cors', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + email: loginEmail, + password: pw, + }), + }); - if (res.ok) { - changeEmail(loginEmail); - router.push('/dashboard'); - } else { - console.log('Incorrect login details.'); - } - } catch (e: any) { - console.log(`Error: ${e}`); - } - }; + if (res.ok) { + changeEmail(loginEmail); + router.push('/dashboard'); + } else { + console.log('Incorrect login details.'); + } + } catch (e: any) { + console.log(`Error: ${e}`); + } + }; - const togglePassword = (e: React.SyntheticEvent) => { - e.preventDefault(); + const togglePassword = (e: React.SyntheticEvent) => { + e.preventDefault(); - setPwVis(!pwVis); - }; + setPwVis(!pwVis); + }; - return ( - <> - -
    -
    +
    -

    Welcome Back

    -
    - -
    - Welcome Back +
    + +
    + - + setLoginEmail((e.target as HTMLInputElement).value)} - placeholder="Enter your email" - /> -
    - + value={loginEmail} + onInput={(e) => setLoginEmail((e.target as HTMLInputElement).value)} + placeholder="Enter your email" + /> +
    + -
    - + + icon={faLock} + color="black" + /> - setPw((e.target as HTMLInputElement).value)} - placeholder="Enter your password" - /> - + -
    + icon={pwVis ? faEyeSlash : faEye} + onClick={togglePassword} + color="black" + /> +
    -
    - -
    - -
    -
    + > + Sign In → + +
    + + +
    -
    -
    -
    - - ); + + + + + ); } diff --git a/fullstack-templates/saas/src/zustandStore.ts b/fullstack-templates/saas/src/stores/zustandStore.ts similarity index 100% rename from fullstack-templates/saas/src/zustandStore.ts rename to fullstack-templates/saas/src/stores/zustandStore.ts diff --git a/fullstack-templates/saas/turbowatch.ts b/fullstack-templates/saas/turbowatch.ts new file mode 100644 index 00000000..34eb6123 --- /dev/null +++ b/fullstack-templates/saas/turbowatch.ts @@ -0,0 +1,121 @@ +import { defineConfig } from 'turbowatch'; +import { ChildProcess, exec, spawn } from 'child_process'; +import path from 'path'; +import os from 'os'; + +// Function to execute a shell command and return a promise +function executeCommand(command: string | string[], abortSignal?: AbortSignal): Promise { + return new Promise((resolve, reject) => { + let process: ChildProcess; + + // Destructure the command into the command and its arguments + const [cmd, ...args] = typeof command === 'string' ? command.split(' ') : command; + + // Start the process + process = spawn(cmd, args, { + cwd: __dirname, + stdio: 'inherit', + }); + + // When the process exits, resolve or reject the promise + process.on('close', (code) => { + if (code !== 0) { + reject(new Error(`${[cmd, ...args].join(' ')} exited with code ${code}`)); + } else { + resolve(); + } + }); + + // If an abort signal is provided, kill the process if the watcher is aborted + if (abortSignal) { + abortSignal.addEventListener('abort', () => { + process.kill(); + }); + } + }); +} + +let shuttleCliAvailable = false; + +// Function to check if cargo shuttle is installed +function checkShuttleCli(): Promise { + return new Promise((resolve, reject) => { + exec('cargo shuttle --version', (error, stdout, _stderr) => { + if (error) { + console.error(`Shuttle check failed: ${error}`); + return reject(error); + } + console.log(`Version: ${stdout}`); + shuttleCliAvailable = true; // Set the shuttle availability flag to true + resolve(); + }); + }); +} + +// Check for cargo shuttle once at the start +(async () => { + try { + console.log('Checking for cargo shuttle...'); + await checkShuttleCli(); + } catch (error) { + console.error('Failed to check cargo shuttle:', error); + shuttleCliAvailable = false; + } +})(); + +export default defineConfig({ + project: __dirname, + triggers: [ + { + // Watch for changes in frontend files, excluding certain directories + expression: [ + 'allof', + ['not', ['dirname', '.next']], + ['not', ['dirname', 'node_modules']], + ['not', ['dirname', 'dist']], + ['not', ['dirname', 'public']], + [ + 'anyof', + ['match', '*.ts', 'basename'], + ['match', '*.tsx', 'basename'], + ['match', '*.js', 'basename'], + ['match', '*.jsx', 'basename'], + ['match', '*.css', 'basename'], + ], + ], + name: 'frontend', + // If {interruptible: true}, then AbortSignal will abort the current onChange routine + interruptible: true, + // Routine that is executed when file changes are detected + onChange: async ({abortSignal}) => { + // Build the Next.js project + const nextCmd = os.platform() === 'win32' ? 'next.cmd' : 'next'; + const nextPath = path.join(__dirname, 'node_modules', '.bin', nextCmd); + await executeCommand(`${nextPath} build`, abortSignal); + }, + // Retry a task if it fails. Otherwise, watch program will throw an error if trigger fails. + retry: { + retries: 0, // Setting retries to 0 to ensure that console logs, especially errors, are not overwritten by automatic retries + }, + }, + { + // Watch for changes in backend files, excluding certain directories + expression: ['allof', ['dirname', 'backend'], ['anyof', ['match', '*.rs', 'basename'], ['match', '*.toml', 'basename']]], + name: 'backend', + // If {interruptible: true}, then AbortSignal will abort the current onChange routine + interruptible: true, + // Routine that is executed when file changes are detected + onChange: async ({abortSignal}) => { + if (shuttleCliAvailable) { + await executeCommand(['cargo', 'shuttle', 'run'], abortSignal); + } else { + console.error('Shuttle not available, skipping cargo shuttle run'); + } + }, + // Retry a task if it fails. Otherwise, watch program will throw an error if trigger fails. + retry: { + retries: 0, // Setting retries to 0 to ensure that console logs, especially errors, are not overwritten by automatic retries + }, + }, + ], +}); From 62064cab1f56c6a1daff2f6ca0ac9ab9e1d453d6 Mon Sep 17 00:00:00 2001 From: Sourab Pramanik Date: Thu, 8 Feb 2024 17:46:29 +0530 Subject: [PATCH 134/239] feat: actix + react + clerk example (#133) * feat: added new clerk example Adding a new fullstack example application to showcase the usage of Clerk in Rust(using shuttle runtime) and NextJS * chore: remove unused files * feat: adding variables example * fix: cors error * feat: added auth middleware * feat: added data in response payload * feat: using shuttle secret * fix: api authentication * feat: added user table and signout button * fix: ui fixes * feat: use vite react+clerk template, shuttle secrets, and static serving of frontend assets * fix: ui fixes * feat: added tailwind and swr to vite app * feat: final fixes and move to `frontend` folder * fix: names and api call * update readme * chore: move clerk template into actix folder * docs: add template to readme listing * feat: user extractor added * fix: cleanup of endpoints and data models * update README --------- Co-authored-by: jonaro00 <54029719+jonaro00@users.noreply.github.com> --- README.md | 3 +- actix-web/clerk/.gitignore | 3 + actix-web/clerk/Cargo.toml | 5 + actix-web/clerk/README.md | 29 + actix-web/clerk/Shuttle.toml | 4 + actix-web/clerk/backend/Cargo.toml | 15 + actix-web/clerk/backend/Secrets.toml.example | 1 + actix-web/clerk/backend/src/main.rs | 121 + actix-web/clerk/frontend/.env.example | 1 + actix-web/clerk/frontend/.eslintrc.cjs | 18 + actix-web/clerk/frontend/.gitignore | 24 + actix-web/clerk/frontend/components.json | 17 + actix-web/clerk/frontend/index.html | 12 + actix-web/clerk/frontend/package-lock.json | 3931 +++++++++++++++++ actix-web/clerk/frontend/package.json | 38 + actix-web/clerk/frontend/postcss.config.js | 6 + actix-web/clerk/frontend/src/App.tsx | 17 + .../frontend/src/components/ui/avatar.tsx | 48 + .../frontend/src/components/ui/table.tsx | 117 + .../frontend/src/components/users-table.tsx | 62 + actix-web/clerk/frontend/src/index.css | 45 + actix-web/clerk/frontend/src/lib/utils.ts | 6 + actix-web/clerk/frontend/src/main.tsx | 20 + actix-web/clerk/frontend/src/vite-env.d.ts | 1 + actix-web/clerk/frontend/tailwind.config.js | 77 + actix-web/clerk/frontend/tsconfig.json | 39 + actix-web/clerk/frontend/tsconfig.node.json | 10 + actix-web/clerk/frontend/vite.config.ts | 12 + 28 files changed, 4681 insertions(+), 1 deletion(-) create mode 100644 actix-web/clerk/.gitignore create mode 100644 actix-web/clerk/Cargo.toml create mode 100644 actix-web/clerk/README.md create mode 100644 actix-web/clerk/Shuttle.toml create mode 100644 actix-web/clerk/backend/Cargo.toml create mode 100644 actix-web/clerk/backend/Secrets.toml.example create mode 100644 actix-web/clerk/backend/src/main.rs create mode 100755 actix-web/clerk/frontend/.env.example create mode 100755 actix-web/clerk/frontend/.eslintrc.cjs create mode 100755 actix-web/clerk/frontend/.gitignore create mode 100644 actix-web/clerk/frontend/components.json create mode 100755 actix-web/clerk/frontend/index.html create mode 100644 actix-web/clerk/frontend/package-lock.json create mode 100755 actix-web/clerk/frontend/package.json create mode 100644 actix-web/clerk/frontend/postcss.config.js create mode 100755 actix-web/clerk/frontend/src/App.tsx create mode 100644 actix-web/clerk/frontend/src/components/ui/avatar.tsx create mode 100644 actix-web/clerk/frontend/src/components/ui/table.tsx create mode 100644 actix-web/clerk/frontend/src/components/users-table.tsx create mode 100755 actix-web/clerk/frontend/src/index.css create mode 100644 actix-web/clerk/frontend/src/lib/utils.ts create mode 100755 actix-web/clerk/frontend/src/main.tsx create mode 100755 actix-web/clerk/frontend/src/vite-env.d.ts create mode 100644 actix-web/clerk/frontend/tailwind.config.js create mode 100755 actix-web/clerk/frontend/tsconfig.json create mode 100755 actix-web/clerk/frontend/tsconfig.node.json create mode 100755 actix-web/clerk/frontend/vite.config.ts diff --git a/README.md b/README.md index 26f27064..fd4d80b9 100644 --- a/README.md +++ b/README.md @@ -48,10 +48,11 @@ cargo shuttle deploy This is a list of all examples maintained in this repository. **Framework** | **Name & Link** | **Description** | **Command** ---------------|-----------------|-------------|---------------- +--------------|-----------------|-----------------|------------- Actix Web | [hello-world](./actix-web/hello-world/) | Hello World | `cargo shuttle init --template actix-web` Actix Web | [postgres](./actix-web/postgres/) | TODO app with a Postgres DB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/postgres` Actix Web | [static-files](./actix-web/static-files/) | Hello World page that serves static HTML and JS files | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/static-files` +Actix Web | [clerk](./actix-web/clerk/) | A React + Tailwind app that uses Clerk as an auth provider | `cargo shuttle init cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/clerk` Actix Web | [websocket-actorless](./actix-web/websocket-actorless/) | Websocket app that checks the status of Shuttle's API | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/websocket-actorless` Actix Web | [cookie-authentication](./actix-web/cookie-authentication/) | Use JWT to authenticate API endpoints | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/cookie-authentication` Axum | [hello-world](./axum/hello-world/) | Hello World | `cargo shuttle init --template axum` diff --git a/actix-web/clerk/.gitignore b/actix-web/clerk/.gitignore new file mode 100644 index 00000000..04868a2b --- /dev/null +++ b/actix-web/clerk/.gitignore @@ -0,0 +1,3 @@ +/target +.shuttle-storage +**/Secrets*.toml diff --git a/actix-web/clerk/Cargo.toml b/actix-web/clerk/Cargo.toml new file mode 100644 index 00000000..9a504184 --- /dev/null +++ b/actix-web/clerk/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +resolver = "2" +members = [ + "backend", +] diff --git a/actix-web/clerk/README.md b/actix-web/clerk/README.md new file mode 100644 index 00000000..b2a6abea --- /dev/null +++ b/actix-web/clerk/README.md @@ -0,0 +1,29 @@ +# Using Clerk auth with a Rust Actix web backend + +This template uses Actix-web and the clerk-rs crate for providing authentication from Clerk in the backend. + +The frontend is a simple React app that uses Clerk's React components. + +The template simply shows a list of all signed up users after you sign in, but it can be extended to create a full app with authenticated endpoints. + +## How to use this template + +Clone this template with `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/clerk`. + +Sign up at clerk.com, go to the dashboard and create an application with the sign-in options you prefer. + +Get the `CLERK_SECRET_KEY` secret and put it in `backend/Secrets.toml`. +Make sure you don't commit this file. + +Get the `VITE_CLERK_PUBLISHABLE_KEY` secret and put it in `frontend/.env`. + +> The frontend was initialized from the React+TS template in `npm create vite@latest`. +> The Clerk components were then added by following the guide at . + +cd into the frontend and run `npm install` and `npm run build`. This builds the frontend assets and places them in `frontend/dist`. + +cd back to the root and run `cargo shuttle run`. +The backend serves the web page from the dist folder, and an auth-protected API that fetches the list of all users that have signed up so far. + +You can then do `cargo shuttle project start` and `cargo shuttle deploy`, but consider switching to a production key from Clerk. +The development key can still be used in `Secrets.dev.toml`. diff --git a/actix-web/clerk/Shuttle.toml b/actix-web/clerk/Shuttle.toml new file mode 100644 index 00000000..96eab060 --- /dev/null +++ b/actix-web/clerk/Shuttle.toml @@ -0,0 +1,4 @@ +name = "shuttle-actix-react-clerk" +assets = [ + "frontend/dist/*", +] diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml new file mode 100644 index 00000000..ad055455 --- /dev/null +++ b/actix-web/clerk/backend/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "actix-react-clerk" +version = "0.1.0" +edition = "2021" + +[dependencies] +actix-web = "4.4.1" +actix-files = "0.6.5" +clerk-rs = "0.2.3" +openssl-sys = { version = "0.9.9", features = ["vendored"] } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +shuttle-actix-web = "0.38.0" +shuttle-runtime = "0.38.0" +shuttle-secrets = "0.38.0" diff --git a/actix-web/clerk/backend/Secrets.toml.example b/actix-web/clerk/backend/Secrets.toml.example new file mode 100644 index 00000000..0c4d3056 --- /dev/null +++ b/actix-web/clerk/backend/Secrets.toml.example @@ -0,0 +1 @@ +CLERK_SECRET_KEY = "" diff --git a/actix-web/clerk/backend/src/main.rs b/actix-web/clerk/backend/src/main.rs new file mode 100644 index 00000000..627a5a9a --- /dev/null +++ b/actix-web/clerk/backend/src/main.rs @@ -0,0 +1,121 @@ +use actix_web::{ + dev::ServiceRequest, + get, + web::{self, ServiceConfig}, + HttpRequest, HttpResponse, Responder, +}; +use clerk_rs::{ + apis::users_api::User, + clerk::Clerk, + validators::actix::{clerk_authorize, ClerkMiddleware}, + ClerkConfiguration, +}; +use serde::{Deserialize, Serialize}; +use shuttle_actix_web::ShuttleActixWeb; +use shuttle_secrets::SecretStore; + +struct AppState { + client: Clerk, +} + +// Get the full user list of everyone who has signed in to this app +#[get("/users")] +async fn get_users(state: web::Data) -> impl Responder { + let Ok(all_users) = User::get_user_list( + &state.client, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + ) + .await + else { + return HttpResponse::InternalServerError().json(serde_json::json!({ + "message": "Unable to retrieve all users", + })); + }; + + HttpResponse::Ok().json( + all_users + .into_iter() + .map(|u| u.into()) + .collect::>(), + ) +} + +// Example endpoint for extracting the calling user +#[get("/users/me")] +async fn get_user(state: web::Data, req: HttpRequest) -> impl Responder { + let srv_req = ServiceRequest::from_request(req); + let jwt = match clerk_authorize(&srv_req, &state.client, true).await { + Ok(value) => value.1, + Err(e) => return e, + }; + + let Ok(user) = User::get_user(&state.client, &jwt.sub).await else { + return HttpResponse::InternalServerError().json(serde_json::json!({ + "message": "Unable to retrieve user", + })); + }; + + HttpResponse::Ok().json(Into::::into(user)) +} + +#[shuttle_runtime::main] +async fn main( + #[shuttle_secrets::Secrets] secrets: SecretStore, +) -> ShuttleActixWeb { + let app_config = move |cfg: &mut ServiceConfig| { + let clerk_secret_key = secrets + .get("CLERK_SECRET_KEY") + .expect("Clerk Secret key is not set"); + let clerk_config = ClerkConfiguration::new(None, None, Some(clerk_secret_key), None); + let client = Clerk::new(clerk_config.clone()); + + let state = web::Data::new(AppState { client }); + + cfg.service( + // protect the /api routes with clerk authentication + web::scope("/api") + .wrap(ClerkMiddleware::new(clerk_config, None, true)) + .service(get_users) + .service(get_user), + ) + // serve the build files from the frontend + .service(actix_files::Files::new("/", "./frontend/dist").index_file("index.html")) + .app_data(state); + }; + + Ok(app_config.into()) +} + +/// As subset of the fields in [`clerk_rs::models::user::User`] +#[derive(Serialize, Deserialize)] +struct UserModel { + id: Option, + username: Option>, + first_name: Option>, + last_name: Option>, + email_addresses: Option>, + profile_image_url: Option, +} + +impl From for UserModel { + fn from(value: clerk_rs::models::user::User) -> Self { + Self { + id: value.id, + username: value.username, + first_name: value.first_name, + last_name: value.last_name, + email_addresses: value.email_addresses, + profile_image_url: value.profile_image_url, + } + } +} diff --git a/actix-web/clerk/frontend/.env.example b/actix-web/clerk/frontend/.env.example new file mode 100755 index 00000000..4d8bc119 --- /dev/null +++ b/actix-web/clerk/frontend/.env.example @@ -0,0 +1 @@ +VITE_CLERK_PUBLISHABLE_KEY= diff --git a/actix-web/clerk/frontend/.eslintrc.cjs b/actix-web/clerk/frontend/.eslintrc.cjs new file mode 100755 index 00000000..d6c95379 --- /dev/null +++ b/actix-web/clerk/frontend/.eslintrc.cjs @@ -0,0 +1,18 @@ +module.exports = { + root: true, + env: { browser: true, es2020: true }, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:react-hooks/recommended', + ], + ignorePatterns: ['dist', '.eslintrc.cjs'], + parser: '@typescript-eslint/parser', + plugins: ['react-refresh'], + rules: { + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, +} diff --git a/actix-web/clerk/frontend/.gitignore b/actix-web/clerk/frontend/.gitignore new file mode 100755 index 00000000..3f23b745 --- /dev/null +++ b/actix-web/clerk/frontend/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +*.local +.env + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/actix-web/clerk/frontend/components.json b/actix-web/clerk/frontend/components.json new file mode 100644 index 00000000..c7a2b627 --- /dev/null +++ b/actix-web/clerk/frontend/components.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "default", + "rsc": false, + "tsx": true, + "tailwind": { + "config": "tailwind.config.js", + "css": "src/index.css", + "baseColor": "stone", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils" + } +} \ No newline at end of file diff --git a/actix-web/clerk/frontend/index.html b/actix-web/clerk/frontend/index.html new file mode 100755 index 00000000..bd5875d5 --- /dev/null +++ b/actix-web/clerk/frontend/index.html @@ -0,0 +1,12 @@ + + + + + + Vite + React + TS + Rust + Actix Web + Shuttle + + +
    + + + diff --git a/actix-web/clerk/frontend/package-lock.json b/actix-web/clerk/frontend/package-lock.json new file mode 100644 index 00000000..43848eab --- /dev/null +++ b/actix-web/clerk/frontend/package-lock.json @@ -0,0 +1,3931 @@ +{ + "name": "frontend", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "frontend", + "version": "0.0.0", + "dependencies": { + "@clerk/clerk-react": "^4.30.3", + "@radix-ui/react-avatar": "^1.0.4", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.0", + "lucide-react": "^0.319.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "swr": "^2.2.4", + "tailwind-merge": "^2.2.1", + "tailwindcss-animate": "^1.0.7" + }, + "devDependencies": { + "@types/node": "^20.11.10", + "@types/react": "^18.2.43", + "@types/react-dom": "^18.2.17", + "@typescript-eslint/eslint-plugin": "^6.14.0", + "@typescript-eslint/parser": "^6.14.0", + "@vitejs/plugin-react": "^4.2.1", + "autoprefixer": "^10.4.17", + "eslint": "^8.55.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.5", + "postcss": "^8.4.33", + "tailwindcss": "^3.4.1", + "typescript": "^5.2.2", + "vite": "^5.0.8" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", + "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.9", + "@babel/parser": "^7.23.9", + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", + "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", + "dev": true, + "dependencies": { + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", + "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.23.3.tgz", + "integrity": "sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.23.3.tgz", + "integrity": "sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", + "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", + "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", + "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", + "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@clerk/clerk-react": { + "version": "4.30.3", + "resolved": "https://registry.npmjs.org/@clerk/clerk-react/-/clerk-react-4.30.3.tgz", + "integrity": "sha512-bX4fUxGXUrMl8A50TpeUM8PHFKbMHmt7UfJ/NnUQMBN54h9N/NF2eSE2omY1+lDxBJmh/V9EiJZV8S6MwDflzw==", + "dependencies": { + "@clerk/shared": "1.3.1", + "@clerk/types": "3.60.0", + "tslib": "2.4.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16" + } + }, + "node_modules/@clerk/shared": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@clerk/shared/-/shared-1.3.1.tgz", + "integrity": "sha512-nzv4+uA90I/eQp55zfK9a1Po9VgCYlzlNhuZnKqyRsPyJ38l4gpIf3B3qSHHdN0+MTx9cWGFrik1CnpftdOBXQ==", + "dependencies": { + "glob-to-regexp": "0.4.1", + "js-cookie": "3.0.1", + "swr": "2.2.0" + }, + "peerDependencies": { + "react": ">=16" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + }, + "node_modules/@clerk/shared/node_modules/swr": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/swr/-/swr-2.2.0.tgz", + "integrity": "sha512-AjqHOv2lAhkuUdIiBu9xbuettzAzWXmCEcLONNKJRba87WAefz8Ca9d6ds/SzrPc235n1IxWYdhJ2zF3MNUaoQ==", + "dependencies": { + "use-sync-external-store": "^1.2.0" + }, + "peerDependencies": { + "react": "^16.11.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@clerk/types": { + "version": "3.60.0", + "resolved": "https://registry.npmjs.org/@clerk/types/-/types-3.60.0.tgz", + "integrity": "sha512-f1A16wFh5MtikxEo7o6vAVX7FxpqC1YmzA6c4ugwq5MH8J2mvIM/LwNVIHgNpZkn/s/G+BUhBcJJmUXqajDK2Q==", + "dependencies": { + "csstype": "3.1.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@clerk/types/node_modules/csstype": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", + "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", + "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@radix-ui/react-avatar": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.0.4.tgz", + "integrity": "sha512-kVK2K7ZD3wwj3qhle0ElXhOjbezIgyl2hVvgwfIdexL3rN6zJmy5AqqIf+D31lxVppdzV8CjAfZ6PklkmInZLw==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", + "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz", + "integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz", + "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-slot": "1.0.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", + "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", + "integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz", + "integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.6.tgz", + "integrity": "sha512-HUNqM32dGzfBKuaDUBqFB7tP6VMN74eLZ33Q9Y1TBqRDn+qDonkAUyKWwF9BR9unV7QUzffLnz9GrnKvMqC/fw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.6.tgz", + "integrity": "sha512-ch7M+9Tr5R4FK40FHQk8VnML0Szi2KRujUgHXd/HjuH9ifH72GUmw6lStZBo3c3GB82vHa0ZoUfjfcM7JiiMrQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.11.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.10.tgz", + "integrity": "sha512-rZEfe/hJSGYmdfX9tvcPMYeYPW2sNl50nsw4jZmRcaG0HIAb0WYEpsB05GOb53vjqpyE9GUhlDQ4jLSoB5q9kg==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.11", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", + "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==", + "devOptional": true + }, + "node_modules/@types/react": { + "version": "18.2.48", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.48.tgz", + "integrity": "sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==", + "devOptional": true, + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.2.18", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz", + "integrity": "sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==", + "devOptional": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==", + "devOptional": true + }, + "node_modules/@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.20.0.tgz", + "integrity": "sha512-fTwGQUnjhoYHeSF6m5pWNkzmDDdsKELYrOBxhjMrofPqCkoC2k3B2wvGHFxa1CTIqkEn88nlW1HVMztjo2K8Hg==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.20.0", + "@typescript-eslint/type-utils": "6.20.0", + "@typescript-eslint/utils": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.20.0.tgz", + "integrity": "sha512-bYerPDF/H5v6V76MdMYhjwmwgMA+jlPVqjSDq2cRqMi8bP5sR3Z+RLOiOMad3nsnmDVmn2gAFCyNgh/dIrfP/w==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.20.0", + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/typescript-estree": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz", + "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.20.0.tgz", + "integrity": "sha512-qnSobiJQb1F5JjN0YDRPHruQTrX7ICsmltXhkV536mp4idGAYrIyr47zF/JmkJtEcAVnIz4gUYJ7gOZa6SmN4g==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.20.0", + "@typescript-eslint/utils": "6.20.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz", + "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz", + "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/visitor-keys": "6.20.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.20.0.tgz", + "integrity": "sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.20.0", + "@typescript-eslint/types": "6.20.0", + "@typescript-eslint/typescript-estree": "6.20.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz", + "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.20.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz", + "integrity": "sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.5", + "@babel/plugin-transform-react-jsx-self": "^7.23.3", + "@babel/plugin-transform-react-jsx-source": "^7.23.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0" + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.17", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz", + "integrity": "sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.22.2", + "caniuse-lite": "^1.0.30001578", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.22.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", + "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001580", + "electron-to-chromium": "^1.4.648", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001581", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001581.tgz", + "integrity": "sha512-whlTkwhqV2tUmP3oYhtNfaWGYHDdS3JYFQBKXxcUR9qqPWsRhFHhoISO2Xnl/g0xyKzht9mI1LZpiNWfMzHixQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/class-variance-authority": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.0.tgz", + "integrity": "sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==", + "dependencies": { + "clsx": "2.0.0" + }, + "funding": { + "url": "https://joebell.co.uk" + } + }, + "node_modules/class-variance-authority/node_modules/clsx": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", + "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + }, + "node_modules/clsx": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", + "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "devOptional": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.650", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.650.tgz", + "integrity": "sha512-sYSQhJCJa4aGA1wYol5cMQgekDBlbVfTRavlGZVr3WZpDdOPcp6a6xUnFfrt8TqZhsBYYbDxJZCjGfHuGupCRQ==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.5.tgz", + "integrity": "sha512-D53FYKJa+fDmZMtriODxvhwrO+IOqrxoEo21gMA0sjHdU6dPVH4OhyFip9ypl8HOF5RV5KdTo+rBQLvnY2cO8w==", + "dev": true, + "peerDependencies": { + "eslint": ">=7" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz", + "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-cookie": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz", + "integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lucide-react": { + "version": "0.319.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.319.0.tgz", + "integrity": "sha512-IIbu4TfVI3yPI3ba/Li53mKeOd+WwcWI6+WcyoVdFLtrBfH88m2uQ/uTmtzBWt523HyxCFjWy3RFs0OxDFYm8w==", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss": { + "version": "8.4.33", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", + "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", + "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "engines": { + "node": ">=14" + } + }, + "node_modules/postcss-nested": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", + "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.11" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.15", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", + "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-refresh": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", + "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.6.tgz", + "integrity": "sha512-05lzkCS2uASX0CiLFybYfVkwNbKZG5NFQ6Go0VWyogFTXXbR039UVsegViTntkk4OglHBdF54ccApXRRuXRbsg==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.9.6", + "@rollup/rollup-android-arm64": "4.9.6", + "@rollup/rollup-darwin-arm64": "4.9.6", + "@rollup/rollup-darwin-x64": "4.9.6", + "@rollup/rollup-linux-arm-gnueabihf": "4.9.6", + "@rollup/rollup-linux-arm64-gnu": "4.9.6", + "@rollup/rollup-linux-arm64-musl": "4.9.6", + "@rollup/rollup-linux-riscv64-gnu": "4.9.6", + "@rollup/rollup-linux-x64-gnu": "4.9.6", + "@rollup/rollup-linux-x64-musl": "4.9.6", + "@rollup/rollup-win32-arm64-msvc": "4.9.6", + "@rollup/rollup-win32-ia32-msvc": "4.9.6", + "@rollup/rollup-win32-x64-msvc": "4.9.6", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/swr": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/swr/-/swr-2.2.4.tgz", + "integrity": "sha512-njiZ/4RiIhoOlAaLYDqwz5qH/KZXVilRLvomrx83HjzCWTfa+InyfAjv05PSFxnmLzZkNO9ZfvgoqzAaEI4sGQ==", + "dependencies": { + "client-only": "^0.0.1", + "use-sync-external-store": "^1.2.0" + }, + "peerDependencies": { + "react": "^16.11.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/tailwind-merge": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.2.1.tgz", + "integrity": "sha512-o+2GTLkthfa5YUt4JxPfzMIpQzZ3adD1vLVkvKE1Twl9UAhGsEbIZhHHZVRttyW177S8PDJI3bTQNaebyofK3Q==", + "dependencies": { + "@babel/runtime": "^7.23.7" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz", + "integrity": "sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.19.1", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss-animate": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", + "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" + }, + "node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/vite": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.12.tgz", + "integrity": "sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==", + "dev": true, + "dependencies": { + "esbuild": "^0.19.3", + "postcss": "^8.4.32", + "rollup": "^4.2.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yaml": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/actix-web/clerk/frontend/package.json b/actix-web/clerk/frontend/package.json new file mode 100755 index 00000000..c1c54cad --- /dev/null +++ b/actix-web/clerk/frontend/package.json @@ -0,0 +1,38 @@ +{ + "name": "frontend", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "build": "tsc && vite build", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0" + }, + "dependencies": { + "@clerk/clerk-react": "^4.30.3", + "@radix-ui/react-avatar": "^1.0.4", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.0", + "lucide-react": "^0.319.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "swr": "^2.2.4", + "tailwind-merge": "^2.2.1", + "tailwindcss-animate": "^1.0.7" + }, + "devDependencies": { + "@types/node": "^20.11.10", + "@types/react": "^18.2.43", + "@types/react-dom": "^18.2.17", + "@typescript-eslint/eslint-plugin": "^6.14.0", + "@typescript-eslint/parser": "^6.14.0", + "@vitejs/plugin-react": "^4.2.1", + "autoprefixer": "^10.4.17", + "eslint": "^8.55.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.5", + "postcss": "^8.4.33", + "tailwindcss": "^3.4.1", + "typescript": "^5.2.2", + "vite": "^5.0.8" + } +} diff --git a/actix-web/clerk/frontend/postcss.config.js b/actix-web/clerk/frontend/postcss.config.js new file mode 100644 index 00000000..2e7af2b7 --- /dev/null +++ b/actix-web/clerk/frontend/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/actix-web/clerk/frontend/src/App.tsx b/actix-web/clerk/frontend/src/App.tsx new file mode 100755 index 00000000..045e7139 --- /dev/null +++ b/actix-web/clerk/frontend/src/App.tsx @@ -0,0 +1,17 @@ +import { SignIn, SignedIn, SignedOut } from "@clerk/clerk-react"; +import UsersTable from "./components/users-table"; + +function App() { + return ( +
    + + + + + + +
    + ); +} + +export default App; diff --git a/actix-web/clerk/frontend/src/components/ui/avatar.tsx b/actix-web/clerk/frontend/src/components/ui/avatar.tsx new file mode 100644 index 00000000..991f56ec --- /dev/null +++ b/actix-web/clerk/frontend/src/components/ui/avatar.tsx @@ -0,0 +1,48 @@ +import * as React from "react" +import * as AvatarPrimitive from "@radix-ui/react-avatar" + +import { cn } from "@/lib/utils" + +const Avatar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Avatar.displayName = AvatarPrimitive.Root.displayName + +const AvatarImage = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarImage.displayName = AvatarPrimitive.Image.displayName + +const AvatarFallback = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName + +export { Avatar, AvatarImage, AvatarFallback } diff --git a/actix-web/clerk/frontend/src/components/ui/table.tsx b/actix-web/clerk/frontend/src/components/ui/table.tsx new file mode 100644 index 00000000..7f3502f8 --- /dev/null +++ b/actix-web/clerk/frontend/src/components/ui/table.tsx @@ -0,0 +1,117 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Table = React.forwardRef< + HTMLTableElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
    + + +)) +Table.displayName = "Table" + +const TableHeader = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableHeader.displayName = "TableHeader" + +const TableBody = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableBody.displayName = "TableBody" + +const TableFooter = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + tr]:last:border-b-0", + className + )} + {...props} + /> +)) +TableFooter.displayName = "TableFooter" + +const TableRow = React.forwardRef< + HTMLTableRowElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableRow.displayName = "TableRow" + +const TableHead = React.forwardRef< + HTMLTableCellElement, + React.ThHTMLAttributes +>(({ className, ...props }, ref) => ( + + + + + diff --git a/axum/htmx-crud/templates/todos.html b/axum/htmx-crud/templates/todos.html new file mode 100644 index 00000000..257b3dcf --- /dev/null +++ b/axum/htmx-crud/templates/todos.html @@ -0,0 +1,14 @@ +
    +
    +)) +TableHead.displayName = "TableHead" + +const TableCell = React.forwardRef< + HTMLTableCellElement, + React.TdHTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableCell.displayName = "TableCell" + +const TableCaption = React.forwardRef< + HTMLTableCaptionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
    +)) +TableCaption.displayName = "TableCaption" + +export { + Table, + TableHeader, + TableBody, + TableFooter, + TableHead, + TableRow, + TableCell, + TableCaption, +} diff --git a/actix-web/clerk/frontend/src/components/users-table.tsx b/actix-web/clerk/frontend/src/components/users-table.tsx new file mode 100644 index 00000000..827d91b4 --- /dev/null +++ b/actix-web/clerk/frontend/src/components/users-table.tsx @@ -0,0 +1,62 @@ +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; +import { UserButton } from "@clerk/clerk-react"; +import { Loader } from "lucide-react"; +import useSWR from "swr"; + +export interface UserSchema { + first_name: string; + last_name: string; + username: string; + email_addresses: { email_address: string; id: string }[]; + profile_image_url: string; +} + +export default function UsersTable() { + const { isLoading, data } = useSWR("/api/users", (url) => fetch(url).then(res => res.json())); + + return ( + <> +
    + +
    + {isLoading && } + {!isLoading && ( + + + + Avatar + First Name + Last Name + Username + Email + + + + {data.map((user: UserSchema, i: number) => ( + + + + + {user?.username} + + + {user?.first_name} + {user?.last_name} + {user?.username} + {user?.email_addresses?.[0].email_address} + + ))} + +
    + )} + + ); +} diff --git a/actix-web/clerk/frontend/src/index.css b/actix-web/clerk/frontend/src/index.css new file mode 100755 index 00000000..ca63dd9b --- /dev/null +++ b/actix-web/clerk/frontend/src/index.css @@ -0,0 +1,45 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --background: 20 14.3% 4.1%; + --foreground: 60 9.1% 97.8%; + + --card: 20 14.3% 4.1%; + --card-foreground: 60 9.1% 97.8%; + + --popover: 20 14.3% 4.1%; + --popover-foreground: 60 9.1% 97.8%; + + --primary: 60 9.1% 97.8%; + --primary-foreground: 24 9.8% 10%; + + --secondary: 12 6.5% 15.1%; + --secondary-foreground: 60 9.1% 97.8%; + + --muted: 12 6.5% 15.1%; + --muted-foreground: 24 5.4% 63.9%; + + --accent: 12 6.5% 15.1%; + --accent-foreground: 60 9.1% 97.8%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 60 9.1% 97.8%; + + --border: 12 6.5% 15.1%; + --input: 12 6.5% 15.1%; + --ring: 24 5.7% 82.9%; + } +} + +@layer base { + * { + @apply border-border; + } + + body { + @apply bg-background text-foreground; + } +} diff --git a/actix-web/clerk/frontend/src/lib/utils.ts b/actix-web/clerk/frontend/src/lib/utils.ts new file mode 100644 index 00000000..d084ccad --- /dev/null +++ b/actix-web/clerk/frontend/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { type ClassValue, clsx } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/actix-web/clerk/frontend/src/main.tsx b/actix-web/clerk/frontend/src/main.tsx new file mode 100755 index 00000000..57cf908e --- /dev/null +++ b/actix-web/clerk/frontend/src/main.tsx @@ -0,0 +1,20 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App.tsx' +import './index.css' +import { ClerkProvider } from '@clerk/clerk-react' + +// Import your publishable key +const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY + +if (!PUBLISHABLE_KEY) { + throw new Error("Missing Publishable Key") +} + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + + + , +) diff --git a/actix-web/clerk/frontend/src/vite-env.d.ts b/actix-web/clerk/frontend/src/vite-env.d.ts new file mode 100755 index 00000000..11f02fe2 --- /dev/null +++ b/actix-web/clerk/frontend/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/actix-web/clerk/frontend/tailwind.config.js b/actix-web/clerk/frontend/tailwind.config.js new file mode 100644 index 00000000..7cb7e37a --- /dev/null +++ b/actix-web/clerk/frontend/tailwind.config.js @@ -0,0 +1,77 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + darkMode: ["class"], + content: [ + './pages/**/*.{ts,tsx}', + './components/**/*.{ts,tsx}', + './app/**/*.{ts,tsx}', + './src/**/*.{ts,tsx}', + ], + prefix: "", + theme: { + container: { + center: true, + padding: "2rem", + screens: { + "2xl": "1400px", + }, + }, + extend: { + colors: { + border: "hsl(var(--border))", + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + primary: { + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + destructive: { + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", + }, + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", + }, + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", + }, + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + keyframes: { + "accordion-down": { + from: { height: "0" }, + to: { height: "var(--radix-accordion-content-height)" }, + }, + "accordion-up": { + from: { height: "var(--radix-accordion-content-height)" }, + to: { height: "0" }, + }, + }, + animation: { + "accordion-down": "accordion-down 0.2s ease-out", + "accordion-up": "accordion-up 0.2s ease-out", + }, + }, + }, + plugins: [require("tailwindcss-animate")], +} \ No newline at end of file diff --git a/actix-web/clerk/frontend/tsconfig.json b/actix-web/clerk/frontend/tsconfig.json new file mode 100755 index 00000000..8464ccc6 --- /dev/null +++ b/actix-web/clerk/frontend/tsconfig.json @@ -0,0 +1,39 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": [ + "ES2020", + "DOM", + "DOM.Iterable" + ], + "module": "ESNext", + "skipLibCheck": true, + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "baseUrl": ".", + "paths": { + "@/*": [ + "./src/*" + ] + } + }, + "include": [ + "src" + ], + "references": [ + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/actix-web/clerk/frontend/tsconfig.node.json b/actix-web/clerk/frontend/tsconfig.node.json new file mode 100755 index 00000000..42872c59 --- /dev/null +++ b/actix-web/clerk/frontend/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/actix-web/clerk/frontend/vite.config.ts b/actix-web/clerk/frontend/vite.config.ts new file mode 100755 index 00000000..5790e820 --- /dev/null +++ b/actix-web/clerk/frontend/vite.config.ts @@ -0,0 +1,12 @@ +import path from "path" +import react from "@vitejs/plugin-react" +import { defineConfig } from "vite" + +export default defineConfig({ + plugins: [react()], + resolve: { + alias: { + "@": path.resolve(__dirname, "./src"), + }, + }, +}) From c8fbee25c60d5f4f01cc09607766998bdf68a4d3 Mon Sep 17 00:00:00 2001 From: Elad Kaplan Date: Tue, 13 Feb 2024 02:12:37 -0800 Subject: [PATCH 135/239] add loco framework template (#139) * add loco framework template * add loco to readme * remove workspace from Cargo.toml * return [workspace] * change default port from 3000 to 8000 and change readme * add .cargo * fix fmt --- README.md | 1 + loco/hello-world/.cargo/config.toml | 2 + loco/hello-world/.devcontainer/.env | 0 loco/hello-world/.devcontainer/Dockerfile | 8 ++ .../.devcontainer/devcontainer.json | 9 +++ .../.devcontainer/docker-compose.yml | 12 +++ loco/hello-world/.github/workflows/ci.yaml | 80 +++++++++++++++++++ loco/hello-world/.gitignore | 16 ++++ loco/hello-world/Cargo.toml | 43 ++++++++++ loco/hello-world/README.md | 16 ++++ loco/hello-world/Shuttle.toml | 1 + loco/hello-world/config/development.yaml | 45 +++++++++++ loco/hello-world/config/production.yaml | 45 +++++++++++ loco/hello-world/config/test.yaml | 42 ++++++++++ loco/hello-world/src/app.rs | 44 ++++++++++ loco/hello-world/src/bin/main.rs | 7 ++ loco/hello-world/src/bin/shuttle.rs | 19 +++++ loco/hello-world/src/controllers/home.rs | 11 +++ loco/hello-world/src/controllers/mod.rs | 1 + loco/hello-world/src/lib.rs | 3 + loco/hello-world/src/views/home.rs | 16 ++++ loco/hello-world/src/views/mod.rs | 1 + loco/hello-world/tests/mod.rs | 1 + loco/hello-world/tests/requests/home.rs | 28 +++++++ loco/hello-world/tests/requests/mod.rs | 1 + .../snapshots/can_get_home@home_request.snap | 8 ++ 26 files changed, 460 insertions(+) create mode 100644 loco/hello-world/.cargo/config.toml create mode 100644 loco/hello-world/.devcontainer/.env create mode 100644 loco/hello-world/.devcontainer/Dockerfile create mode 100644 loco/hello-world/.devcontainer/devcontainer.json create mode 100644 loco/hello-world/.devcontainer/docker-compose.yml create mode 100644 loco/hello-world/.github/workflows/ci.yaml create mode 100644 loco/hello-world/.gitignore create mode 100644 loco/hello-world/Cargo.toml create mode 100644 loco/hello-world/README.md create mode 100644 loco/hello-world/Shuttle.toml create mode 100644 loco/hello-world/config/development.yaml create mode 100644 loco/hello-world/config/production.yaml create mode 100644 loco/hello-world/config/test.yaml create mode 100644 loco/hello-world/src/app.rs create mode 100644 loco/hello-world/src/bin/main.rs create mode 100644 loco/hello-world/src/bin/shuttle.rs create mode 100644 loco/hello-world/src/controllers/home.rs create mode 100644 loco/hello-world/src/controllers/mod.rs create mode 100644 loco/hello-world/src/lib.rs create mode 100644 loco/hello-world/src/views/home.rs create mode 100644 loco/hello-world/src/views/mod.rs create mode 100644 loco/hello-world/tests/mod.rs create mode 100644 loco/hello-world/tests/requests/home.rs create mode 100644 loco/hello-world/tests/requests/mod.rs create mode 100644 loco/hello-world/tests/requests/snapshots/can_get_home@home_request.snap diff --git a/README.md b/README.md index fd4d80b9..73c09aba 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ Axum | [websocket](./axum/websocket/) | Websocket app that checks the status of Axum | [with-state](./axum/with-state/) | Hello World with example of how to utilize State in Axum | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/with-state` Axum | [jwt-authentication](./axum/jwt-authentication/) | Use JWT to authenticate API endpoints | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/jwt-authentication` Axum & Next.js | [saas](./fullstack-templates/saas/) | Competent opinionated fullstack web app with pre-made routes and assets | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder fullstack-templates/saas` +Loco | [hello-world](./loco/hello-world/) | Hello World | `cargo shuttle init --template loco` Poem | [hello-world](./poem/hello-world/) | Hello World | `cargo shuttle init --template poem` Poem | [mongodb](./poem/mongodb/) | TODO app with MongoDB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder poem/mongodb` Poem | [postgres](./poem/postgres/) | TODO app with a Postgres DB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder poem/postgres` diff --git a/loco/hello-world/.cargo/config.toml b/loco/hello-world/.cargo/config.toml new file mode 100644 index 00000000..8b040c15 --- /dev/null +++ b/loco/hello-world/.cargo/config.toml @@ -0,0 +1,2 @@ +[alias] +loco = "run --bin hello_world-cli --" diff --git a/loco/hello-world/.devcontainer/.env b/loco/hello-world/.devcontainer/.env new file mode 100644 index 00000000..e69de29b diff --git a/loco/hello-world/.devcontainer/Dockerfile b/loco/hello-world/.devcontainer/Dockerfile new file mode 100644 index 00000000..fd43f09b --- /dev/null +++ b/loco/hello-world/.devcontainer/Dockerfile @@ -0,0 +1,8 @@ +FROM mcr.microsoft.com/vscode/devcontainers/rust:0-1 + +RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ + && apt-get -y install --no-install-recommends postgresql-client \ + && cargo install cargo-insta \ + && chown -R vscode /usr/local/cargo + +COPY .env /.env diff --git a/loco/hello-world/.devcontainer/devcontainer.json b/loco/hello-world/.devcontainer/devcontainer.json new file mode 100644 index 00000000..6aecc100 --- /dev/null +++ b/loco/hello-world/.devcontainer/devcontainer.json @@ -0,0 +1,9 @@ +{ + "name": "Loco", + "dockerComposeFile": "docker-compose.yml", + "service": "app", + "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", + "forwardPorts": [ + 8000 + ] +} \ No newline at end of file diff --git a/loco/hello-world/.devcontainer/docker-compose.yml b/loco/hello-world/.devcontainer/docker-compose.yml new file mode 100644 index 00000000..3985587e --- /dev/null +++ b/loco/hello-world/.devcontainer/docker-compose.yml @@ -0,0 +1,12 @@ +version: "3" + +services: + app: + build: + context: . + dockerfile: Dockerfile + command: sleep infinity + volumes: + - ../..:/workspaces:cached + env_file: + - .env diff --git a/loco/hello-world/.github/workflows/ci.yaml b/loco/hello-world/.github/workflows/ci.yaml new file mode 100644 index 00000000..15ee4a6a --- /dev/null +++ b/loco/hello-world/.github/workflows/ci.yaml @@ -0,0 +1,80 @@ +name: CI +on: + push: + branches: + - master + - main + pull_request: + +env: + RUST_TOOLCHAIN: stable + TOOLCHAIN_PROFILE: minimal + +jobs: + rustfmt: + name: Check Style + runs-on: ubuntu-latest + + permissions: + contents: read + + steps: + - name: Checkout the code + uses: actions/checkout@v4 + - uses: actions-rs/toolchain@v1 + with: + profile: ${{ env.TOOLCHAIN_PROFILE }} + toolchain: ${{ env.RUST_TOOLCHAIN }} + override: true + components: rustfmt + - name: Run cargo fmt + uses: actions-rs/cargo@v1 + with: + command: fmt + args: --all -- --check + + clippy: + name: Run Clippy + runs-on: ubuntu-latest + + permissions: + contents: read + + steps: + - name: Checkout the code + uses: actions/checkout@v4 + - uses: actions-rs/toolchain@v1 + with: + profile: ${{ env.TOOLCHAIN_PROFILE }} + toolchain: ${{ env.RUST_TOOLCHAIN }} + override: true + - name: Setup Rust cache + uses: Swatinem/rust-cache@v2 + - name: Run cargo clippy + uses: actions-rs/cargo@v1 + with: + command: clippy + args: --all-features -- -D warnings -W clippy::pedantic -W clippy::nursery -W rust-2018-idioms + + test: + name: Run Tests + runs-on: ubuntu-latest + + permissions: + contents: read + + steps: + - name: Checkout the code + uses: actions/checkout@v4 + - uses: actions-rs/toolchain@v1 + with: + profile: ${{ env.TOOLCHAIN_PROFILE }} + toolchain: ${{ env.RUST_TOOLCHAIN }} + override: true + - name: Setup Rust cache + uses: Swatinem/rust-cache@v2 + - name: Run cargo test + uses: actions-rs/cargo@v1 + with: + command: test + args: --all-features --all diff --git a/loco/hello-world/.gitignore b/loco/hello-world/.gitignore new file mode 100644 index 00000000..5d5402d5 --- /dev/null +++ b/loco/hello-world/.gitignore @@ -0,0 +1,16 @@ +**/config/local.yaml + +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml new file mode 100644 index 00000000..721d2b85 --- /dev/null +++ b/loco/hello-world/Cargo.toml @@ -0,0 +1,43 @@ +[workspace] + +[package] +name = "hello_world" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +shuttle-axum = "0.38.0" +shuttle-metadata = "0.38.0" +shuttle-runtime = { version = "0.38.0", default-features = false } + + +loco-rs = { version = "0.3.1", default-features = false, features = ["cli"] } +serde = "*" +serde_json = "*" +eyre = "*" +tokio = { version = "1.33.0", default-features = false } +async-trait = "0.1.74" + +axum = "0.7.1" +tracing = "0.1.40" +tracing-subscriber = { version = "0.3.17", features = ["env-filter", "json"] } + +[[bin]] +name = "hello_world-cli" +path = "src/bin/main.rs" +required-features = [] + +[[bin]] +name = "hello_world" +path = "src/bin/shuttle.rs" + +[dev-dependencies] +serial_test = "*" +rstest = "*" +loco-rs = { version = "0.3.1", default-features = false, features = [ + "testing", + "cli", +] } +insta = { version = "*", features = ["redactions", "yaml", "filters"] } diff --git a/loco/hello-world/README.md b/loco/hello-world/README.md new file mode 100644 index 00000000..9bbcc76f --- /dev/null +++ b/loco/hello-world/README.md @@ -0,0 +1,16 @@ +# Shuttle Loco template :train: + +Welcome to the [Loco](https://loco.rs) Hello World Shuttle Template, designed with a focus on controllers and views (response schema). This minimalistic template comes with several features to kickstart your project: +- **REST API Service without a Database** +- **Workers**: Full-blown background job processing +- **Task**: Ad-hoc functionalities to handle specific aspects of your application +- **Tests**: Testing facility and examples +- And More Loco Features + +## Quick Start + +To launch your app, simply use the following command: + +```sh +$ cargo shuttle run +``` \ No newline at end of file diff --git a/loco/hello-world/Shuttle.toml b/loco/hello-world/Shuttle.toml new file mode 100644 index 00000000..b6451e25 --- /dev/null +++ b/loco/hello-world/Shuttle.toml @@ -0,0 +1 @@ +name = "hello-world" diff --git a/loco/hello-world/config/development.yaml b/loco/hello-world/config/development.yaml new file mode 100644 index 00000000..4f513991 --- /dev/null +++ b/loco/hello-world/config/development.yaml @@ -0,0 +1,45 @@ +# Loco configuration file documentation + +# Application logging configuration +logger: + # Enable or disable logging. + enable: true + # Log level, options: trace, debug, info, warn or error. + level: debug + # Define the logging format. options: compact, pretty or Json + format: compact + # By default the logger has filtering only logs that came from your code or logs that came from `loco` framework. to see all third party libraries + # Uncomment the line below to override to see all third party libraries you can enable this config and override the logger filters. + # override_filter: trace + +# Web server configuration +server: + # Port on which the server will listen. the server binding is 0.0.0.0:{PORT} + port: 8000 + # The UI hostname or IP address that mailers will point to. + host: http://localhost + # Out of the box middleware configuration. to disable middleware you can changed the `enable` field to `false` of comment the middleware block + middlewares: + # Enable Etag cache header middleware + etag: + enable: true + # Allows to limit the payload size request. payload that bigger than this file will blocked the request. + limit_payload: + # Enable/Disable the middleware. + enable: true + # the limit size. can be b,kb,kib,mb,mib,gb,gib + body_limit: 5mb + # Generating a unique request ID and enhancing logging with additional information such as the start and completion of request processing, latency, status code, and other request details. + logger: + # Enable/Disable the middleware. + enable: true + # when your code is panicked, the request still returns 500 status code. + catch_panic: + # Enable/Disable the middleware. + enable: true + # Timeout for incoming requests middleware. requests that take more time from the configuration will cute and 408 status code will returned. + timeout_request: + # Enable/Disable the middleware. + enable: false + # Duration time in milliseconds. + timeout: 5000 diff --git a/loco/hello-world/config/production.yaml b/loco/hello-world/config/production.yaml new file mode 100644 index 00000000..4f513991 --- /dev/null +++ b/loco/hello-world/config/production.yaml @@ -0,0 +1,45 @@ +# Loco configuration file documentation + +# Application logging configuration +logger: + # Enable or disable logging. + enable: true + # Log level, options: trace, debug, info, warn or error. + level: debug + # Define the logging format. options: compact, pretty or Json + format: compact + # By default the logger has filtering only logs that came from your code or logs that came from `loco` framework. to see all third party libraries + # Uncomment the line below to override to see all third party libraries you can enable this config and override the logger filters. + # override_filter: trace + +# Web server configuration +server: + # Port on which the server will listen. the server binding is 0.0.0.0:{PORT} + port: 8000 + # The UI hostname or IP address that mailers will point to. + host: http://localhost + # Out of the box middleware configuration. to disable middleware you can changed the `enable` field to `false` of comment the middleware block + middlewares: + # Enable Etag cache header middleware + etag: + enable: true + # Allows to limit the payload size request. payload that bigger than this file will blocked the request. + limit_payload: + # Enable/Disable the middleware. + enable: true + # the limit size. can be b,kb,kib,mb,mib,gb,gib + body_limit: 5mb + # Generating a unique request ID and enhancing logging with additional information such as the start and completion of request processing, latency, status code, and other request details. + logger: + # Enable/Disable the middleware. + enable: true + # when your code is panicked, the request still returns 500 status code. + catch_panic: + # Enable/Disable the middleware. + enable: true + # Timeout for incoming requests middleware. requests that take more time from the configuration will cute and 408 status code will returned. + timeout_request: + # Enable/Disable the middleware. + enable: false + # Duration time in milliseconds. + timeout: 5000 diff --git a/loco/hello-world/config/test.yaml b/loco/hello-world/config/test.yaml new file mode 100644 index 00000000..67603bba --- /dev/null +++ b/loco/hello-world/config/test.yaml @@ -0,0 +1,42 @@ +# Loco configuration file documentation + +# Application logging configuration +logger: + # Enable or disable logging. + enable: false + # Log level, options: trace, debug, info, warn or error. + level: debug + # Define the logging format. options: compact, pretty or Json + format: compact + # By default the logger has filtering only logs that came from your code or logs that came from `loco` framework. to see all third party libraries + # Uncomment the line below to override to see all third party libraries you can enable this config and override the logger filters. + # override_filter: trace + +# Web server configuration +server: + # Port on which the server will listen. the server binding is 0.0.0.0:{PORT} + port: 8000 + # The UI hostname or IP address that mailers will point to. + host: http://localhost + # Out of the box middleware configuration. to disable middleware you can changed the `enable` field to `false` of comment the middleware block + middlewares: + # Allows to limit the payload size request. payload that bigger than this file will blocked the request. + limit_payload: + # Enable/Disable the middleware. + enable: true + # the limit size. can be b,kb,kib,mb,mib,gb,gib + body_limit: 5mb + # Generating a unique request ID and enhancing logging with additional information such as the start and completion of request processing, latency, status code, and other request details. + logger: + # Enable/Disable the middleware. + enable: true + # when your code is panicked, the request still returns 500 status code. + catch_panic: + # Enable/Disable the middleware. + enable: true + # Timeout for incoming requests middleware. requests that take more time from the configuration will cute and 408 status code will returned. + timeout_request: + # Enable/Disable the middleware. + enable: false + # Duration time in milliseconds. + timeout: 5000 diff --git a/loco/hello-world/src/app.rs b/loco/hello-world/src/app.rs new file mode 100644 index 00000000..5068ff94 --- /dev/null +++ b/loco/hello-world/src/app.rs @@ -0,0 +1,44 @@ +use async_trait::async_trait; +use loco_rs::{ + app::{AppContext, Hooks}, + boot::{create_app, BootResult, StartMode}, + controller::AppRoutes, + environment::Environment, + task::Tasks, + worker::Processor, + Result, +}; + +use crate::controllers; + +pub struct App; +#[async_trait] +impl Hooks for App { + fn app_name() -> &'static str { + env!("CARGO_CRATE_NAME") + } + + fn app_version() -> String { + format!( + "{} ({})", + env!("CARGO_PKG_VERSION"), + option_env!("BUILD_SHA") + .or(option_env!("GITHUB_SHA")) + .unwrap_or("dev") + ) + } + + async fn boot(mode: StartMode, environment: &Environment) -> Result { + create_app::(mode, environment).await + } + + fn routes(_ctx: &AppContext) -> AppRoutes { + AppRoutes::empty() + // .prefix("/api") + .add_route(controllers::home::routes()) + } + + fn connect_workers<'a>(_p: &'a mut Processor, _ctx: &'a AppContext) {} + + fn register_tasks(_tasks: &mut Tasks) {} +} diff --git a/loco/hello-world/src/bin/main.rs b/loco/hello-world/src/bin/main.rs new file mode 100644 index 00000000..236149e2 --- /dev/null +++ b/loco/hello-world/src/bin/main.rs @@ -0,0 +1,7 @@ +use hello_world::app::App; +use loco_rs::cli; + +#[tokio::main] +async fn main() -> eyre::Result<()> { + cli::main::().await +} diff --git a/loco/hello-world/src/bin/shuttle.rs b/loco/hello-world/src/bin/shuttle.rs new file mode 100644 index 00000000..f611a79a --- /dev/null +++ b/loco/hello-world/src/bin/shuttle.rs @@ -0,0 +1,19 @@ +use hello_world::app::App; +use loco_rs::boot::{create_app, StartMode}; +use loco_rs::environment::Environment; + +#[shuttle_runtime::main] +async fn main( + #[shuttle_metadata::ShuttleMetadata] meta: shuttle_metadata::Metadata, +) -> shuttle_axum::ShuttleAxum { + let environment = match meta.env { + shuttle_metadata::Environment::Local => Environment::Development, + shuttle_metadata::Environment::Deployment => Environment::Production, + }; + let boot_result = create_app::(StartMode::ServerOnly, &environment) + .await + .unwrap(); + + let router = boot_result.router.unwrap(); + Ok(router.into()) +} diff --git a/loco/hello-world/src/controllers/home.rs b/loco/hello-world/src/controllers/home.rs new file mode 100644 index 00000000..9e6345d3 --- /dev/null +++ b/loco/hello-world/src/controllers/home.rs @@ -0,0 +1,11 @@ +use loco_rs::prelude::*; + +use crate::views::home::HomeResponse; + +async fn current() -> Result> { + format::json(HomeResponse::new("loco")) +} + +pub fn routes() -> Routes { + Routes::new().add("/", get(current)) +} diff --git a/loco/hello-world/src/controllers/mod.rs b/loco/hello-world/src/controllers/mod.rs new file mode 100644 index 00000000..9b86bcf6 --- /dev/null +++ b/loco/hello-world/src/controllers/mod.rs @@ -0,0 +1 @@ +pub mod home; diff --git a/loco/hello-world/src/lib.rs b/loco/hello-world/src/lib.rs new file mode 100644 index 00000000..0827f2da --- /dev/null +++ b/loco/hello-world/src/lib.rs @@ -0,0 +1,3 @@ +pub mod app; +pub mod controllers; +pub mod views; diff --git a/loco/hello-world/src/views/home.rs b/loco/hello-world/src/views/home.rs new file mode 100644 index 00000000..83fd56e2 --- /dev/null +++ b/loco/hello-world/src/views/home.rs @@ -0,0 +1,16 @@ +use serde::{Deserialize, Serialize}; + +impl HomeResponse { + #[must_use] + pub fn new(app_name: &str) -> Self { + Self { + app_name: app_name.to_string(), + } + } +} + +#[derive(Debug, Deserialize, Serialize)] +#[allow(clippy::module_name_repetitions)] +pub struct HomeResponse { + pub app_name: String, +} diff --git a/loco/hello-world/src/views/mod.rs b/loco/hello-world/src/views/mod.rs new file mode 100644 index 00000000..9b86bcf6 --- /dev/null +++ b/loco/hello-world/src/views/mod.rs @@ -0,0 +1 @@ +pub mod home; diff --git a/loco/hello-world/tests/mod.rs b/loco/hello-world/tests/mod.rs new file mode 100644 index 00000000..c2e46cdd --- /dev/null +++ b/loco/hello-world/tests/mod.rs @@ -0,0 +1 @@ +mod requests; diff --git a/loco/hello-world/tests/requests/home.rs b/loco/hello-world/tests/requests/home.rs new file mode 100644 index 00000000..6a9246ad --- /dev/null +++ b/loco/hello-world/tests/requests/home.rs @@ -0,0 +1,28 @@ +use hello_world::app::App; +use insta::assert_debug_snapshot; +use loco_rs::testing; +use serial_test::serial; + +// TODO: see how to dedup / extract this to app-local test utils +// not to framework, because that would require a runtime dep on insta +macro_rules! configure_insta { + ($($expr:expr),*) => { + let mut settings = insta::Settings::clone_current(); + settings.set_prepend_module_to_snapshot(false); + settings.set_snapshot_suffix("home_request"); + let _guard = settings.bind_to_scope(); + }; +} + +#[tokio::test] +#[serial] +async fn can_get_home() { + configure_insta!(); + + testing::request::(|request, _ctx| async move { + let notes = request.get("/").await; + + assert_debug_snapshot!((notes.status_code(), notes.text())); + }) + .await; +} diff --git a/loco/hello-world/tests/requests/mod.rs b/loco/hello-world/tests/requests/mod.rs new file mode 100644 index 00000000..b016ba9e --- /dev/null +++ b/loco/hello-world/tests/requests/mod.rs @@ -0,0 +1 @@ +mod home; diff --git a/loco/hello-world/tests/requests/snapshots/can_get_home@home_request.snap b/loco/hello-world/tests/requests/snapshots/can_get_home@home_request.snap new file mode 100644 index 00000000..a686e3f4 --- /dev/null +++ b/loco/hello-world/tests/requests/snapshots/can_get_home@home_request.snap @@ -0,0 +1,8 @@ +--- +source: tests/requests/home.rs +expression: "(notes.status_code(), notes.text())" +--- +( + 200, + "{\"app_name\":\"loco\"}", +) From 60083ca74fcfc68ee0d5c08431177afa1ab06276 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 14 Feb 2024 09:47:04 +0100 Subject: [PATCH 136/239] chore: v0.39.0 --- actix-web/clerk/backend/Cargo.toml | 6 +++--- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 6 +++--- axum/postgres/Cargo.toml | 6 +++--- axum/qdrant/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/static-next-server/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- axum/with-state/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 8 ++++---- next/hello-world/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 6 +++--- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poem/postgres/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- thruster/postgres/Cargo.toml | 6 +++--- tide/hello-world/Cargo.toml | 4 ++-- tide/postgres/Cargo.toml | 6 +++--- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 45 files changed, 110 insertions(+), 110 deletions(-) diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml index ad055455..20502aeb 100644 --- a/actix-web/clerk/backend/Cargo.toml +++ b/actix-web/clerk/backend/Cargo.toml @@ -10,6 +10,6 @@ clerk-rs = "0.2.3" openssl-sys = { version = "0.9.9", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.38.0" -shuttle-runtime = "0.38.0" -shuttle-secrets = "0.38.0" +shuttle-actix-web = "0.39.0" +shuttle-runtime = "0.39.0" +shuttle-secrets = "0.39.0" diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index e278cd50..bfa9755f 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.6.0" actix-session = { version = "0.8.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-actix-web = "0.39.0" +shuttle-runtime = "0.39.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index f5ce9f57..2dc6b7ed 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-actix-web = "0.39.0" +shuttle-runtime = "0.39.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 3b4bc1da..81f48151 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-actix-web = "0.39.0" +shuttle-runtime = "0.39.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.38.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.39.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index f07b28d2..24c7e4bb 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-actix-web = "0.39.0" +shuttle-runtime = "0.39.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 7584fb5e..4248ca41 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-actix-web = "0.39.0" +shuttle-runtime = "0.39.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index c59c0d16..17c5df6d 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-axum = "0.39.0" +shuttle-runtime = "0.39.0" tokio = "1.28.2" tracing = "0.1.40" diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index ab9cf97f..fca3ddbd 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-axum = "0.39.0" +shuttle-runtime = "0.39.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index 307a3ba5..d83736d4 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.38.0" -shuttle-runtime = "0.38.0" -shuttle-metadata = "0.38.0" +shuttle-axum = "0.39.0" +shuttle-runtime = "0.39.0" +shuttle-metadata = "0.39.0" tokio = "1.28.2" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index ecb3d577..4b24e511 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.38.0" -shuttle-runtime = "0.38.0" -shuttle-shared-db = { version = "0.38.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.39.0" +shuttle-runtime = "0.39.0" +shuttle-shared-db = { version = "0.39.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index 800018c7..25ab93b7 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.7.0" -shuttle-axum = "0.38.0" -shuttle-qdrant = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-axum = "0.39.0" +shuttle-qdrant = "0.39.0" +shuttle-runtime = "0.39.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index bae240d3..bb0bf96e 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-axum = "0.39.0" +shuttle-runtime = "0.39.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 969d8f96..39824aaa 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-axum = "0.39.0" +shuttle-runtime = "0.39.0" tokio = "1.26.0" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index c4fff21d..5c1a30a1 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.38.0" -shuttle-runtime = "0.38.0" -shuttle-turso = "0.38.0" +shuttle-axum = "0.39.0" +shuttle-runtime = "0.39.0" +shuttle-turso = "0.39.0" libsql = "0.2.0" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 1333d97d..d6e430c3 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-axum = "0.39.0" +shuttle-runtime = "0.39.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index d12b7f28..52e30d7c 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-axum = "0.39.0" +shuttle-runtime = "0.39.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 810ec546..ad972835 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.38.0" -shuttle-axum = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-service = "0.39.0" +shuttle-axum = "0.39.0" +shuttle-runtime = "0.39.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 2ad16ec2..24ba9a0f 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.38.0" +shuttle-runtime = "0.39.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index a3f8e48e..31fdef41 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -10,7 +10,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-persist = "0.39.0" +shuttle-runtime = "0.39.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index cf6bbeef..bb9e4b52 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,10 +16,10 @@ lettre = "0.11.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.38.0" -shuttle-runtime = "0.38.0" -shuttle-secrets = "0.38.0" -shuttle-shared-db = { version = "0.38.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.39.0" +shuttle-runtime = "0.39.0" +shuttle-secrets = "0.39.0" +shuttle-shared-db = { version = "0.39.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.1", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index 4689e4cd..0ede439c 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.38.0" +shuttle-next = "0.39.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 73a59d30..61a383c4 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,7 +15,7 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = "0.38.0" -shuttle-runtime = "0.38.0" -shuttle-secrets = "0.38.0" +shuttle-axum = "0.39.0" +shuttle-runtime = "0.39.0" +shuttle-secrets = "0.39.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index c9e662fc..679647bc 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "2.0.0" -shuttle-poem = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-poem = "0.39.0" +shuttle-runtime = "0.39.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index d00a6725..b4ab6781 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "2.0.0" -shuttle-poem = "0.38.0" -shuttle-shared-db = { version = "0.38.0", features = ["mongodb"] } -shuttle-runtime = "0.38.0" +shuttle-poem = "0.39.0" +shuttle-shared-db = { version = "0.39.0", features = ["mongodb"] } +shuttle-runtime = "0.39.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 8bf9f4da..7da28f70 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "2.0.0" serde = "1.0.148" -shuttle-poem = "0.38.0" -shuttle-runtime = "0.38.0" -shuttle-shared-db = { version = "0.38.0", features = ["postgres", "sqlx"] } +shuttle-poem = "0.39.0" +shuttle-runtime = "0.39.0" +shuttle-shared-db = { version = "0.39.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index eb8543d6..7d421a40 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,9 +7,9 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.6.1" -shuttle-runtime = "0.38.0" -shuttle-secrets = "0.38.0" +shuttle-runtime = "0.39.0" +shuttle-secrets = "0.39.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity -shuttle-serenity = "0.38.0" +shuttle-serenity = "0.39.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index b7a69e94..edcc0e78 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-rocket = "0.39.0" +shuttle-runtime = "0.39.0" rocket_dyn_templates = { version = "0.1.0-rc.4", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 07e8e07d..95919e5b 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-rocket = "0.39.0" +shuttle-runtime = "0.39.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 40ef9b33..0180a501 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-rocket = "0.39.0" +shuttle-runtime = "0.39.0" tokio = "1.26.0" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index f06247b6..b43d6125 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.38.0" -shuttle-rocket = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-persist = "0.39.0" +shuttle-rocket = "0.39.0" +shuttle-runtime = "0.39.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 6163e3b5..96e9b3c6 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.38.0" -shuttle-runtime = "0.38.0" -shuttle-shared-db = { version = "0.38.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.39.0" +shuttle-runtime = "0.39.0" +shuttle-shared-db = { version = "0.39.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 9b61cb8f..723826d1 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.38.0" -shuttle-runtime = "0.38.0" -shuttle-secrets = "0.38.0" +shuttle-rocket = "0.39.0" +shuttle-runtime = "0.39.0" +shuttle-secrets = "0.39.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index a482e89b..b340ecba 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-rocket = "0.39.0" +shuttle-runtime = "0.39.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 458737e8..a9542d49 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" nanoid = "0.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.38.0" -shuttle-runtime = "0.38.0" -shuttle-shared-db = { version = "0.38.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.39.0" +shuttle-runtime = "0.39.0" +shuttle-shared-db = { version = "0.39.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 021ff731..d3803d9a 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-rocket = "0.39.0" +shuttle-runtime = "0.39.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index bcc9fa4d..c7ddd63b 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] salvo = "0.63.0" -shuttle-salvo = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-salvo = "0.39.0" +shuttle-runtime = "0.39.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 621a995e..2f909336 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.38.0" -shuttle-secrets = "0.38.0" -shuttle-serenity = "0.38.0" +shuttle-runtime = "0.39.0" +shuttle-secrets = "0.39.0" +shuttle-serenity = "0.39.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 28c3d45c..f04fb0d1 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.38.0" -shuttle-secrets = "0.38.0" -shuttle-serenity = "0.38.0" -shuttle-shared-db = { version = "0.38.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.39.0" +shuttle-secrets = "0.39.0" +shuttle-serenity = "0.39.0" +shuttle-shared-db = { version = "0.39.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index a6696f9c..49cba2a6 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-thruster = "0.39.0" +shuttle-runtime = "0.39.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 4c8e6da8..290d0d10 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.38.0", features = ["postgres", "sqlx"] } -shuttle-runtime = "0.38.0" -shuttle-thruster = "0.38.0" +shuttle-aws-rds = { version = "0.39.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.39.0" +shuttle-thruster = "0.39.0" sqlx = "0.7.1" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 69637f71..1753f8a5 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.38.0" -shuttle-runtime = "0.38.0" +shuttle-tide = "0.39.0" +shuttle-runtime = "0.39.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index 161f0244..4b01e3a3 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.38.0", features = ["postgres", "sqlx"] } -shuttle-runtime = "0.38.0" -shuttle-tide = "0.38.0" +shuttle-aws-rds = { version = "0.39.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.39.0" +shuttle-tide = "0.39.0" sqlx = "0.7.1" tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index f97a3c86..2380b913 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.38.0" -shuttle-tower = "0.38.0" +shuttle-runtime = "0.39.0" +shuttle-tower = "0.39.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 51c690b5..03143e72 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.38.0" +shuttle-actix-web = "0.39.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.38.0", default-features = false } +shuttle-runtime = { version = "0.39.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = "0.3.17" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 16092892..18ef66a5 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.38.0" -shuttle-warp = "0.38.0" +shuttle-runtime = "0.39.0" +shuttle-warp = "0.39.0" tokio = "1.26.0" warp = "0.3.3" From 893c5a453203838ff8fc94218cfb5ac1555d04e3 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Fri, 16 Feb 2024 18:11:41 +0100 Subject: [PATCH 137/239] feat: add Feb 2024 benchmark results, add salvo image rescaler (#143) --- README.md | 1 + _benchmarks/README.md | 335 +++++++++++++++++++++++ _benchmarks/axum-static-files.yml | 16 ++ _benchmarks/saas-template.yml | 14 + _benchmarks/salvo-image-rescaler.yml | 13 + axum/static-files/README.md | 2 +- axum/static-files/assets/index.html | 9 +- axum/static-files/assets/style.css | 13 + axum/static-files/src/main.rs | 11 +- rustfmt.toml | 2 - salvo/hello-world/Cargo.toml | 1 - salvo/image-rescaler/Cargo.toml | 11 + salvo/image-rescaler/README.md | 5 + salvo/image-rescaler/src/logo-square.png | Bin 0 -> 163928 bytes salvo/image-rescaler/src/main.rs | 26 ++ 15 files changed, 445 insertions(+), 14 deletions(-) create mode 100644 _benchmarks/README.md create mode 100644 _benchmarks/axum-static-files.yml create mode 100644 _benchmarks/saas-template.yml create mode 100644 _benchmarks/salvo-image-rescaler.yml create mode 100644 axum/static-files/assets/style.css delete mode 100644 rustfmt.toml create mode 100644 salvo/image-rescaler/Cargo.toml create mode 100644 salvo/image-rescaler/README.md create mode 100644 salvo/image-rescaler/src/logo-square.png create mode 100644 salvo/image-rescaler/src/main.rs diff --git a/README.md b/README.md index 73c09aba..d3176c1f 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ Rocket | [static-files](./rocket/static-files/) | Hello World page that serves s Rocket | [url-shortener](./rocket/url-shortener/) | URL shortener with Postgres storage | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/url-shortener` Rocket | [workspace](./rocket/workspace/) | A cargo workspace where one crate is a Shuttle service | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/workspace` Salvo | [hello-world](./salvo/hello-world/) | Hello World | `cargo shuttle init --template salvo` +Salvo | [image-rescaler](./salvo/image-rescaler/) | Hello World | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder salvo/image-rescaler` Serenity | [hello-world](./serenity/hello-world/) | Hello World Discord bot | `cargo shuttle init --template serenity` Thruster | [hello-world](./thruster/hello-world/) | Hello World | `cargo shuttle init --template thruster` Thruster | [postgres](./thruster/postgres/) | TODO app with a Postgres DB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder thruster/postgres` diff --git a/_benchmarks/README.md b/_benchmarks/README.md new file mode 100644 index 00000000..3feb5abd --- /dev/null +++ b/_benchmarks/README.md @@ -0,0 +1,335 @@ +# Shuttle example project benchmarks + +This folder and document contains the materials that were used to test the performance (such as request throughput) of various example apps at different CPU limits. + +## Overview + +The tests were chosen to represent 3 levels of CPU intensity: + +- Light: A file server with very small responses +- Medium: A fullstack app with medium large JSON responses from a database call +- Heavy: An image processing server + +## General info + +- Date: 2024-02-15 +- Server & Version: Shuttle production server with deployer v0.39.0 +- Client to server ping latency: 1 ms (same AWS region as Shuttle server) + +## Methodology + +For testing HTTP request throughput, [drill](https://github.com/fcsonline/drill) 0.8.2 was used. + +Each project was deployed, +the URL in the `drill` test file was updated with the deployment URL, +and the container CPU quota was adjusted ahead of each test with + +```bash +docker container update --cpu-quota=${N} shuttle_${project}_run +``` + +The value for `N` is 100000 for 100% CPU (1 whole core), so for a test with a 0.05 vCPU limit `N` was set to 5000, and so on. + +The tests were then run with: + +```bash +drill --quiet --stats --benchmark [FILE] +``` + +## Test 1: Small static file server + +This test used the [axum static file server](../axum/static-files/) to fetch 3 small web files. + +Test file: [axum-static-files.yml](./axum-static-files.yml) + +### Results + +| vCPU limit | req/s | req/s / vCPU | +|------------|----------|--------------| +| 0.05 | 274 | 5480 | +| 0.1 | 550 | 5500 | +| 0.25 | 1068 | 4272 | +| 0.5 | 1117 | 2234 | + +
    +Full results + +**vCPU Limit:** 0.05 + +```text +Time taken for tests 546.5 seconds +Total requests 150000 +Successful requests 150000 +Failed requests 0 +Requests per second 274.45 [#/sec] +Median time per request 45ms +Average time per request 58ms +Sample standard deviation 67ms +99.0'th percentile 299ms +99.5'th percentile 301ms +99.9'th percentile 498ms +``` + +**vCPU Limit:** 0.1 + +```text +Time taken for tests 272.8 seconds +Total requests 150000 +Successful requests 150000 +Failed requests 0 +Requests per second 549.92 [#/sec] +Median time per request 4ms +Average time per request 29ms +Sample standard deviation 37ms +99.0'th percentile 99ms +99.5'th percentile 99ms +99.9'th percentile 105ms +``` + +**vCPU Limit:** 0.25 + +```text +Time taken for tests 140.4 seconds +Total requests 150000 +Successful requests 145391 +Failed requests 4609 +Requests per second 1068.36 [#/sec] +Median time per request 5ms +Average time per request 14ms +Sample standard deviation 18ms +99.0'th percentile 52ms +99.5'th percentile 54ms +99.9'th percentile 61ms +``` + +**vCPU Limit:** 0.5 + +```text +Time taken for tests 134.2 seconds +Total requests 150000 +Successful requests 138972 +Failed requests 11028 +Requests per second 1117.46 [#/sec] +Median time per request 4ms +Average time per request 12ms +Sample standard deviation 18ms +99.0'th percentile 51ms +99.5'th percentile 53ms +99.9'th percentile 57ms +``` + +
    + +## Test 2: SaaS fullstack template database call with 500 users + +This test used the [SaaS fullstack template](../fullstack-templates/saas/) with a Shuttle shared Postgres database. + +Test file: [saas-template.yml](./saas-template.yml) + +To prepare for the test, the session validation middleware was disabled in the API router, +a user with the email `test@example.com` was signed up, +and 500 customers were inserted with this script: + +```sh +for i in {1..500}; do + curl 'http://[URL]/api/customers/create' \ + -H 'Content-Type: application/json' \ + -d '{"firstName":"Test","lastName":"User","email":"test@example.com","phone":"123456789","priority":1,"userEmail":"test@example.com"}' +done +``` + +The test then ran against the `/api/customers` endpoint for getting those 500 customers. + +### Results + +| vCPU limit | req/s | req/s / vCPU | +|------------|----------|--------------| +| 0.05 | 52 | 1040 | +| 0.1 | 99 | 990 | +| 0.25 | 263 | 1052 | +| 0.5 | 533 | 1066 | +| 1 | 775 | 775 | + +
    +Full results + +**vCPU Limit:** 0.05 + +```text +Time taken for tests 193.3 seconds +Total requests 10000 +Successful requests 10000 +Failed requests 0 +Requests per second 51.72 [#/sec] +Median time per request 301ms +Average time per request 308ms +Sample standard deviation 63ms +99.0'th percentile 401ms +99.5'th percentile 498ms +99.9'th percentile 500ms +``` + +**vCPU Limit:** 0.1 + +```text +Time taken for tests 101.1 seconds +Total requests 10000 +Successful requests 10000 +Failed requests 0 +Requests per second 98.91 [#/sec] +Median time per request 195ms +Average time per request 160ms +Sample standard deviation 51ms +99.0'th percentile 299ms +99.5'th percentile 299ms +99.9'th percentile 301ms +``` + +**vCPU Limit:** 0.25 + +```text +Time taken for tests 38.0 seconds +Total requests 10000 +Successful requests 10000 +Failed requests 0 +Requests per second 262.92 [#/sec] +Median time per request 78ms +Average time per request 57ms +Sample standard deviation 34ms +99.0'th percentile 99ms +99.5'th percentile 100ms +99.9'th percentile 104ms +``` + +**vCPU Limit:** 0.5 + +```text +Time taken for tests 18.8 seconds +Total requests 10000 +Successful requests 10000 +Failed requests 0 +Requests per second 533.31 [#/sec] +Median time per request 18ms +Average time per request 26ms +Sample standard deviation 17ms +99.0'th percentile 64ms +99.5'th percentile 66ms +99.9'th percentile 72ms +``` + +**vCPU Limit:** 1 + +```text +Time taken for tests 12.9 seconds +Total requests 10000 +Successful requests 10000 +Failed requests 0 +Requests per second 774.70 [#/sec] +Median time per request 16ms +Average time per request 17ms +Sample standard deviation 3ms +99.0'th percentile 25ms +99.5'th percentile 26ms +99.9'th percentile 35ms +``` + +
    + +## Test 3: Image processing + +This test used the [Salvo Image Rescaler](../salvo/image-rescaler/) to resize the Shuttle logo, a more CPU intensive task. + +Test file: [salvo-image-rescaler.yml](./salvo-image-rescaler.yml) + +### Results + +| vCPU limit | req/s | req/s / vCPU | +|------------|----------|--------------| +| 0.25 | 4.68 | 18.72 | +| 0.5 | 9.59 | 19.18 | +| 1 | 19.39 | 19.39 | +| 2 | 38.8 | 19.4 | +| 4 | 58.18 | 14.55 | + +
    +Full results + +**vCPU Limit:** 0.25 + +```text +Time taken for tests 427.0 seconds +Total requests 2000 +Successful requests 2000 +Failed requests 0 +Requests per second 4.68 [#/sec] +Median time per request 807ms +Average time per request 853ms +Sample standard deviation 380ms +99.0'th percentile 1810ms +99.5'th percentile 2007ms +99.9'th percentile 2310ms +``` + +**vCPU Limit:** 0.5 + +```text +Time taken for tests 208.6 seconds +Total requests 2000 +Successful requests 2000 +Failed requests 0 +Requests per second 9.59 [#/sec] +Median time per request 408ms +Average time per request 416ms +Sample standard deviation 172ms +99.0'th percentile 803ms +99.5'th percentile 893ms +99.9'th percentile 999ms +``` + +**vCPU Limit:** 1 + +```text +Time taken for tests 103.2 seconds +Total requests 2000 +Successful requests 2000 +Failed requests 0 +Requests per second 19.39 [#/sec] +Median time per request 208ms +Average time per request 206ms +Sample standard deviation 86ms +99.0'th percentile 393ms +99.5'th percentile 397ms +99.9'th percentile 412ms +``` + +**vCPU Limit:** 2 + +```text +Time taken for tests 51.5 seconds +Total requests 2000 +Successful requests 2000 +Failed requests 0 +Requests per second 38.80 [#/sec] +Median time per request 108ms +Average time per request 102ms +Sample standard deviation 42ms +99.0'th percentile 191ms +99.5'th percentile 197ms +99.9'th percentile 216ms +``` + +**vCPU Limit:** 4 + +```text +Time taken for tests 34.4 seconds +Total requests 2000 +Successful requests 2000 +Failed requests 0 +Requests per second 58.18 [#/sec] +Median time per request 75ms +Average time per request 68ms +Sample standard deviation 27ms +99.0'th percentile 132ms +99.5'th percentile 137ms +99.9'th percentile 145ms +``` diff --git a/_benchmarks/axum-static-files.yml b/_benchmarks/axum-static-files.yml new file mode 100644 index 00000000..5b5b997d --- /dev/null +++ b/_benchmarks/axum-static-files.yml @@ -0,0 +1,16 @@ +--- +base: 'http://localhost:8000' +concurrency: 16 +iterations: 50000 +rampup: 1 + +plan: + - name: Get HTML page + request: + url: / + - name: Get CSS file + request: + url: /style.css + - name: Get JS file + request: + url: /script.js diff --git a/_benchmarks/saas-template.yml b/_benchmarks/saas-template.yml new file mode 100644 index 00000000..88710cf9 --- /dev/null +++ b/_benchmarks/saas-template.yml @@ -0,0 +1,14 @@ +--- +base: 'http://localhost:8000' +concurrency: 16 +iterations: 10000 +rampup: 1 + +plan: + - name: Get customers + request: + url: /api/customers + method: POST + body: '{"email":"test@example.com"}' + headers: + content-type: application/json diff --git a/_benchmarks/salvo-image-rescaler.yml b/_benchmarks/salvo-image-rescaler.yml new file mode 100644 index 00000000..c8bf04a9 --- /dev/null +++ b/_benchmarks/salvo-image-rescaler.yml @@ -0,0 +1,13 @@ +--- +base: 'http://localhost:8000' +concurrency: 4 +iterations: 1000 +rampup: 1 + +plan: + - name: Get small image + request: + url: /200/200 + - name: Get large image + request: + url: /1000/1000 diff --git a/axum/static-files/README.md b/axum/static-files/README.md index dda9f655..a8659eee 100644 --- a/axum/static-files/README.md +++ b/axum/static-files/README.md @@ -1,5 +1,5 @@ # Serving Static Assets with Axum -This example shows how to serve static assets using [axum](https://github.com/tokio-rs/axum) and shuttle. +This example shows how to serve static assets using [axum](https://github.com/tokio-rs/axum) and Shuttle. This example is inspired by the static-file-server example from the axum repo, to see more ways to do this check out the [original](https://github.com/tokio-rs/axum/blob/main/examples/static-file-server/src/main.rs). diff --git a/axum/static-files/assets/index.html b/axum/static-files/assets/index.html index dce375e7..42f4d4e4 100644 --- a/axum/static-files/assets/index.html +++ b/axum/static-files/assets/index.html @@ -1,9 +1,14 @@ - Static Files + Axum static file server on Shuttle + + -

    This is an example of serving static files with axum and shuttle.

    +
    +

    Axum static file server on Shuttle

    +

    This is an example of serving static HTML, CSS, and JS files with Axum and running it with Shuttle.

    +
    diff --git a/axum/static-files/assets/style.css b/axum/static-files/assets/style.css new file mode 100644 index 00000000..13c6f985 --- /dev/null +++ b/axum/static-files/assets/style.css @@ -0,0 +1,13 @@ +body { + background-color: #334; + color: #ffc; + font-family: Arial, Helvetica, sans-serif; +} + +main { + text-align: center; +} + +a { + color: orange; +} diff --git a/axum/static-files/src/main.rs b/axum/static-files/src/main.rs index 46c1e790..2213bd4b 100644 --- a/axum/static-files/src/main.rs +++ b/axum/static-files/src/main.rs @@ -1,15 +1,10 @@ -use axum::{routing::get, Router}; +use axum::Router; use tower_http::services::ServeDir; -async fn hello_world() -> &'static str { - "Hello, world!" -} - #[shuttle_runtime::main] async fn main() -> shuttle_axum::ShuttleAxum { - let router = Router::new() - .route("/", get(hello_world)) - .nest_service("/assets", ServeDir::new("assets")); + // ServeDir falls back to serve index.html when requesting a directory + let router = Router::new().nest_service("/", ServeDir::new("assets")); Ok(router.into()) } diff --git a/rustfmt.toml b/rustfmt.toml deleted file mode 100644 index 7e5ab516..00000000 --- a/rustfmt.toml +++ /dev/null @@ -1,2 +0,0 @@ -edition="2021" -reorder_imports = true diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index c7ddd63b..1f4320c0 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -8,4 +8,3 @@ salvo = "0.63.0" shuttle-salvo = "0.39.0" shuttle-runtime = "0.39.0" tokio = "1.26.0" - diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml new file mode 100644 index 00000000..37af783b --- /dev/null +++ b/salvo/image-rescaler/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "image-rescaler" +version = "0.1.0" +edition = "2021" + +[dependencies] +image = "0.24.8" +salvo = "0.63.0" +shuttle-salvo = "0.39.0" +shuttle-runtime = "0.39.0" +tokio = "1.26.0" diff --git a/salvo/image-rescaler/README.md b/salvo/image-rescaler/README.md new file mode 100644 index 00000000..25270691 --- /dev/null +++ b/salvo/image-rescaler/README.md @@ -0,0 +1,5 @@ +# Image rescaler + +This is a simple example showing how to use path parameters in Salvo and the `image` crate to load and manipulate an image. + +Running the project and going to `/400/400` returns the Shuttle logo image but rescaled to 400 x 400 pixels. diff --git a/salvo/image-rescaler/src/logo-square.png b/salvo/image-rescaler/src/logo-square.png new file mode 100644 index 0000000000000000000000000000000000000000..e19cd12db7b5c1c68781f298cec0a45faa50dd4f GIT binary patch literal 163928 zcmeFYdpOho8$V7bl}buETak2dNDet|OF2}Mq>`MfCCMo*huJ~rA-}{m79{#bGFAMa@tiU zSAJRJZE0^QA(4-kUb?zgVpYVZ3#Mfm-oYZQ6=FzcJ#1?+HEh@t~zWD z#lL?F3{~cI4c2NF>ECw3DL~gw4^214MCz#*YOlVyBR<8p1~#3u?)8 z8NPYtlm7Wyybs^-`%2>IQK{co_p~Hc|J*zFzk4?SyW09g^7mig%l><{Yt7w1|8Vnv zSL^@xCQARi`tR-jU9tbx?!Q3!4`hG%=08UHk3RqC$A4P!pU(cV7yp@x|M{l>Q1Krs z{zJuYiTE$C_#YPj%gO#tr~cE5|Fq)Y>cxMk_zx9-vWfp+wPL(x%|9O-IE9W7r!8V5 z1XT5w49{DtXw12h#Th>H4rqBYg3e%bG*iGNdg2J;_EIm(KbI-f193$@M3OVY1BQCX z5x1u8_R~t8Uk5HCQEdJ*ujULz*!(X;@b=f;zV zjXRmXWgZY;__%I;0*7~*bO1WyOemfoU&%7a;pbt?J8Q8 z8wXxgbR~HCN1kM?*5ov8<(V6z9S^PE|Hu+2=?C9(t2WUz`n=kf^Q9 zdt|<{IJL@rfs@5@r2}h;W{^UvsOMxr4x8EUDGg#9+o%QEPz!eS9KMm_-I1NPN3WQ> z5SC)b@6F|WQ%k@`Bm^6Zmh$8Bd9t%%*G+M zlgZ?%u6~V8#1qt#3+!r)Yy#vF^X>`Rpvgv>0TH60DLmkL`Vd4IB6*C8o+%c!+z+C3 zq3F?4T;^zRDI))S??mqctDr(x;1LkFz{k0vr6nZ7^j4Yuvs$Ioio^&}DL57lXnE7A z3u|V-`|cm{-ge7l2b$h(ZKp%Xuc(mJtf z;cjZV8VBgYEKJc|!Qy)*A5XS+xMB^Ui^WlY025Db>Iq#iMV^hl^l6m9ue12nSrY>b z`VO0=8!jORlUi~KKGO%A=*;0e;U!Q|`|*`gF&lutmaN*E=tYhY9RbJ6c#iU!1@*Ha z9FP_eRY#+0-tkZAV&s37@gN;(_e?m73m!M40>1}R^SzJG=IRkfCK;E4O)(HK0A4+n zUZw2__a}2GV;s85XQELbqskVBMdW&^4TSl*T{_!o8f~GD>U+AN{FYv#jsCQs?J{6H zF-vF!$XnOH$wP|=JleXT3;LlWtk0!(qpMdSNLcfG`9{&M7R!f0s4&ItUBXTZwBK}` zJ>>HRHf34nXK&oVnlJe35TtkCIQK3nbymC9=a9vz%j?9b<^?1iU&N)c%0yM5>|`+1 zRC7#ard?(v;6!I-owj6$%NE^hJrSP^z zoU|0@yd%jy^VR(he+lkq<@*W8jEvZ`D!kR$@J+g2g8|f@ZFswn!r~0~-Vmg=mnTW4 z4*($KWn{lbenRwxxo`ui_i1V@C~Wa?O=S7uqt%zLxXs;Oa`D(dB=X=C2MD)9`HRS9 zyBA%O5<|H46DuQ>sPXn^FXf_}IXRz%e)KZ;a5v!b>He3D!`XvW7Gf!=kz5dCNOV?l zq6hivzEdNM8t6MuZK)2{wFPMv5;dD3z9P|r<279<>Wm8pvyb5xW~F`bho|29iPbck zm~P}Bkyz~zn9O@i1?79BA;DWtk54eBVvGRTh$picL?E;1 z6+eGcSe2*&%k{0wVMNIn#uNPG)r1f<)E$ySDzIiXZ6C$U z_!PRj0dli^4&y#$auw*%a)1y<@qJfIBoE{|Ok~xQ?p|HV5$CFZGd=ZT5RoGj@m$UR zs-cc`idHG7a~AfXO56U(YkKt{^g%_#qLRTa2l&bYYR3rLQ{>f`l_a@ z<#X>_@j~M}MNE0Hid`{)&eM%TI|&ucmBzR`R_M%i`!C`UKNJ+q0IK&HRDs5VXlkwm zw+hkZSe4#l*>Z4wm^+ZfM@@DO5s>Aa0xF$J@V#~h%R5Pz&0v^Gq7ugLJeiL!IW4%! z^|@A|=dH$?iXT6Meoe+q3(xm7&zo?EzjkphsRh@w@(oe%=*;b-$V?t$3q!F@SOlA= zea3M!(nle<6IXOQQW9Xfq$?=XWFz|_3^aOW*5bCl6&Fc)es9alF3$mejPRFXjT{=d zP}^w`Vl-cV6ZY}j6jFdlK8+5(ZmyFFddI&5VV75h#};)j`qe>Q=~(n-Z$O;lwD2Rs z-tIZ?lUt{8S(8Hn5FIw?hS(FoV_fwWyHT5#UGS z24?V7DFEZyYD;|wWFBj6%lXyVD z%U*ILRNH|kXeTEZ_9HFArP-oMo$;J+A-b-hRQ66Dy0m@&lq`&)kMkgYRuzdy^pD?e z1N3T9Fk?SRLx@nB1;#d(9_LLLDw}8T`7nHWIcDA~XU%f}0q)E$V8YfQQ6q02=;b54 zXZQvqdIVfx*96}L&1;Q5)Ve}0wZh*`Rq^H&*3yw>VTQK_IL52msSGHNA!rB1Rp8-- zO$9GLeda)6=PIOnDs(GB8J&c~&2H^w$r}7i8>?++-fj69Wo_@v z`(V`>t?+lYDHcTir5jNeZwYa9B8Y}O$=krROF=(d2=8kz_`1}4-klrpwkD8VzTsQ$ zqxql?ODg)#_5|J`PmY{`Plp-R2?VB+*o+~%Z`WgKBRx*a-a&@jPB36ONvS4h-=SHd z+E{o%r&g<-R0(m#XjZse|UaswjBcVvZdxaA{m0=AomfZ->syF{m1xWpP5e2dUNHQ z>=JVwK4!A=2N7GYnZM)g!3a;zAo6Q1J{o>QfjaAWcM!-59KZ@&%cS}yH&+IRYD;5R ziSwz!I2qAkbsVIX=cKp7&{ZWX1bo81UPV&N2d~<_TauP zmHvkAH4SYhtx8Jl|5S!Q$K_ZX%@7MB;Z*8fBB!ub&u*N4WYlXK6D=#yN~VA6sSYf4 z-dbNWtjNWK2CJqm#Eb^XQ1U-(8TETDU5nr;%Rim*1v9~ICBf2ZzV~8fGodPN?q+&F zt4}y}(TEj~hfI4wo$R!L4P`xE?5e=B(xKpXQ$2&~GnaV8maZQD9&H@ZQ~PY^+BLxI z=+ZG00O$GwFLtb(PFq;2QY&Nld+Tb1^NzHM;y&{N-_fUZOYmX0rthfA?|8LfE&6^B zm4A$y6<L21%%8oKa*Ng~Fj zjDBPGmXI%C;ED-mdk5?MM{fhQ@(F@=XcOYhNzcoOw=5uj{8DPLqQ41m*>Dr+8Wg8Y zrS9#;(A7Qfoh7ebgH*=>;DcvuDY+J=RBU*XZ>#6U9Vdk42_n8|A$@VhOH5vSF!nu? zQ;YFhwCf8w+_|Ch$x2o>H1pg0C06?h@kBdM9O8??J*M4PG-jZlnl6)}S&ctO6?Wgn zC4Nr9nlm4IVDKDeo3t}_&*)0Yn3K7p^2;{+JSm6O-jQ=~uh3@)w94(G*pr{zp%`@W zxIYGTP>n>Kt(2b}Xww1IVDiI62UWvGDJ}7pkmOsQ=xeiQ?9D5gp7n3aatXLz#?DEG zpwBl=Ms|g&Dd=C}_q?c?Q-jbYS3A581Y=AuRB6|EaM)u8&&TE9+FGD~XzSQFj`!<@ z!jgQRG0>fUc+>!&P?i{}XZJo=e|AAMNy2EVkYsyu$x;Rjo*IjL|^GJF3T_n&Ao+eE2dS zw&}==2!7m(7v$~w8n&VQ^`n`odiPH?IR#?f4dMMSOxeTCI%6y%NFTpQ-ED z?BN&#^q~FK+_5ftG*^17pkXyfV?2HlvJKZm$mcPyt9AmMPpjZv&*eDq&R|ah6QTjS z^4nIt3-fmoEYculxdG$f$Mrc`j42;dbF}kwqK0;Li&#)Qy9iw`)$3}x2abF*V@s=3 z(Mx4|i;B^Ja&w|1Bgk`}o{QF}RId@dg)tPqwhu?VNch0qKAG;|PKy6jK`%i+7hjrH z^(f_>=O~vzatVod_BsHHW=HuC;v>j=+XGQp^X;N00faX43@XJi!C)L>AscZXTeKp2 zy!rwEGx&24c`@{eW%(6;No$UaG{+py-5(=kq}$bo-0pJ-2C5!Vh9j%}a@(#V1Bz-& zstz{;ABN0qr!T;2R(#oNpa9~tpUpRA)Gxd_of`yJz^Rg0d>;j*>vxoW%UE?VR!`Zo zh7xgOzt=3>ttL@_5_RSsX5MSG@+&%8va)C>cQ+*!ltXr!RiD+y+gDaR&F&p>);%Qin-?EqVYWAo@#dYHQ@an`6p6McMuAdv zXcri$I9g>nI;;jAYTq@4k?`nh4Q;Ez`1|ngs&%5;hy<+YgirM88e2)8(6oGbD3X*OT8FangKpT1Vh7NtgD2go-6-^=BJ~ef58%-za8DEKGWBtq` zrsjB1d!S}d6oB*Keue#rE!dlGy^jCjF-&2>j1OAAvm(~a->2eGx2wf{=oP5r^=z64 z)fW|xs9h~7Za0HNQ8VlWntz>}81A3TxCE)Jm0Fxwo0xC4o@ z&6sDiP#<2!beDa2JL4@qa}EVqR4eS7zw6qFqxvGrr1-j}nQe2>8X+p@zIg6j%Ozd$ zoj95}si${urSHf6ODE_|@zhh0X*KGpmpKGxBU&Ixj9aha8+lRIT|qCdh+^fh!#?)_ zF(E{bx5aX*6!FfJF~t_N7ZK7(G0W(vOxr;u0VGWunbCx9J_6xV4SYNw4=M$zLBND+ zEy$%MP+43V+=g62^%^WSO$3EPKvWu3Ez=?NB-66uDYpU{(28fcPsRm5udE5A$X9_u z=Da~seJ=WEIgW*kQ&l4?V&vzek(lSsj}QkAXqFTgq2@ zb;_q+A*x*!>}k63b`+V=bE8ac7&mbG3@JF2^j#(GyB=x7t6(M6=`q_;-_@NveWe*4 zJPiO8E%ri9yC>xEah#|~PA^!M4k0rudE=!dMz{onXM*w9^KnCZG|8?k`0sk`J!Y{+ zN<{GK6x**KO5-BjXBU7TmD)4z>TT|Nyj;|ip7>9(*c#HCt_ckMLtsa_U*Qj2x-O>! zwh@k{#1*;0MvuFpeFGb4*Y1y*&^{TH3|-tYqH6Oem$*1Ta@%$e=ZY^bU}0KJ%BuS{--Bb|&C137 zSMFq!co-Kn=JTLd2k%f)9qVubFg5&Huoo*{SK|czpgoTVe@kuTYN9X;Zb@{YLk#`d ze1XN*+$RgDZep`orNUQW%51ktF{4mRMe)`5L$+WDG9@)y>DuH2p~5#I3;AC+&Ix=a zCGM5({^e4rb}Q9AV)cqu2GkJCD$gVWz@tBqrLRKXc9ed~oOpxY>~j|Ws!wMReo)A0 zqaoqJp!@-dc~2Rlsw5{LjxEZ`*LDDV*L#~VH<&bPB{{F@R(yemzav2lkh+#A(^7q2 zCXSgu10Age@ib*VqqXcn;>F}w1!8)x(ZyW5S{^aiXIoX0y!(76zra2oBf=^XfJAhS zLy$;VlsuM5So=?T?YE_(n%i0|PbFC}Wesd;i~=%L38#A%XO)B9ANt8>I;lYDpN$7* z3w>{CcQuv1o$rF`nNrZ-=3LOc^dVnyC<-OLNJ?jvMsHvnV}?BSG%G)bzH%$Ua6%#w zL@hN!Jztimf_r=B0I|NZ{M5zzNstZ`o$*(?AXml3i9Ft%O zKWT}Qo+_r;aKg*)tRx>{GQVn*b2#=2Aw<&k(n`1+Ce-p6J6~Zm+aWUDMvte*o?XIB z<`8fdjDj_SrH^6?X>^j#N~j)Kx&vM?{Duf%j-|Vmx_8C#-curSVC#U5h9Qc+omhR- zb}ipgXS_moyB!V>Yj2m{#s=}=c{Q(KSC6+hYP6z}gsv%iQCN7L!2b2Zs>gR*)0s}K zgGp4Ppjyxp+BJ(*gM}=GbuD__S{54cy!%S$cLyt{F*{JRZvXf~t6#>T`ba;JxI9f* zY|aP+kpr+TIY&xWiFOzsIN(#Uoi^bm&qVNOS6 zd$}FQl{qO1@2lVwsjt-njA~kuL^)Oj6 zbmYq!^~hciOwP4^kmH)*?IMo}$aj=^EAdZc!JP|PD{wvk04fR;5XOB6v zSa@N?)IR8FS%QZHF>~(j^3Gp8GK~t^zaaaaFc1Cp zc!*Q2SI(sV=|jyWhtzW*Yzur_^&@Tvny5KIq{lVEPG@B7p@@;2$9=xQ-}X?tFKPI` zJETTP4aEK|HJI&4VfLx*ALr8gsO6`1@ns&nrYw3`@9=G6dftG>-IGqE=`m1~P;>hT zUis8vUfQP(b7JP$wa04Ti11WB`89raWIC}4YcOk+QcXw5)@Caa`1>YJTFO4F`4)eDKbJQ|6FIWxmSOqdZQjPVzB@Z=>z7Tp1=f?AQR|l6)oAx2!S~*l6 z0)ep%(0vcOZjN0hW^C0{Q6}pxLB4{?V+Rq25cJ6ib|G;D5W#=C zk_s7(ca9KV1={lzv6HYG5^sU71eB)lA7+WG_k_P?X3-2FRkOWKW|IS2=s@q-(*2V( zq)1_^KyEQ+k^y?vyNX$mZKT4Rd98oaqw!T3aCtH)yn9TRB5ZEB-99H=r?W&$>o$%MDs8w-)ld8ES7I+ zlR>TwT4XtyfqphxG2n?vJ_bf5@=l>y75TAhK@jOe$CC8wG&Ia})(6>KfCPsZ#i?C{ z>>Osfz3a#Uj({77Npdxq@al%;>OrK-yc!(33)?lRPc^6JpJ6axltqkh`_yGjaNCBP zW%Qvr7ZW&dJ?ERUBQ(u6x2>McM>LvsSbPtbDGv_F zl45#gvgT(&e2R<#fEb3H;juj)B43&MQ}k{|R$C#;%MT6f?g^yx*k>!&?-uk3*TBW^ z7~y`QY@%~0(Cs|4PRoy{o{Zkr4v83o4-juJt zjjD~^(E6lvHS15={gFe;I-L$X-A zt6ftS;+ctBDxaneJmu1R-(Dg*oZJm=i5!G@3KmvFrp%H{)v_^{Ei&351EeJj&*Ijx zd8gi#-7xb-l$x)M060sG-XlPg?LhR&)Q1QJ=4E^hruP$pY`sH|4vX@qcKWJkpSoQb zRXckpLKqmi68N>HcE4m)+y!ssL@YKqvtH5*X5eSlhUX0%pYq3l+}y`K=|2O$;l_PGJC8|J~0U;V9oFU^v0_W{tkSH85ofh zv1DCA=c^2Zn94vv+zDCp!D#a%Jq3f%N*k<1To7^UPC%KAB}um1sn=c>NQEFlnAEAr z!Vd7=M>LDC79oent%6;8;AjG|R3`UnnTNx3Y9jS{uGXS6m-3NOGHODMHhC^luq*X_ z@#)mh#ryi+y;BIASRQ(@KR#ZETmZ}qC&&M+xB#&e>mS|^KPpy}l#{$OdSfs95wp)+ zV+5(eIe2f+6y+9$&ZaQU;q-PCAam~e^~TI3zeg9~2b2I_AxGuH7alrqc|wo!)~WNo z|1J6YiP6?ojC;HG$KZUiOz<`209y!D4w6SkWVhz$RrFZJ)hW-iF!VP zxM+5x76Wzsc7eMwi^v&bW_RT8-j9bXFFC)nwaIYBKJ!Q=hfCIpOl|5-HfNhSLJmVi;tx{7XCzhtSY^^L8U{se_x6Bu43j3 z_Wj_A8yAqq`Za1(>{u(mueUiHHxX-|KTTw9e)u43RaTP1i-Eo)#EF(FcB_9Y=4OP# ziIC_ia;3fdzGV2B;JglW+4Cz4!tK8IqSuD|`CR?}Q}5}rX=`k|j?CqsTa)$Z>t&AP z{7Z*e(@Wznbj3t04J>c{XXPn++a~_qg-446EHlnhl*RHyP*iLVw86i*J29bXjg?Vi z(CF=C>i{8iU!mi7o0C5kMVk{t@RkK0Xw%Z&f~C6&EjACRM?XSBZm8LV3hGzvIl1gkDKx_r?LU&Vj|g6Z~1Z7EjLX`F2p~KLNB7Ma=CR?*0m< zf4(7d%G8O=Jd6cXr<--c-=Z%3fL~$hn3g1)-JYvsnhf-CBxK(ZTFh(S!ESx*@nWJ7 z^v$t*7s524uQ0swJsv%D-@8J)F{p<7YN37Xl`UYcTa9J6q4ZpExuEsn1G6;VN%agj zkBekX88K1TOOze5>a+hKJ!Hyw-5|rIignxKzRJ$ymxv#_Rz=dfH=L>aqBh&HI3NSO zHQTtC;Y+bpG^%<0d)$Cce~&xh1WcTbzQUN5J&7}3^E9I>?agMyty3olwjo-^cUKJ_ zT|D;IW7%v2H>PFFfXBemcgj&W4(1P%uA!fAnIkm5m>UG`%x$WZxu&3LGVh~vdcDDs zgzshdBp6TpHNyfPjCB7tOG)Ubj?%l;1 z+-dwL*g^6q-b?=*Fe4A0UeKwCD{oBKpIPc_)K6<01k4os+Rd$PIUN%a5|^m^VZ-G2 z)D+~`C>YoScGZfd8D6*la;4qT@+2=8|LxRlnsLZ=;Z1qeX;bOs;QlQGSq`a!7-?mh zM~-)mb*(-xIe#jD3_p4Te*Svc&ZUa=BRB&IYnj;E*PG5hmFq{Yt1ON=a_NV}%$(Eq z56JS5sf?cQ@ErrRHPQR>VhtB=%06&TzP2gFnG&e8>GuX4tJ2%^<4*{!5U6Ey6UQ#4 zX8rSm9l(HHt}bEY^m94lL!EDm@gdJuh?`DqAsKia>v9%rPGqO0>KI4k*w6Y$R2j~l zM#}S5T|i3#DfQmMWcVm7(kAqI!40YXj6E>NrFEaLP2A8`)@a4^Cv-l?Uat^trS7WW zOfR;!djmh9%BMc`%eg#0)v(f?)uAeKV13V2h9Y?>ohHcD4`)NNjqg7cE0j4QdMtd zK4SE}pl%xozF6K+22PEamx;oLXwXvl?-oL457tSzcog)RrS@NymGpNzj^6=;xUoz~Lt)1`-AYpZu>VXQiW8BHFE9XZ_oYx?+FVCCvgTdgKotoV-bHEwYc=+w*4ZouYwEl0_ z+*P$gJm?6ns_<=K$sr?KrscFDEt7v3!kanh zUAGe3S4-Vrgp^sa3lCP5tADW^2sjpca#-QJS(mw0cG_j`K~KHm7}wO?_!HYR4ABbP zQl>B!Mstu2S3wTSgSWe-T0rmp>ZDTJqwqH;CG^~+l}_Cb{Q2mx3xG5tIosWml{Nmu z0Uf?A=yKJM=&j+7Yly1QbF_o~0C|ghJ3VJA(-_H9)K%0HK7GE5<@S()3|Q&O-tpMu zI6QR_H&FhEPUZfh(<)~V_R`7}K%4rw8t0LT`*P0EVBgK(Ej$aan-R+$MrnVreR%AesZp@?*KxI!ub&fXuT=nFjM2ukX7~-f^sES5e zT?+B@#B5W;YSXt>P9y4%wlP?SQEaUA`YK_WKvEzTs_|LswxrYzV|l%QX-eU*=n4y5 z@fE&guCSGpe<5tT1GnFhW8s7SE}vF#@RW*PZTwn`GzZCuvDJV=1s+@%WMO#<~WV({zA*_M;V`g+~|Dyd3-Vnlj_ z;Oz31^2n~G1oPisZlq4*FOA?GYvBYUx2Js?yiH}r^t5qGSc`0-JXu@AR@8{niXkYI zR2Xv=;!U6<7Ff3XP+A^VD?PCIbX^KeCv&i)&EN};aeTpK-ZFVXO-|^su(@UX8sk%w zJAzUU^Yk@Xn-lYPuJ7I2zyCv>PtdV@Cv<%f&I32jhnLLcH;z>&NN=rhFLt}8Q&rZk z5)rVQa)kI^Fo;RrW2&QaD9c)ElBRLUDycAMBB*q=2l55*o=cxw*;Xh6{u|=;LYu!( zfim1bPO(n+b&9Uy;A8{*#5DB0dM z`dT8$-s@3z6STDa_|Y-19@k7|5NIdRMDIY@vw1Bm9vwE;_q3>1vh=(bp1F{_)^?Hp z{r=^R`TY-nn!woQIu<+46SmAR3`yO#L;RV?)8l{7W4|6uykhX)qK|INh%r7JsrUBT z{pwv=Fjtmvzg(B*0Y^EfZUeewN8foh>1%SIc{{)+6NhX~r^3d0`=Z&64rd(4cf@)e zGuy%@gU4RtcDLFohnD+hEnrU6w8LbgE`Y)I(K~M7f-Gy5aAv&Zb`-`D%x>ASM;QAp*QR<-!*I)@LM+` zc~93={L#PlyFmsXWJzW40g;W+4OQXg(R;e7pby#N$S!{;`DlUyxorT~^}1?71=xnXJMb z8QBVz&Xp8aMb#}Hz78mp=JK7yWhnee-m=(0V;zcH1Sy;@%^xeFvPs$2VadEfuZzA{ zT*IQ+9y3!0xDS9H?ud#}fM!m<&SK!bk8KB>vzv8!xp-))T@xogCJ*dyBtFf@?J@HY zt+{A&zKC0KQ7hA2Ppg)}_*QWoxvg(`Fi+{_ts2Of>yzA)dF#URU?6ue=pb)MTK{p) zaQvoR_njW1uar+XC8kAvpJXM z=Aa+GwKbIMh>wPx53zHMe4?8lV64&e@Xmw5g@yalla| zJd3rn5YlETuX0g#234lkBbqQ4tO4Da@rVEzs+oXvqP@=}=`zuBxAKp@nwT|pk~udT z7O(?*3KT&^47wI@I@p#gsZfe(t29%*v7%UsX`!Xhm=JFWd&F)Uji>){B)9)|B-=GL zh)jR-?#pHB2q7&P&{kS1*S3!ppVioyU|iR(y~XjT>h$C?ISr3`UFCFz-mD?>{A0iZ*qODeeTEpTKODUJZw|&PXcCv}MPSpT zw?iEZ6s$+%vsBGC$u>5|n?;=4!?QF49o<$~HE$+`gfbFFRHwrMx?9G+9pCCTAa6GH zCbbmv$hspb`O!9D-qmmFrko>@sZU#6n;9K@2aX}ps{%i$LVo07C)~ny?;kjKm|VH} z>Mmleyv(jXnX(;7p3`|wtl$uI^JT!W=9kJqW`4~WKQs4z*NMCMii?gD7d({-%Ac;* zbm5IVY`{7CJN|6UrT=SVhU4kWcm2uYPg1Q0@0$e|>&tPlouLXTQ2Q4>8veEmv#|6s z?_pd{S8+_hUf-DPLjkW}$InCzUK6z${HT1l|2Z7W?0=9{pN;la85{^9XBsPBh=_(< zvN|MV2&l1Dc~tT(fo7TR9ChiAIX*8{oQA(oyc6o?BvHBTC|MPLGv-JO)U{*s1-;Y! zwS1m}`nfl@dJ1_{kk*yi-XLGzXb`8ie4d4iGHH98gr_w0T>94}{$H5afF{Gl4iU4- z7DW4RmS;vxM-(+Tz4$Iq>`iOEfApEhxstKHHlIS9E3br}8%S(Ca(<{f-Q?mI4mXa1 z%9)sq+DeqsEHaH>s#s+W9B?r)?+NRsxTM(nXKs;Rw+r20FzDd_FmgICJFvN?PFHeI znQwmW2ULeFzii!inVD7ro$7CK)AIPmMX`(HQZ6dSbR6_$2i(Xv3#R4hVP00}mQ93O z9t)uvgrV9emOX%ZxSjtmw2Mz%UpbsXUAla71VpIR@Q1nvmIlqvZ>+Ru`N~;Vwaa-r zM=6NSG!V{jZYR3}({Hp)TlSQuz06M6*>Jtr1F5rRqOd3J@{;UV(2 zH=K(fVl$2F50N{PUj#R1f3xewL~;YpCP+gH7trX5>5UUy`^AfU!cWe>{}Oj2o9y^v zSh9m*==m9)S9<504P{c`4Ia%1IF>}-FsXKFc}ipPO|;s+wLI^ix1%SX5`)z&KpMX@ z*Tv_5r+_k>SK>-t!;heO!|-l*#`#Yt?WSJME}ovp)iw?7R!W27efI-l@PGrbCDilx zdU}AYjl?|vg8@-nJRgKu>1EWSyq0T!Ff{8|tCwW8&rPct`MUxS9}{RpINeNLjJ2^< zio-+YV%={)Xx`@%nzqc`R>HhFsCFpr(DN|{YSd%x5@MMwt#-I&VC5unsGpxg)6((e za|6oUs{v!x{j2CCnsy3)+fZs$+UMMgTJ^}Bgg=&jwfbK+3oNHe1Rvwac)vdWb*`VX z6h+Nhe`EEBXNg(nR{D@VLAJ)!7ek+Y{mrpTp+8f6xX>)V#dQCy%G!NP^-be((~Z-Y z=Pt^Lcjj01&*glTN-CtNk+b6Vy(sj&c7inR0QmVP9L&-FX1@jIx$A7P``Rlhl3peo zMmKdn0W}~D?x!uOz3un$b37qj^cmDWA%Cdmj@G00`)NJ;^!`)|oPYmuN0p(%D*T2c z){Cy!5bhBcY8SU({_S;HmVZ|P0dG8)N^1gY#11PSUXmRAuzhdyhQpll99>DuY=NBD z2Cnzp>st$nJ6^k8BR89K6(^Hr)`U7=tOnIvCS6p4J-JJs$Lg1iQPTbFybvwZpqJ!# z{o}aDRe+Maw)&`;(Ht}ib5+s0Ep@=M-}Ok~T2FMtD*h(zy=7~Q{BQ3$q6nL{P;&CP za^L^KD?^NPOkavu{5ab`3hUbnR#CXc)|r z{eHs=ajz)H;71z6?Ey0KPL{TC`Yw3>WSp%vxh5zfH1@+={}=uFo(KI^ktK+ki*sKD zn#sx55m%be$kGGyuDs9aTR4<_VaviqAuUt(BgesY60+Vpixhjr5joHxI! zw&|Tj`QP6Xty~~+>Fke|O8NyfOoe{3cGbEhyOibmdPx>I!fY(|fd%~)1YGsA`Tw#HsgPq=@7y_)b-`Iv-=LXBt;O z#F4mW>K11!-AmKrIorKNen% zoOyTn$@9C566~L58yDX`;GWt!V?7Le>bv#xrr?_84<}g8hOjW}L}qqB!)0V~bAHTW zbM43crq%UTb^Ng>((4W%Gn?bT_s7G8@aIbB40im=1GNsI@=;iGr-Y7)rlwh|TmoUEt@VtVRy9iXn&Ir5 z(S#TIqlX?U8SPT1=v&`S);K{8wUIj+7jA6UYx2G-W*3&2t7WDR$9&YeO6nWWy8uka z`|H$ZSu0Gc*pS$g7Wk@$+r2LHOvj(IkZ%$R#ZwATvk8pA0RITD(Y&UsR-_v1x%K1U zSEGCS@9&8A(EhOy)vt4}VNn!#5bJ~| zKczt2Gohg=Ssl^4SE)}sj`H{%_vNL*EBB8F;A&!bw_ASI3c)GAS?ExhSoLp$Y5iA% zX?rRqg5&!nzqdGZkpl`f^V)ACiOFuuIJLEKeGO4E(D9^t$*mD>67{`CwyoiO%kIyY z^Xq+VwhEh?Pt~p~0;zu1xqq5|QEGko))ClhFK86W+$CyG*nz*CbVXDYTx8I*x2*BF z8C1dWeEM{at1S-Wz`Xo)cy{UR&Qk)@Q@G7I*X+W3Yo+=Ws5aY63y9*V{5SXdkH%9o z2cbES7Oq8Z8={O|G*t`-l%E)ih1sqeC^at5dwS~zP;@rmWc1)4m$2(EmvD`iK*#nH z5%clUcCS2_Lt+**)i#%IlybVYCB@8d;!4)OD^EGuyC0a8Go?0!6ku;+V#o9n!hRaW z0JDk>2I~!8JLr6gWJ~OCm+fbQfO8RdEFmpnM^TrSBF7uu@<5u8G}6A5GX;`#-(CJ` zcQnR4{aYiU@r!|xl%#|EU(ytdOm=A+uf;mMZa&yu%tn5zeO=@I3LZ$NO7BqFxqFSy zz4s^PLYFPD3JuG%BZUmv-tpCE4sHr>Eg%kt>09otn+R?H@uzMNQ247&mnCU9A4#4?4Y;D&`iR z!KQ--TQd_5m!}6>2SVgT2h9MC)tw~2U(X!x=M*dy_zyRY; zuE|)j@U8Et4YoY?@#?$OtTY36o8^_PFxIXut;6|XTa00b>bmcii=}&rtjV!04DV6x zwcoZx@4Dq<%Pl7wD;B?&4;laidgvLhI;b*2UG4Je8h?lb|KA*YO+@Rz?TPifcdisV z^p-ocxCYeg`Ju^>03LrJ{W$0Al-6asvz34rWtEei-<1^KxoO)wh2}H#aQUzO^pbv6 zsZFPL?5UC=mFr?mB7PqEn&_pWx(@0s(<=O?^d=x=zL?d+%tAaBX1>C9$adWiZUHQf#(Erka7rujh49C*G-+@Mlr_0vE^j&*EY2`K1Bm)9f;AxQXumH#R$4 zno;PX$k~CZq>HPIt`J$$F&^MnX>y{!!8>Z^wTrU-&Zm-gPSBw-;0ybxvh>%Ws*>QR zBEAlO;_|fPOsd~k`pBDuY1mr?#6wu+xUX)Q!i9nHt1%&Wz-nga|1dq}Z*Q>!CiZ3i z$}#$N{2X?ZZ)p0$eW%v?WhX!R(Tx0VV0ZU2P%_Tz46_SuR7G01OVPpbf*yAU5Aw8q%NYjsQ2Qx;v4yD zJyT(FwV%P`54%R%yZ!~%*8c;nk%R5U{zCJWu3jMMfRg!bBFoxV9ZVXdFX$y(sb=po z*j9FZj}`VN1p|3BV@kQJHP zq{!ZTWtGavc5E4C&tsDjnUNU|k;ppsc4TiS*$$3<>|-4V$GGQre|^8d?&ER)g!gB> z#&f;133xSso;L?W-3!n*-+FQ$gt0{7Kict+6CQEs5s2(rw}N>4A#(2!}V$2OheA)c_P9a_|PxLs$Clv0QKG?FBjtxoV8I8iDuwC(Sl}%3t!brAaHU2@}rs*%qHMdGeem>A@gdHe(u5o zHNavK1qpbN#!H6|({G>51w!8_;1$&d1e}GIqvPR;%F320Q?=eP$+^h+y7l%yjXFI4 z#^MjNfMwaJ*Rk-!F>n{~0@ScsPi8A#Bi+upcE)p8uAl1oeBrz{S6?{j-P=v-_hv`; z3w{*gjgqt0=vJWdVcQW&hXUs&?Olk$(3bFTJA5d%GO4(T z>zy0W3v1U-DSR2H7a*P0xA~>o%VO5JWFv)Z`tSpsC-@!4!&f**OC1MeQ0F!!7OL=LGLcjG#wwyr~3F>!+}v$jbv>{!*@ximTTWV zJ-2%Uk}*Qk4-t5L$%2~W#||h!)Iks}jaWp|F0-zu z#ieBcLvE#QYwqWNz?WP916;cekGCH+EXaonvXW9`BQyrjBVf4wv zoktg0I(-TGlJSCr8sKLx%9+lq*lPXEak%77rE7IfPRI;N76|dK&*3q?kcIJ)qaedZ>$@YQorr^FON;y%KO z#}(m1!`0HZlbWVvCY<9^3$oKd#~E?Y8p1me@n;YM9OGv$3@uFw~gz2mz+N8J$$0Z zM{x5xmRt}_=8ZVDvl)3(En65=MolVm8!{BX=X8FJZ=jOVk#^ck%$aA_k*N*h%OY)N zCHa1JES8$lLdy~@MiD{q?v3S^8yF0g}PC0FwA`{2XhMpFKx8EDV#D z#pyna@4leHKbzQJ$nqieGAA~bCFF9H6H2 zjl~>W17N2~aMbaEg1(|L+$UNCH z8eNsTg&)oYRS78K>*vT%=m7RV^QGJ0e;y75V-Im@KTSr2tT?`vA929EmE?h?t!Xwj z4=>sb>;X&_gaTXH8)SadMDP+W%q7p8Tr}6kwH=8$E*rB;JiEY%R^JI@4xal|QOw0e zD)~lTE3W4j-N5`?r*zcR*eIv|`6J?`N zyuarz;~IoUZst*krwq!^{L*yTGAfuPR>DcBdsbaQv|su)ra`*NiZw{A(PK}_3^20F zes@QexiVs9zvxK~Ey=`6H0UMoMNsW9=5b=k1Qko-f15koqR3xAVtO`qw}p%z_l1ieoN``&7>1}wb_awTsY}Ezp3|I|k9CNwoQd}=-K0k# z6;i81V7%U+CXnA26PkI<5|d2p=t&oHbzB=HHQ%?G`W_rNrdc^2mjI${)K!5%g-#co z1*s3QZ02Z|d)(Js7Z zmr17&XX*t+5~Mm%Q7@=AI_sR-)iU}0^nT`tI2NV+WkgGL;$>bx%PjZGnF)P(F%z?3 z84xrdBa75Gd4`SyFt-1eEx-sxRu^;w8}C<5H$0f23@o_`dj5XT@HP$21bc*2m|=v> zcM;-*eez-`)fEBTUPr9LJAl75j0y2nyNzvT-oXo3rO{nsIUDS^ZU6?2TYv77{qNzP zwo3dDTZk6mZucEH)~XPJ>NsGvNp~GBZqgNw-wm#(KzD}i8{{e(3RjdG(+<2!WnC!V zwWZeE8z&BuH1vv>wO93I!_wfCX{yet;pgj9vty`XJ}8iAju@BOHjAxAvSD^)bgb8{ zDujT|i5nSCLwhoXU~I~XWo~}uuBx*-W4lPsb?N>9kuoI6a3nCaSn13b>dvx;)mC5h zUPZ9WV!ef68>~YEFUx7Pe53Eo64eT$zk?VC`$z2AgiMofcvtEn(Sy&wC8pAvsf|*z z5R(M*%TfHd0=2sSeMmNN|8dB9GJ@sn8&tB-PVph<(a$5ku9>8jhOJo25FPeRam}b_ zZ`EzHlg383NZxoohsE*VF*avs_{O>26JtsiZFyQ|zq@X;z&ba7IK0Dojtkm6%FoXO zH;2!QouW83I5wQ`bHE*8Y6jzWHw8LqYLNDTntI zTUDqR3Hk;NZ>pr8VuJo;06{-3TdT;UA6i9*iwu`Jxo=ED57xPzaML?Lx5Y063a(l&I7 z)3PI>maS~-_YxMZ#gGlZv%efwaAa+#&JCpGdwlT0Jkkk(c~0cEk;+av-JwA1nvZ_2 zukSmN$CI595LlX8x2sYYVt6ACR%mIBp252mu}*OI%wZoq?m;(!@( z0qddVdz_Fx$y=y|#U$1udY40a=3@Cn=aaaG?kGNL|JE>d;Yw1!1b>9Tfb6C!QPVxE zQ{|01tXihc^iTUB{|k9N-W4uZlzejsHX>N0~QvZJX>Xe zGa(|!QjG_WydSKZtzIq@{mw$en{vxF+QYQ93KjdO;hl$}ld9sjmB(#H1{XyZ6+zrX}*Lw9r zap)M8dtn%H_$jhc6-`;hSs3;5)mAg8jO#S+jV7icM@&-~bIa*R!fnx=S$Uyt=I6Uq zAo={7@*Nh=YCt7oYOX&2pk~2})vPPerO_#`u-*^>!R!s7Las0e>Iji9px2OqJ5XaZ z<*^|Yf_Ka#(E7}vuJ7&;x`d!1kM@z*$40`A;vluxS#MfV33z_wv_vO#sF?}6rwsc) z=;WYwy1^8{ZxbJETC?|bmgk!kddocGMk zN2(r36uX|a{uvK^p?{ADZvPQ9U8Au}u@)j^BOpt!CV^55NLP+{*WyNqY~!#p^b%L0 zF3MK(%W`|z4BmVT%P)<`tI+?F7JujV?`QM(CupL$b{o1Ms&OgjXa}0y^`ZJ{%p~EW zrl%-kN6qQAI?fRXuGM0E)UsZiikE;85fKX%70+~0qgd?#n)qV~zn<2SN=;U7=h|$u zh6PQ~J(;+|iDh{rP*ZN<-l5`3uTWjV-s@{5a4(}qC=Ys?-P>B15Zb=x8e&n=%WeoNN%_DxR_-!OXX2F$_a4(r z04$Y&M?KDCwBNz2ek^H|z6!t&lX=3-@kwImc_$0L^~Na!qT9a)~J)jTZb@uT1dQS4=#Jg*r4rA(taj zIZk{r&C=8U1BW{%YWV>vBq+AH7ZI8|rbk|b`+#@mE(hn`-A>tBD^gb+&z6FDkBwFi zr6NkDCdO+r4W%ts(z>Mv;kCPO_?XyZ*}`CU56_Af0;82{N^@^V@jk0i8@9Jw^PHvt zqoywSR;&1%R0GtuU6bZm2Xg7eTwGJOu7+Ml!8!ozt6n(`DTv*qgi}}J_Q2K=&%xCc z{ZpujWYF`gKpMQOduMHQ-A(3`J*CRGTOLWr1g*oJM;V@}iGrq_e5y2@lgM`KV-4 z=3Bln=Dc_hWzsjBx}tlvoAMo6tk&tzrf6|YhHqgX-SD`4;a7a2^bj;g|3i%O58Xys z=0Z^~NQq9h6l?;Y?)u7Sik!cD%XYsjz)ES){MJ#k|2t=(%cncg;66pvB2mY?_lhV+ z@ydq~Lq{@DHmFcfaK5x&YNtO86%3(7Y~%Ugw9e)1kW`P<#mbAa z_YnZ~|BOU||IgP;=eKd*An$)tzfL>a>6U3eu|R+I#a;-VHgRsMMg@MMbCVIDk_qQ) zW*Vh~2DS{}I{dP3$Aocm0^1ASZL9xa;m43Nf_LTpEZnx>=WN`dFg1E#vLQu9r+P|%&AI%iGuOe0@h|HeZoCeYCp6cvg5o`ny7fPBEGR>ZA<$e z5d?%hOl;W{3vtHfI4T{TJ*(1wNNauYSx@YXOh%DSSVOnB7p8SkWPhj9Twkd7KISpv zRlGXHLsH!8pN1O!KPvMOKmY&knJ{YT0XAj{X3)OLwVd{ms|CPs{ex^>^2&MS9p~@T zyXlv~9=IAGWTqz-8!JS{ISxeLF0wVXvHw6{_&tXwx3rv>m0d8RDsX^X@R6jH=C~DAlu{dTBLUjnTxFZYp?Zc!K1- zmCGv5mMmonL+5>|%`f+lyZDt8E!R2gLeXAMEBWkPV!E<9>ocsmH_fPjL1k-ufjPb2t0o?zc`+RTyZYsB4gF;&Co$a?`Ud!Z0Q&!L^ zIe&Oc$>~7X%VFr{{qdY;TL5P#h_F#VCazYDp<{@=nATy8veoi8+op{EN)ED1x`Od@ zvokCZpva`HX6+Y<@LtdSEt1uudK%6PmG^8sxzp$Hu4EGCHF0F{`7m~GY|dukX%1>H zp#4GgGQyK@*yuMSEz_Fp4}5|<#58JtlhVMLr|riz4YVX>?mH-YC2wSQ4m)ORQEV@_ zu0M}P`B&>&^9uW?;gFSmQGsosN&oL4GejYQ8mJ3Z7I3mdl`Ee42aC;>`fKGxWFxP) zfJc`|urq9AiPtV=Ozk$Kt!=DaRR6B#_?@vQgBK~^x~(<3pByUU+$4NocQUVt~n1p($yC-GCr+$qK=DQA6&U!=qG6=Oer#7f2_z~LRq$wk>;73pZ zXhXBUPkRP{fc&1U40G$nC#}t}TLb1;>>S50WSn$$cB(A_o(x6y+Bw zTDZG$w_l8P2^}@a9|!8E;`5{^SGR%C{uN+%BHrFM*aM7qMwMX2hu&f&=V$WQ!E062 zt_6(kTKI`S=Z&JFn>#5;zJsrcL*!arBWiH_g?jJ%tPMQE^Nr9-rZi7Waq&F9OtTYy zf-0U9f1p7-W~wW}7+m^GJ@b<2s(Pg5x~ZXW+aF>~@pw|;&p&JN*FT%9?DBt=365S& zPz8bWyE++bhzPY4+*fwzpOeR=Bp||__P1G&$PQLO+dDcR&FVm zCzdlksL>%rIYH*zc3vP|Z0l8;Da-xVqgO~IkUOu>S$C=D0)2n&NOb{ zxckwm>4(x01QaZ(-t*lQNje-J!AUgF zgF}c;uAvupV&Ze58-tB?a8|Q$~E-e849MVWfhM4 z<~$bk8aCyp*1+bc2hrXz%2SkjDps=_w-2J&SWl<{r`Jl*wLe!C`~2KhXiqzFPVN>< zFnWs~ro*YmGB=&R9X3oqMm;G%pIF}#F+KSu!?3#rma0E$ zV?S^=j4=MN8aEPXY5u0gQPUb(;g=hW*K78V(EKm^#TlbJHi>N-t8osMMAY=Mq|eI? z)N{k)yXvIAG%!05HL2#MKU4oY4=Xp6iz4jn-%Dp6c3ytV<5o=W%tU^aIx2>=)9VJJ zpx*VEoDHSUYM7A@qBNMhU_>zN0eia02VXxu*ikmS{Eic+QwPikPG|dm;qJnDXe3EM zH6TW2-AEWX(f8!;T>P$2JnlCOsJfWHYNqm4-opYW{3)u;q$OhlgOSW-$u4;}3blq* z8c#id6SQW7T1(61mt`9$kNt25?)}|=6wwgpL&w*c_eFB>+z5F)%}E@HlVRWV51Fa( zcZH4sfI_TULXH>f<-U81B{;?VPE9SWzw0t_FJcs*|Inf(49tBZUeK6M7nD#9-dmkL zbum9ouF#?^$=R^Vn+o7@>+54%X%3dndzlh%0CTsI@?%ncm~*(tW&M?(Yh%R7lwi7s zClFD^XVl-UG$FGXyRiF3;4qhn1^6`W+$OFxibJwRAM7-Ym0QPMSCsENAD{BBSX|L) zPZf)NE0fP6R$!eC=Bre3Ko0Wst%$k~`!nLw2%ph$rOc2)4};+ArzI?@==oRvt`zVj zOr7~x8fVK7Mjkii__zNh(X{_sbf7p`aykUN)?I6%eiVraw?wCHQ42ZO=ZdsllVX7; z`%G(b9~^PID?2sM&nb%$Ponz^h@57(>lKvu;&gJ8M=M!bzt{GXMQi8^`_$1!f-}cY zSE-gsV(&URBla5QTI{7N@86O(Fi}}bu}{^p9{>g|>pV+$7Ts*vPfI>w9S`6Mp=tNz zIhwCm7%DHM!Ff8PsAu14!bQP3{~{l{oR~ITB>#Z=n^*1l&x|!{ZkN?;F9vn3*jGqpB=_g2S>K~iD&)Hpa{hm8M28)JF}m`C^jIcT_BinK0!KA% z^qh-y8FXaPCRWb*jU`S;&nHGRTP#FhI&3(%D9_x`bcZ4XijTOVOl@NESA7t!T}F7; z6F%DJ^Ulx=5GKaaTWUUg{Uo=n%IanmpP1eq+Ji}p$4|pgrr{M&VASxJ4G%1xctd94 zcuupWM+W`M4OK?MJ?dm9{=Tc%pveaL2znxTEuMl$5xv9oZ&|bIe7)LA|^bK zMO(JEUu#Y1`~8QGIFTcSK=|(k;#;kvSEf|frSQhfz;p%g;(ulgp})Rhf;FtAq9u2x zLBNlhY0Q}~l9YdM9|PI+I&Gwv8ca_KP_u72@}^oyZ#hl~GxzJO{$gI?o31q{PWfH}lv4~)ow)h--uVR1j2ZQE>}^O$fhVk76`b2yJk)z< zV7Gq=X0XV*!KCr{y=zP0cj?ad+UQ#_%G8iwIrps&KYSnQxyKu1nEBp5)n;8JzC*+m zq-&M~8u6UX;jy+GwW-;-ulD7bJuay|e!p|qS%HTc&X(Qh!q;tYywI7@3HHhrr=;qD z_T37+nE8iLd-2x?Os?VzyRJ)4!O@v(&{g?rzXJpl8V>ES%D$NWTE^EjGS(u*yD!u% z&QYb?ok+NCMu@z75VNZqMCx%$$LHKyj){#@Ai)pHTq$Xpq*>l?oecC*(~dr_ZPmQ` z^^~O>BE={Bv&yY{!z^)7M)A9Wp0~E^y8Uh>_pMX%NkrgN&lbEkn| zMzzo$=BA~Gi!;wVhIiz4GxzG~IB0L{E&O@GEO>t{2e=0d7L6QGh3id6gReu=iRuGl zByM&D7pBujHHVK@)By1X*+UL*siMs6Lc3pNvQX>9j@6mvidHBAzD}bkivayDL>i`y zpC}+TL1@%t)1^~8vdMZ*3FQ9BH9iVSK0MEr?9X|eoMrw_2CA#YhO9k!ukI9Ed`C&6 z1@C9mVmX}jO_@7SfR<<1wGbC}5SdWmF7YFomh1od;#6%?%57U_vGoFDCztLAmbd0zf7O<;TS3C2NUCx+|K5C zXzfn0+CtVpP57_zs@49^A8E==(h?R(p=1(`V+RNyXSP4fA9@X-2UACUw+ z0-dwnXE5g%j`wEhGDnrh_()xi892>e-1~eYp0?<`ATt>F@nG&)zsI5{3)GpK6uTMNv`L19Cy(ZH%Rl1KPbT1b zlC;6bUJy$1d~1NH3yq%7ua{qko=baXUxn)j|02T`y#AHuj3V04B_|d?5`m6jBz~Ws zn>UVKW+SOKW{a|b5l!LW$>U0*R4F{KLjN51>hI&KSM(pZe@;U9O-fP9%$bcUPKJJ( zdF5m00#QLJ(YcJ3Tjljsu@)1neIuXFL^;mxJe+GHYemV>o3yBUr?K2yjGU%|316d_d3dGT%VoVdia}ZYJh$4Yz5$ zs4eCCQm$^P2AGES>lwUmq&15hlr8XxQw}z)(_kfcC)1hboSJsO1?wa%n8fv_?rVW6 zBCFQwZnct1Pl@ng=6a!ql3PN{r?XA z_&e#v|z96OqjEjA=l!4$0Zk%{9N zM(poeC_l1-rI}GuqZ#5@57peM=e*o$t+qW?!E7Rzf2rpI8+;twVRzUv55M^8Xli!R<9`O?yWkYO66!;70aihsbItQ{gB3X=>AzgxJBxB}`SCXo%~c?>x5B=sKwQs# zAN#wEF85tp$j}a(-4gWU3vJ|?$?PtB9B67Y(^rUS+SXY$6L2sGa{q}(kbn4Bx3Yif z@*gQgFk?ZqkgsHq-Cg8-LQaYaUC!}tvAm~@>*5AEJJ2{N*#o%f zgE2+~VcUnP5}&{hFySZJf3Te* zq$xM5bN&sz4Ivma_Fo~jpJ;Z2fOw$&i0NLvl*xpqpK7JV+| z6-s34_6HL@N;C3c^%btV7Gyd55+BL8U_F@)3L4c}l{lS@a7suGsMXYZCNbBLfejnpiIP|Xb;TP)+_H6)E zC~1Rw;W9bz1H0ri7mKlV$7|EE-SqN6qnvc6!k=hhZ|_hlrxTddMHd9fM86!&s)~1o zzUHtBNz|9#+%t>ZI+~+wKRPYLIjKX&68b}C4r6~#%h(sN90svk?e-$+M#iUa$GBM8 zozJDR0$=5c%%U4gH`Lp2>i0bEMV-&^31h32M1@GY7zDz23_VvFD1ss7qw_d!ZAXV6 zm+55IoV;o`PON*_D^wMcysDMnyy1$6#!!pYX!TPo*^CQ49M2QcvZEZuccJt;s_ z4dLTWd1k{y0Gvlp!>;8k+q9M*2za>-qADt;+3^$2TEPZJmQ*q)cIbn^^?mXtN$WH- z@Ya+-)d1QB<6i;V5)v`$UzIb9M`TRP#Js+$b0dI}Y0aWTFz8*wn*=;jqINzrs2 zXHx;n$TGz#4{vpcdIYo=x; zdTGm0KRQ?M@`I(9e8U+k!9dPz1oP^%`1iv3IrgZ%5h#-s2}&eogbY7p?@mx1Qx789pARE=A-*Zqj7NNDGj4m6&~$W6 zV;A0D0Rs1LnyopBqN09qkAkWDPS-a=D>^)>LWQSSTA zhbOzIipV%_Bj;?Wbq>>CDkP^o}B8!2Dt!PUS8 zz%vn^bE#S0taCHxuUBK8ZbbVbXWQJ7`yj5zGUR=Ivp@Ur}Z-iWfFDusm zs7!Nl|9Y_fd{CLA>~F%+t(4z&8#M=BlP|vJ`oLSyMpSgEiaXbS(LaUeGPw86H?feR z+XC}ru^_%TSuB!<|1N8}c;qD3818@1_LF_?PMe%>tARZwIlc6{fg!0h-BG46HBS;T z)xOa4kZqQsRbj#qNELO(Wu6~gC|V@dkpH8uDaQ!YnGS@Jp%We_gtS% ziKXd}IP6eD9i!bnFZY20P?Ot|(mC|J;u#$H#ENcYu5qeQMBw9^6z3VXx#bKX+a=(r z>C4-7s#Xg~*fl?5CH}%35JdL@`X+M`&O<@)ysg(#zxjgpL*jPZla~}*koFsW`P#QW zXQ!u@aOJ)!7ku}jV~g`4g<9m*DKhiVko#92MaV7e9#f=QO|~`_eFz9)x`5>!r3zI{`=zc{u-8r#37p9bCQA{3cbYoQZA)qW(}jo=U?kkTR|(gY{9{; zs;JLMz868#@Gq$+k~<8&JE@2qaEJzc<7sG|-Dwqd3y`TCj+1?#?7U2~=)ttsW{bJr zCr`FY=}Q^@H#5l#@K#;9vWR0_j~@gpUJoX3rcq<4q)rR zF;;(h*Pd5u1>u_)06|IH*1Rtnex)b{Hvr3ap0vl`vNk)!p!iq+7ER#p)31DFtnBt z-|x+6|J6g{iWlwIjV(QMR!j7zu_Yoe++@7SgW=1Jo$fvLjq%fyQn>-{Pp4gN)2OTA z7t`&o?H7i@>Pi1d?MMFw&Z1euv7W_3t#>e=lyA-f-&I&B#V!P5a$hj24*gQZX;-;; zG|dw^ZtwM!sV9zN7-W}%&(L2b|GA|{$LLe>V?QUgu^;DB;;`P=$7_}52n)<`IwhSd zx-U6b-=;zSMe{dHTf5Kiw(s?G%~W$HMLu27C;=ay^4WZaXYzoO|`d{iP^e#F&t6~VU@&RA5ajVzzBshhosB=Nm&#`BoD5Sj~KB$1gvvYH#P zYW-d(eEUMmQg%;pp0k(jD)0*IQHs^_m$eucN+OLnOmF?FmO&!yFIP;EbSFa)y#9uh z$$HJ&MUnZlg;Qzi(UhyUc^V1ExwrcACy8Ui(Pi5g(gzSrtcVZW%&tn?dHnt?gNXl` zHO?sJk1nxpjp@^@HS;vVn6JS;1j7`?E`8A&alE9TEY69E3kOT^G&PX?w^ZK5XzX0R z7BvTSDqpwdh}^8<uau+up;LJbgdzhEj`E2zUIC$}O%T6q%^b}*<7lkWkCCD!= z0Bq{&d~yCr6-WZy0#s|$_g~_C_}#+Jr=;;+`_7Qw ziV#?3@P_8PFWPz2zL_e!d*JN~s~`U12K)QC%Ej1b3~wY;(||9NI!mvAGpX6&j*F{7 z?_15`qXvJ*xh!3_4<{q=!xDQ$_Qqf-i?yqthIO2YPnH7H#lw2(Z)i{+d5wU&@Q7`^=en6vyE0!iHuc2U<1CSwkshVtSY?7*ViNEW90T8 zE@CFd5Nqdj$vj!qma(J>k9}iFqPTB!vx+t$?edI+K0#6y$`{etY9%4s3q+v*RV|z` z{*NDX#Xej}aIW9Au1)FY7T@Pe&syud5{;>TbrVfDKSJFObOK z(JDq;+?K=a!_$!c>yZ2W8*fkjJi@RqNL+4WC+|?Hx}r)L*2}yI!f;39A&WzTAN}%4 zP?LTWb-aFYX#~f$Ya_&+^H+dQout*>IWB1UL{2BLo6F3Ah<=L*%U{Y ziXa-^=Y5asb4)}wpky?W+yc%0JwzBu$q{rY@XbxhFmhlYn(zs@oSnTmJ46bE^AeNv{sD`Rhcei>fA?-k$&ea!gG=ADMK(h z^UNh_$!&WnWj#*>i<_EUqV7aKE?w5DmMhFROKz^}RzvrG@);s+iPcPwp?z>Lc=Pb* zvu)4|z{IuZNY3R#oUQnE!~?7*e42j!eNZU1d3DoqB*x~6x1NMW$R61zzr03%*1ZE5qx$r5LE7M)5T*S%$erUvR``f zMM$0KXY@*X_Kwv7r?QOFTK3N-n@_IaSKT#*;BX1fs}XXzMdKMeFK6%uwYGiA@|k`Z zd#gNRzFgq5)cdnpQ@u}c{B~6Mf9kShd+9%g19Izsg<}cphS=hSTHFk*DWAsWzG1hh z)gGz=VvY+?jvq6dA|(*-?YKEdMZ)mi-40>r8~T*}%B`AP9sOa&*_~1#)=i7)^lv3l zx^mYkN{^3qX&VbGCE+#?x72(+kRu7%R;y3V%OMzix`J3)`sHKLyV|x zAwi4?1E-C>#{%FtrYc@+`m#39<^=5sIQ=QCM*8}C`SLDA0r9;1^Y0$77GwTatU-3E zyJO!brA`01wVYqCxFM6AGV7sKRGD)lxMr+RWJ4tN*#6772s*H6nwatz8_aKu_3c)1 zRECUXS@YAD689=sCgz8p(_}<0*)9OyU+F*Ebb8|6ZlV_L1gZ%e*jf+g=5g3d7Uf}1 z2V`+Twk6{W^X_J_#ilRryur_dmMDcHOs>Z~n^Xf%J3O$ImS3%TR2J(9qW-7f(c=Eg zW!%E18{}dQLj=po0180%@b5<~0>AcCOK0zYf6PuFPB{ZaM|wcD$2HII{!X;DnT}jb zibtf2wnW<0b83)1ppN{`*l_A2L$o}X%m8>g)_Mn}{6j5rQK4G?1^=D;``Z!?QY?j^ zgomOr^B%27L^EOkxeh93tmZ&s>9NXlG!1m@oG!MLvc1%btHA~{;w%o4w}pW#-mxXT zPIu_*w^hr10r4~5ge5daJ-_6(HHCJ{eDd4}sqt0w)Fh?q+USnkShQ_piUVdUz9`Q^ zxs0xK^b;S1?-NT~Fcy64V;t@wJ#jDW5t%r5z+n)c(@-ng+&^D6r8ylS+8!#F&quOp zFi#RB%uY=(I1^`>irNLE-?oWd1v5j~w>%-lu>A*_5s=*Q`jZC9-AeZi<(eDMmz8Bv z=qhHg0@Pj`Gpqa|nAfo)ed+`QC_|NfZE>-?q&Z!a3ok{{2NJb+TDFTb3&_KCJZly?J%YM7}j+g%higM2nmA!I>h=&m?WfqO+c zNn9^~LlYUXIU%K>hrnARfQzS9CF|;By>}bgt7!hBi#e%_8`QPzLCB-o-urXy*bm+B zr>8vy<3yCp71;?IM_{Gr!ikR#a=X| zq3a00)3BYG`eDP9O8*V+`YU;PsQ(x%?%Dx;_kT`-%hCCJo2K;B2Bi7<=&Pr{QTn4+ zu%nbU-cFOti3G%fz?4McIUg+h+YU{pd2ZnSDYWDP7h`;^}jQ>s|E zq?<3(+NSsHPw0MT7^6uhEW!6D;Z7%x(9d*<=`S_6h$MKN!jq1UMfj&O;PSKkrYg6~zluH1p@NUI-~_S2+MF>K*fh5P z0%?I1|MtMZb*#oJ#NQRR&y}t%{e5@N$@D%&AnADT^|Mf^I7AI&kZP}H)|=kfa+RiB zBF94D&8akHp(EngHFY_Gszvp?&DE{}1QcLikiC9Arfa^wzxC!&IiU0vXYILh89=?u zQ>Mu-=<|o#Baax5;5+I>3{w=>UTco7D3DHftxbn;W?l>?5yOAKii7O+6$G-ig4(^( z9vn$4$I5NTn;)e2z&vc^F<6D&uwlFJBhrLxh_2cXx0=mOa{|@Y?xK$DIQ@;QVU3mz zJ3n;l0ruvD!?yXfz%zO9iz$KdVNaaihHZw-^P(e@drSAs;6dXuGHdXk(vh=UEl)6f zm;zc_MTTmv`R5sir<0_Om$!R`uqjc2eFt)*W>h2?ZnA3Fk=(ZU+EW4$`U<4S@}_OR zJ^*GYMyC4nGSa$wq`%&GLlopaBJdVFV_@Tw|2$uv|2^MAY*Yl`)<+bPwHRkPo90`j7@u6mfThlfU7cguh5%x)a`qo>1ADn z-d5$4Sg321^iwaVJbN``P^8+US{;QQaczLfZ8FqQGHHcYqAXOgf*rR39OeI1K8X6E z;Anw^@qE%)m4xdvNDz*);(M~&QyPqSCaaPS6eP)hKBxTReFAi&Ir{-502>3m`z!LW z(;%@A; z$;i5G=xb<2wvs>q3%I+EDmR}{q&V%pV%XV?`f^h+s!h*h>?(OJq)8sVSC#kW2p9&w z9x1=nS(v^ZO9un1|B`{io1|uaA4x8bnx6*SIN%I#tDDHWZ6@=gG3{5bSVZ^(`#(c6 z`@ci-*-+ta=^PZIraK&pWAJocL{H%4R>8fCT$*Z z#=Y>8Z&}OR)T%Hf=80-{e^A4{blcP`bfSfNna1kwo}Cnd^Veo6m9fPmn!fP53~zYL zVSYsTZv3PcK+eNK*TE!IHav+aArA!mU_V`J*>l7;I1`^g>JD(JXs9`}C4Pni2eY69 zueT{9suDCY3eppMt)&4%No+n~;1e#Vdd_xi@S6kR5AYp&>QuLie_{ZRS$ z;YSjyQnQ{@N+t?hekC{! zL#7WV295|fO+1c9+t*rGKs$aav3JxgCS}sk*LobU%hI4dPplr+ADhRyLw#I5325F( zigWp=M^GIHwIx;;UpHLI?VwMuJ)L3v{|*$){|pq}hLka~Xf`S(^Hbwy(CK5{xtxcJ z(qA`a2%j_>uDGZrVt4pBHj54gvYh({2p4d5(1(DEv~}+^sJ8vR=kM=;^*8ym?e!d{ z1_D)*D+mTFn@2S2RW<@Uiu9XfE+a22hzVBaZ)TaJ5I?4j`pqbmiJqgrX~U9?>qLin z8&Nz992lnU2gXs1OW6Q!gDyYeVa*>CJhK^KyZP4sPpedwM&H4~g=A3i&_O1176ttP zyX6m6J%R+`v}KHNHtjF9N1Op{o6LN7oZ1V1%2n`qrd(ib3SWQROc(<_i?&E*?@LTV_PSk10(Cl?E6I zmR*=~&M(eoV^%HMHr(WLL->t1nTYn!07xkZoHQ*pI&cz1!$4Q7bk+ zBA!97QXud2InJ2m+0fBiN^H{1M)ORu#L03R^Fyo339@1y4WqcFy#=EDi<$`6;bbGV z@2v?AKO6yXe>_3n`2CE+c~vDhw8PgI;IdrWSp^wAetZ_$1k3W)?AQh58i=|N34gFpeG&Q@pYd;J`O0?R@vL+bYY`B96Ms2<6 z&j1ynOTy1-00}wzg5ELXq1A%7Z(e=gD)Kv3Yp+1B(6{x-E@nj_(@XcH;0FmTcen-Q zq-RsMQb!vVz^5{%sJ7|S(9*gO-Hd5BIP#~)_1RMq(*S?1}j<0MA85YXBEnMJvV zanr)bIpb@Ms~BT_@2u-~mYm$GLYu{LpjK@jS{-s+A0$8>1q?wpr2Z1A;RVC*zkEJx znB^I|_v=wjIa9A~Yp`rVLj@Fw3{WsiLMVLt-*aUDCxqUD9_u2&aA;xns5@iVy6j%nT0r_7W-#h@_x&Hi8nAe}=u(l8)BLrM%%Lk%78oafxP_j%Xi z!|-*l>wjH)?_Z(3D9>k#_8k;yUd%J6w7g@^7K(f2ySGP*nGk#x^+iYL&iy!W-Q%d0B6&-() zYvg{FwW~+EFdMK{{8n#8O+m!+jHB_>N)YAmsc}lyzWhf<(p5AVI}R&3miUXh#z=_J#wN`41<^)8~;D3{uA%Bf5{r3s<2mX$LID%?teqgj%iOz zH>n^$p4++#s?SiN!{(052=f4&7ZOG+Bu%RzEOpaxOBbBhQ!tDlV!e?c?H; z)w(ockGLslKm=IZJ*ZSp*M&y84fW;Z~RPXZUzU&Zfx1)>qs_01N=FL3oyL}z)-pX4BSkuJA~=p51e@BiX(W(t2tIWu20I~NV~Lp73?4>_83 z&s9j;52Or_y;!_Qe&#(K7FB+=Z0b`K?wO}7BaxYucTF~w>eX9Mq*=SMOG;u&3PEW) zfo@fUr8M|jBySu;9B5R=jz59RP9wfYOi`ux z4PV!nqdK;ZPZstG$uBV8bZXz1UQ0$?_+eegZc)B8ELp&E8Yk_mrQ6bo6Xl6MJOZ23 zwPM@~^m~bz^2xk{Ipq#CjbPlw@|}pRuoU7*mO)#3BA9yHvF&F_W$d+NRyDv&HgEu(d0P$h>Vpx|LQKqnFBOB zpvC&Jpnw-XTEs5PpMiNjM997tGnXfoctGN~fEt(>Z9%4j6lnpAUczP_5TVGk6^&+E zi!6;l{8wXk8Lv%wrxu@xPMC#U6iluYxs|wl9GqmB27*+lW=iC-N!24jzXYqOya1z* z5}g+Y<0;KPOc)x9*CS28P5u)6ncGd7?+tA;CEa*do8Ll%f|mA~eBMjf>j zEGCA`e=2Q#iSner$j`I6pRwTBuF=Vm$WBTRT>^BR_20;e?)1pUlwrgu*I_K*NDe}jG1Xw1CV}QGoNK zH1{V1V3=C8#vd&j%T(1YrMi^WZ7nX7?}jXCRr0sr}lQO`|jx z%#o%hpF^D6&j;;w{s_mhl@dJ;Ihhzee2Fx|ZM2iu00S_McZF%&EUK6L?|PK>Db$Ql zNiQh2fM-dK=0MGY{%3;{N|-CTCrTJk&O?|21^c`YY!^68+}vcK6qKFiIgJ-_3rHd0 zQhdodq-u&OBQuI|{Y3I-$7gznC{P^q3(^R_SIf36I6B>rlX%F{K6{%Ii}9PJ!b_i9H;;Qprf&PPuWOL_X0G$t&;_A`x=va!0k$$IM98i|>y zm&(}OKWvduNcVmHLA5# zSl%2#BcM?OK{fd<=~#BJrQv~-8*S8_6Y2;xS_mHaiL1lg<}3^p{KP}M<$JgMWYGZw zw?kwJWFacbkKBY(a{q9ccez;li5yBnoPxiGMMdJ$yd&K;+tRc5(iuT^i@A^_&+T5zVuIM zhnca?ixV`rk3;$K%4RII+S1Zs3s2hnQ8AuUD||SyE_9lEiMDdVlxIzP%l65d2JmZN z`u(R`M>W}=YA?3pUf|28AXHWEurr5Ky>ni~%Wr(JczBnU82-;#5=D;a?!FGNG{+Q= zh>c6NT%hPmAwfUVt*HZ6m-8s$Hj}t$G8{54g_R|FRSRDSI;S&ikrHWbVgTtKzRn2; zPWwk3j|c!D_kx{{qbCOx%bH6QHDA<;ci?%=Jph2`g1|AY{O&E>qiss%_f&BBj8bb{ zQvVs4+FlUq5bvQ@sW`sEN{SHs^^vHdThB)&XgEv&+Wch>IeXsjAK%Zl7uWn`%Vi8_ z-R1F@Dcul)Z>OaI2^Tg|S7yHClA+Ia9mIleE%(>fxs`kHHwz;?#Ur-etzT|}rF2$$+ zeE7b2z<;D{gZh81aZslA=EHZdubLy!U z$`nznZPrj%6(7|;n6;1dAE|GZUKBvag9T`gQDIcOWko+RK^kyns~IZ%W@EJ>fd zCX?iFOmXBl?WfHh?d4Ys1HHN;>;@l*5uQ)Jq45V*fY_L~vGn97uB*53y=r8KPHu&> z@Tr@YEcu`4xR2$dG_SlduIDj(L*_@;Cayae&?xEV+<9871$6n3Z|iwE?CdW7jQ!sR zu8RI|1IJ6Kx8dUqCpsQ~sWiQ>Iq6_zM%LfBXH>v?LQ@-&!w{($DHZ`!Sm-6+&0a|m zZ@fNzr)(uHN%=Aj2BCq=mILa)Kt2mQI}G;${W2O|W^fsXj5zf&1N_{i5~z2wnw>SP zT1#5a>sz`MsWNijf2L(!r^E3dk7Z>Kn0|iE#wEz=0sc(HjiK=gld^H|K<1s;4(_pJ z)4i)jC}7;a^kF%c-I|d*+;#Ld*m5aX)?2(jeaU@nGFoZ;cugGX&9{PAES}!9w5+(O zOjk;p7cn3>Ear3XGyOY4LV>a6iB8DApVfFih>3ncO1ISzNE6h#v8oHT1?2H+CMN*T z0YV*}+e=%>f|mda;zOpiBbf1}xzPtCa)^@x;ZYpbG6w}u3giY>`4HHXh88`9;;3t! zaFiljs_4tI@!}Qdlh9vt>b=6>%2LC6{?!;2F>a!r=qY!@iJkEpCzoA*%R10FvW>m1 zTp+gA*@1vk*oMvGU*%BQz*t??wmzmj2%LO%B@nTDoSJ%<0{zjsd};}SI7F?Ky{~uj zTi7_NN9nF{l&(;IQB|~`b0_061i%5ZDoY$Yf<)HpUISjvU)-cPrt(L(cbqO)frr^5 z6w8*+qKGi42u~IW@gwgf;<>aBn<~VnlPar@rywquu#8^g-b<)ag%OI&)b}X-sDd7# zEp8u(OR=+HoE?RG(tjZ?6}LiXaPh|^JObmoU5D6EunX0D)p;jjmUMJl-tEym21sax zx|Q}^wxfMIrL@GI$5OcimX`68z=tM3RWNPFyOEu}M96{lxc0alG4>rm za8X1?BWDVWjxHz2dxvKrXEc~KSC_?LRW>j#vbn&{#SoM92yk5@M;Q_yFk3K7z+A_r zl*aTM8u_fy$OUhqKgO`GKfG{t%CkYDjx;AzqlnHTS_9HgH0k(sN#~u<&t)QC2Mx9I zOlQ58kA#H?{RWPvyCwjJ{J`(*>XN`R<^FbgQ5>f#-z<-N;mKT;4{w?$I$Aowz1&B1 zBe3CBdt^G2K2AtVTdj)x&HZb!ty76$QF)0>ifr75;M!zd}57@k#6|vyLdV&!|?KswA%gT-U!# z4`9x8E2)Ncn8@|TtNYV4OUbKirovl9GXm7=?(O3vo8UmGh!Qy!n3g0$E=UZorXtRR zjQ$?gSN~lCf@u8MYRDtab}aENo+h=8+y?jju~=eF>iXK=N|N;Fj1;*`pXi-u^q2jS zgIV9;T)Ebva&dVBbjNQ$?rR*B?T8otKFa>{aG8g;QG~Z$FXlluAVBG0{8^t>g^nG^ zdyQ_4%h%M{s9Tf!sQm5#5AHX6BDGK(GoXnm!(OrI#%Iz2(O(Pw1N!O~>@JO(XBnX& zPGxZfkP;Y%;(1i<{d{@;9S!);kKY5Ax-#Q6(hMxA9vY9@K!*>`tcP?rcRp7x{nCIIry+lVSOEOi8&Pzo14%qUS$|iwbl@LzedL}#YjQDVJF$<$7(H| z%f)agxpmgg(D4OvU-9?&TK_jN=yzOupzUzXF8a_cYT{^~n;Obw-bMvg1HAFU*lFFe ztmw?X4|Lk@d5$^9vv29o$cOOO9JTq(UgrX-czHPxB;7`DW(+4YLI$yV<&A3e?gB@2 z&Sj;~4JKb|6czxDW+OI%2n_e?h~ICW3zTSXwbr9vkyKWBvSD<*HEk0<@JiV?;L&54 z((gJULbcuOC1*!Y-Y)-YwT-7bd$t_oXf#)Q^)tKAcB%LvrlJ#q!(NpDbwfSbx2ZS6 zJk^u`?3X^}QS+`=?53teCs11_lCl%=99(obVlD7wW9|Mm$UI0-pg%S zS^*wyM*x(=r_ML;-HW}a19wc3V44H%iAIBoIcBk?mn(n#LI_`G zhM3@btM+-jFb1G%XwID5Z}~tM0-roM<5s%%pH&iQeq-3e9V==TPM7$L_B{OZufedt zOfy;_(*xr1S$@)&@R5UwJR)~&<=O_nZTuOQDY9JEsB9oP6Pl`q0IgUaMZkl;oQ?|T zU|T@e-$pi$YB@p+9*(|zy&XZv++U2{eusa&${tY9W^JzQ4*Rg+o@EDz{8pHhPdd=r z)>~R6K*l{r`OI+7tJQsza=}ddyi>-u`Nc$6v=l&ww9ZZkZ)(&S28Hq^*Ut%O~f32 z-s4<5ofJh|_k48yfk48m{L&|D9ja|5+}e8v}ue`L)8Sg!lB$uLh%B;~6if z3g(3kx11saW`0X65 zgcU;Q)a6zVN`-Z=Xcp^n9Sa2HLVZT19pYnwn~EvBTLHA)Xz!%PK)ru1+lOvz3<2vD zJ^x5If8+O{1M^ne#wA?JK#HPaAudHJMJ^IM1?>6JA()jd-FzzEgJc z)@S;~lcM+rFR5ula9sxONuTHJ91~FNC*gPDY0EPO={Shf?c0xxRTTl}wmX(cbV^|> zD8mSTeD32?e>w#_wlo=$Sa5Q`Er5HCH^Qg&%quIp2lp2N$x;KHkjJy4rn1;>Y)>n_gGeH?!CD9#uc_r-2tzp)ORuYJ5%&OL63? zqe#9iYb&Fr@pa?i}hMI4OI1hoI3nJxI9 z`|mlWmj5>+wSy0xco&37L(DR<1z5wGFK9E)w5&3hG?FO|=(JW9JR$v3EkV9RY%kpu zN);tH_q&E~MCDo(%!(hXh?Kuu1x^ZFkt?^=iZ@M~x^#h5pVSw8nG1V{G$mcruM!d` zVI3B4b>!U)QfxU#J&EeJRj>sUxGdxZbe1{@xC>XMw)M*NmjZDto@7`0$t&sI!Tnq1 zS+``8?)XewJ>&gU@n$7rfoyzsPJCkyL_3~ z=?f{(3qB~5!jOVd#0u-z4C0S{RE?sqgm-F2U}Wz&hIZO)v3PAUj98GE4q%Ibk(%Bh z7@^w?6x6N~+T5_(`&f_00GL*ltH}UHo5(Kj_)6|OXRY`S^lBVr);J=#3)S{_uCSHv zUKbMttftN&u3lVHa49tSw$DJiB!S$NPKCLfn2RPUYWdj=Wb zpVKn6_OIx-geD$vqw_E8j#NeciEbpoR40@|-rF#@qy#U`A*;DzO&-Hy{h4lX2L z;;Lo*2O^9Z<}D+-U1Fy{rZb*}5rn6A(nybAlA8i@4K7AKNM63>tUnrP^j3j4n{T^L z`Pqr&k*`dx*-jagw@QFN?}xKQP)=Pg;c};MKOK2ax!s*I_WI6}0(f^qv8K}uKsu>6DllHmQlXmkDk$K_~TLh<7t^ZN-b(?4LgwMVlr&Y&PEqI3PxzS7_@5(k=$ z2EK_9!u{=i#&g=j5AEMbh0=!S4QEhArA;|<)p#mnMwJFJLEg^Jx1)=540jLmt(SN$ zSYZCofPTD{Gzv@UgD){Mpp8mZ+@(%~%}GQrR6wt*MaSHV9L8@m)`jR=Kxq?1%tM*d zwj?6f!TW|drYB5%#o0z0Z|bk{f5{mgE*dpZ?>G;?jDr^+g_bTgU4Ie zjpx7beJwL_;kxv}KS22?>4&wP_u#uvYX|iLE1JC;adxTTeiT~E)K<>p3?8PNF=XeW z?~fAp+jmclk@uEkS>%^Xy2ZX;xxetWJ&+wwKV}fZ<72{iQWKhA=A}OfM@iJ#`Q-E_ z;p4@&JdcgeMLPsD-&P_qor7NC6=aCCf5@3kRIYCD`fTNC!w(ry_@h%hh!#8#O-0m^ zWqqFIFSfC#W9*+xNN$@v!7z_r8m zJ1^(;Wz^t)y_o$xqoLQJs6CAw7R?-16$o&p(RN_tc;$F{WEi}rUb(8(4g zn8$ZpT`KX7t$+zkd5YJ|earEsPTI9_9_Kb%EpiOE78n@WT;Z?HRvO?VUANqspmVZf9v)eyiHWSl)qPU=Z|G_}j(ts(M<)g}q z(}?$o5foUdf~^LPw)I+{2NLR0sR!O=#aLE*4uJSod3SGBc;9^rVbzf(Gptf8>p1#<;b0Fl;qx znFgL)c;Zx0w3}~qPPLLPoG;3$7%7ds!C$ONqbKUo8^V5lbc%YvSR0~G^6&Ixys%+MX5Pe$f9Iu zE9r$VgF5JVVd{^qfP#`BwoBI}nltNhWq&kc{FlxUx4h_bW6- zkd=#8wbHfP2c+t3c4LMw@_;FxNtmlzFdUBVH*Y2G4OzOl#XCkJS&Y@)QyEND<)CXG3FTVet;VkPPDF;miR~!t0W+ZcKE9;(J z+!HOL+-^Q5vUW_AE$*T<0Jptd|I!zpOA-EejN?=Or^<2P@=V-u3bi?oFYd+&AZp_( zrxX$ISs$<(#EXl&99n6)+kEqU(KWcPL83DC&V{>1({Vw)=r-2lJBC;ON|f>f3_McGO)l+19H|pQ<0hZ!(y_ zKPU2SyBAmo`x!Vac4Hu(+a@yWyZdZTc{DmGp!#VKb0UGOh%4oA(9Yd*$P&LohOqQ{ zYm~=K^)l|hDN=D9@Kx(pB9^yJPt^>LVZ9Z1pkiDdyb`i?5s2=@{?GZ1`TtQFppX7% zOO|VtgqS3%zQf57F@9yz^sBA>p!e6X@f!pNu-|FqVLSmk6jx@*R`8=#cpyKH>9An3 zhLp0L!CRfyk>znL=}$9-76j}h5uC&2+{C%uVJa5&)`4)(GU8%i+TqU?ELAry>6u1C ztrl5FZClhdF9YM;XqpCP931d+hZ-t`i%w(sJN;Svik?W9=G>}iFAp4*S=CkG-kN*m zz{Q8Vk4!((H*;T?0ECZt1|YLebJ@92LC-qE9XC~M-6`S|+YUG+`=hEPva%=RJu;zc zt`qyf|K5mc-7g-%=XvLv(nX2CaRL_61fcA|p0XHH;iKFVJ>w&tFs)pWSH+kO(`#yl9ia%%=j2OvRd|3Q(z2ju>) z!l8tX|C1CEsN%ASDJuDO6Z(FGyFn9v)^QhdzcFMtSWVu8G7buqDnz^K3PPT4JcKU3 zYJk%d#~{DeWoPIj!yCMV&}3?Vn-D?Z(hxFzZN-_8`S9nd}s8RfLL zE&~wx2GT}d@MQ|Yw~7rt$x^cepEVu5;#ZuC$wjlMs2W*1U&R8W2C8;jt2?)C(B6q# z4x$hQ<1R{ZzTV#|K-^hGF=i&Q33XHCcOle^ys}?!xSnonX_(?Yn7{ zMH&%UkVE>a^VNt=V5YQecqYwhjLwRVruUlN999Y(V}*@RSL&Nf`FSUc=gd@#6Q7>D zgHNgdYCNt)f1t6(0~2*rxJDfL#azv^$yS|F6w@u;JR}=oe%RJ0jx$%5yg}Oyn*%h! z%tZ%gPZBrh%guKq4uU7uFf@*5SAJy7I+o)-FjaK%M@Fd){i7f3`!9s54-tyI+vA41 z!Ov3OHn+Rw%(eF=g}5H<2eq@#eY1MHAe1IJE}k5;xl2XZ&gR^l@{6yqlo{d}CozM1 zH-TE_ys13b9SF{q+Hpt0du@Jn=rI0LZJ1N#rP7c#N{e?_^D=nrvDXr3I;U>#8>?WI z2`TIk*b_W6FpoAde6ZHeeWSZ@{7uzK7V6?Mm?4F0C*6C5^vJY*VAy=PKsK088~6_7sBWH`<;VZ(sL(MQBlvl8Mc)l7+a=0H8wY@L-5h0#@C6Jdo-i)Ax)%Dhcqw9c+;VZY zM*tgz27akHuD9xWHQsJxh*LA>z0nyE0h$H#HW-eQ2$Q#eMY-WF#|XKn4%3)?{ph+B zsV5D*I{=6gaEPzff zMOLz$)#O|!YxDiJ%#++}kt*Tk$&RJvougNIOU0lQzgXsh-U_)k7vaiXv(OpMPggZ9 z9F=9Y{H5{v^~KFk`53yd@nS7!^2kYCnPRVhV~SgEpiwXPu#TwW>`bE-8^QcShQI*{Y2 z|2WyTqnF%c@ao|a_HqD7i`xA!G3V`a%2BAhwSurVueBmO6yU6)oo?+ zhe2v3l|EtIz09P64PhTBa&>X+*Fm0OJhs^Z|E>ecP##3;YzH-Y<@o$de+<8n{p+`R zk%!LrM3bhOSoP}<3EIR82wf(RH(FK9e z@vc}2S6cL|T6wB^>D@q*X+$mf#@L!lTV8s)CT1)LLwC3f^5#-Ms@TmapD0kUfpOp7 zvF)0+@~1!^QG38Sw|Sj$Hk(Cjll8jz9G-a`y(It2w}No2ED~e->9`$PS&0pncm1%A zCH~)SQ@;-$He-mY=Ge-=C}cGGDLQJssL*}Y&Uned2VD~wG2;ERTgU*hv%}}atAY#k zHlG!g4qCgds)}-s>UL>v zVqE?GRTYKVS3l|64jkmWx$D8f&f(|gDdpXrl%H(=sayxltpaZSj=z-p4Z=Jyw$PR? z&UsR;XZq_V{qNKkg#CAHV~8~Z-)9Hhc##;63}7p1U|BrXisto&Z>A2Rx@Dq$5DhFZ z!Gy+_EnjxN5#ueSTLaj8VeT+Pclk8S2?$x7bFa_2&$I`|Yx&Y*T?S1Dt0`jBOUcMp zOtE&U2&#orb}?VJ*KZX<1?Qh$l@GWBy?gUxTN09qtMU_L=KBmAEhz>oSQK$Ek!O^s z(~!XD{C`*<02nUB`b^)B4>Q|wKTy0t&UmhjG?5cgjyAvwB<(w_wY}tB08VdAp|<@U zoHH@c%8NL@6`#9~#W-x-MB_CuYX)V7*nF z7kSmzL9rBv)Ph%R(V;=f+Bs03%AdP6 zpB-&4Tdb0bKeL`>|0rkrUNcU^PE)}wx?~WkdB)nmdNm^iRnAQ=E8_ZM(y++_guQ6q*klA`Va2*y75~f z;8kEGvSbjsSwgW(U0jSpRl47fBC)btg%FG87Rn-j%x(`?+P?gy-MqP({LAuh19e>2 z1uX`yr=xdn(u2*3!6s`J7(HUFv4teQCPB+Re{ke?w<2Ji62eEulZh(y$Fp#)X~G4) zxs{Fy)oqq?O_-#LGqAo*W`pf??D=uaZ(a?l@xUyUr@-<)d#!olPEP!=?}-)(nK9!8fTS>zV|CYmvqDd6$R>Phujeo*z&Oerg~ zTYi_4F5CuBr{ddsInDQzFV*8EHikdCEC*59Mrpmygiw)jeg=GvmViU&WrK`0Zm*3`UYvJVUY|D#~w0ky2 z`0R6+aK$-vP7EnUP9l>wzkIcum!W4M)k)I31|Wrp=XeHTZQc-Nej!2{P54>D&)>zm z9g0Znovf-P0GYa~(k?68TMutRziyx$|89Ygp1%2a_&72}BN##GNF9krzGO`{={Pva zIS}Fa(ZgY9nm=UcJR0bqCJIITW`6?3Y#QIjwtNi)Yq$|C1jiC^~Lq2ez=rWr_=` zS+@MSp5QVtyKX+R)^G7T0Ba~3$vl>uI#UM}+UEID-|sapPo;NubfHDCIC3enaLqxVuc|{gj)83UX zRvYflX^kBS29ktPRkY-)Ww!__JxP-`#2ms}njWPI>V5bjF+YCf(PDhTjg{H+tk*Jl z?mUqXdrw1>8r9{Uzf(J&#&<2=@@tzOU73 zeO%!K|9Gny^;|77y_XV=9~y<%1&dzQtt>XvM_oEhuh2qdt| zEo8v${k!5ISEf>gN#A)O`#(gn@Qb0p3p8)uf1C))Up`To$xL5-&Q>43(PB-vx!^u5 z^Q35Rm%IKPZShk^&{WMD9s7+W+Frs4z&_QnW%b)IykT_j7r*uLu7l~bElA%>2&?Nm z4g1#SYzXJs3Kn$~=@2C$*efC@{p}00$@czBi>t2%6;eF;4u!lQi4MKA>orIr?H8Dh zed8Tc5WmOQ!K4|-uF7v{e7g9u$>~L>r3=6CYqng$^umKCv?PfwDs`{pMzZl`vhPBE z;xp4h{3?Y$b7&v6?1yF;pVsZd;Q4U3=i%05-ffda-i_i=+D@LQ*IAspbJy&lQkobH z%PaRKLx?C|Y=%u&vY=sa8m}zmeTRwoVq+kxZeNliuRuqr_yszO)rYO-pM6^u$#SX^TPW_Ni2%4x}SX;fE|eCBTXT^3hJkiI5_1+$-9lf%o)gj;haOW-y-`$sJy~!s)QMKbdY~{;8EdMwDHvi2JTK_&;rf^8H zoWTbUM+zH8O_2}*T4luwygvn_opM4$2V@~?Tw<2i?&uuf{+EAbdn8MIxi(E0NL-hy z$tqO?CX#X(G4y=A6@+y#4B@Pz4Rvh@lG^Rly|}FnTZXxjh@WBs3hi(3Rqm*#>)?ad zmTjB|jOscHM+y>3~u>$}C3Kk28hEXV!sLMo`v((KhI#!CP1nk`=G#VaBG%P&pmb9fN9JJ zWo?&ra#Rlgh$!LFO?32;>U#EW;7(xE)LE;xOHyaeHrtscmp#}^=SZlswuMJVmPAZ? zEdzPGil&?2fgw)+t4Mj{5B#sj0%-qDvn#ZPeO%NGWR1n-wW*?!TynY1UIm*9`?>BQ z+IzI{c$ulbjEKm(`of8Jw5Be*f|DRaFsRDTGC ze%<$TKCWNt@Fo(rDu*o~kHn`FjhxzY-C#(`DM+ki{--yyjxlfI)BH_6>^@0vgKqpD z^*pJNFbAXMfQ_uXx$AD}PIwu1vcG*5;cr&XKj53Enk~^Ufxmi)^iMJ7+iv;|M3fwH z8sK~F#aj4lh#lJ&yhXDlvFo+KwC0Yf17yoxu7`Rw4X8I0X;aS_ zw%nT2?8$sBU2syEY#um!Vo8xe`>^r^s`o1W)U?DtVmc%2Do`b)di zD#VM(ouEjwD2`l_V_n%Zvc}bnsf>ciioqA99BqV!p^)8Y^SJEmP%R;MqDE6e-bf&2 z1J!0Y6*q}%OX_V}QuET*HvKp5t}%U0iZS?!b$1MwT=TBl zDjp-XH^j6zVUSzoe<+3D-@8`Y?LYw9X}NOOf29`B(UwNSlJu_M(TcJ$wjg-JJl~2{ zw@^Y-*)XMqv@WrgD5rA{GF$xkNRnK6Pcv-87uJm?gDDqKIy{Q}3G4f_Rhh{NrD(Ra;PxF91igLXP>GE%7}p&=a=1E z&T=r(D3-W)hY4e!gUsu3`3tlnvtzjbJQlZv_g5vM5c%PqtCKI_CSCBpC@9Yf{%`i# z-_)o+wG=cQ6eaDjawYz_iY)V9+7IpiZIql1vUZk`3}^b9q?pG1>2-SE!-FniVcvdy z<_w3`ry>u8aUE|Wn=uZ0=NE|%G_ZY7C_0AglIzY(NBzO&Fk72%_a$m-(rUZe?dOIK zrM0!CX)Or7j7_LSKYk>$Yj<7ezRvfM9Db~Kj0bq1ED1SJ{CD2tFZbcU5~{E5I_-I= zoi+aRfwE2!j!fsH(@-WYnkAVTBQwe?cyQhxerQyP6G6|z>K*4P(4qcMjAgMfXMZsL zdFeAo^K`E5Y?Nq^`6plpc(R4q5AT92r0bBasB=89N&iN|NJLfeQyE zhx+FQhZ{Ti3U|2VSEq<0@7HSCwa>6;^qM-mzC*t17ltwN$se9?BE zjYp6AO6Y>SzxFJWuYPk7wg6EoPWR_CJo3Sl7cA~TXZZ$4J(45^0|%}JB5B;DKv+fD zXVAI^{$TG=SiR(~@`Qv4|LZZ)wF(G7HbwW!33)!OritF%5z8X-)?o2bp(a~?P!?+O zu9nYy^x+}UYtQy8mn5l=>gg3!`GwM%Z=!CZB@nw2ASC%N7#*rJOAe^I4{q}MsnoXA2KU@-K>RtWQno)~3%*mfiexaIu-<%R(*XddOUvXo1(=IZyBv05E_uGOxr+fw=no%GBSSq)0}#5yG9GE-gGBS%}Ao%N2gd zPiyOexNt*Nk4Wc5qQ#ZqY%I$9NEhq`DiWhU+rr3oL5R6jf`+=be{ouTOPav*=XdW+ z)B@r%z2Xoee8VKQPG=q9!`YlJBt1vAtzn&{S0mGDjimdFg$>W8*7x7P)BVBc;&ly> zS>h+x>&iy81gq1nU4%lN&v;@UV9w#LiYbb@FLg2bFF%;+*f|oZ8zG$Sq{+b{`cmc# zo}*wvHq=!G(J~DLy-L1;y&$N#XE!^opx0_#B$z~97?#~gBOJ5j`u%VM^k|}10~WFb ze1B_1Mr?z|OTQ&NuNJ$zA=(~9?Q<{8tu@ctN~~R~r9w>psp&Ttx&P{W+nkz&fC@le zL@n{@t1zE&?wmelb}Ia=+f5PPMhO>{p~7g=sVpp{V8kZTe?0&wCEIOz-&{h-MNc)M zEz4b>d%*CO9`hF?Xt&f9@Yb&M|~P@@#bcPD5&`_g{?r`z$aRQc=Nao>UF9> zv4(_a@U8TC&oMZW$4eQ8;NN^O#t^3!8qV^3A=AcGDcH@|oy;*$)pO!<{sGousX`BM zvHjDoY%Yg8t>3 z-%>8@>!_7D7c?hhW=}7^jOiVy#=WQIhYG|KHx&%M=bx2!;!~ojSzb+wKT-Hz+!3e% zzE6n$@8o7BJ!tvo6u%AP@!Ift+P485^AF~Eu_&8pvukLg_SkMvewQkG+awtGxv`sc zxOGP(p!;Aqo;X;kB^P1my1h+~v5Q^FE`QOaFh}9dS<);&D|_pzdxqOO{PMKynP8Rn z751O_`RY+jaix;j==aqk_Fg4BIs+I4((cTW3u(i2V;G2&oP|IIY_^TCLLAxvl8Gpk z!Poj1XN%M3I>mm0LBRt#!7m}Qmeety<6#38Oqk-Zdvn9T1KO|$#~)KU$m5+RueV`N%B z>Z{XEV3a?Dwv5`3>-2}O*7R7?9xx>=UaMEh!d9!dm~1TV{MPmXD}H=ul+TxEX-+8^ z@aF}83*H&OT+P|@x(A=#@VL9`&z^sgzW8z57-W`&_UvlAGNvKBwhO4B}83ucCH~zlRsh+n@%%t-LglC63WBY_swDF4(84E9(Kgq zC-ZF`ZY3tkG7D>M>S8I@BibgOZtZ%SlN88$(N?bY3+`%JAX?0BZduoS@4~UUe490Q zDeMW+e9erGg*WmD`Bm17^_4znH9#Nr<3RkjN1@5>0W>gleUef1W2Nj=9XRsa65IJ$ zG)@ndlx31a+*10x!uRLp`)Z8u&qnVk!{)D4*D?PzB8M$1HX^Z%EO9JJ{lUT^zQNx> znE}!l}WTXM1U3sfC%Eo|~?KD+Z z80+eue9{R$IiSl}HR$p0GuC17DDUt4W~8yY#D_IluiJxvye?&dy^`eAReuKyrPEZA~?5sA75$Gi9wbr1$8;%Kd9 z*bfm)QhHfUi@lknw6xp&(xu@0`GMm=2_oB8GFpc3nv7rVWcB0tOcpMQ=t*tdWP8aQ zGA{ZD9&49lku#0uXZ-vAb$7dMUS_uGz4M*^HDieO_%k<8GmqOY{r9akPQ`B9@#dvI zLFI0b*gV`lu+i;h0YjU$<+@7Md;i>3gB|@5fn(!C<9{z)UYY-M;r94;pRBYqL$&y& zc3Um6i>X3pKIjty{hzh*gnK>|r*enAtXWbSjDGNHH>7S7FV?@NkV~duDe1@TBm}hb zDVcoH_jBHT1s7C@ST5*fDKF1?N2bcFgu)K+mo{EQ-^jj-U9f+pOgM>_m$qcUY;LgbxDFO8SUwJ<{i%Glr z`)3W1k3*`U!7Wd}LEW-|r+&`2T_EWEqE(0opLu)m)QAD|NLcsx$S#zNWMGKGr3Le6 z^oICvWtIO=W#4dm-`zf~u8reh&fZkg;&uIkBAXaee9#t7=pWscxZz3sWrVFiOw=p% z?IX{}ZN80qL4aQWaPWG}K6~sM4EIC+;t!XUH*k!{in0w4*xv;VGNdYGw0&&;(Z#<3 zIT*k-Pq-!IW9&K1-l~Mok_ZVF@#Ebo2w&JSQ*T<>J260QZvCil1YErylr+8vZ11Z) zcsj87qT^kzv6%tAP0DOr84QLLv#Rs#oyas(b*LWRpv4bgF$uy}$V+GzMc7cv+`h^w zXd@jsr(Wg{plqigKz!0OybN7%*;PWx2aeg!|DieU!|K4@^*KE zxM%ME@1rO9KOeovZe!4TB%<@~7HhjM-X=Sdlku7ByH%Y-HVgRs&`bs)PY0V`J`ySF zexF9Vi<|0%Us72*oox|Y6wE&>UZuwQvkLL;y7$>Da=zISBtz0FVjk2YGvOGTj%m#pV< zIL+3@IjL9uS0)lqSW0rKYDWKbVEAp3TwokjGWb~?+b0$HjVa86b_p>9rigoIC0#S| z9-7ohfFK2(@UtKu;Tf8~FG+(xpC1|_k=H3$ysacdkc zFK?Gr!qQMZSI~FZ569{j)$Wx3&x_^re_kxaFG6V0RNyU_=-e!IxHIB~$mI7X#n|O` z>9$1nWUV)l2bS@<>ff~ru2=Uof`3@>W9e3jFOgX3TJd#B;MS{lWfdTZA0ShSq(Uy* zat^aD9DF`?89Ta;?OxIa=U4E91%&-zh;4CnFa7pc>M0$JkG#*a{VDp zB0TuK8aRBIoprDn1y~ZVPl1kJ8cA(6PoH_ym`y@%X=m$*>y2Fc9;nkmoL;W_P6SqY zf$n!&Jb3hINU!xPe2?Bai`xP|z$G52q*V32n;eHMt`k_USKko{FL1iJ`13CrNRs{d>NU zk5EOIRaMlkJz~~gF^X!8ZnZ~?TA{I5jG9I46@*ej1Qoxyn9aq1j;L#uKw3S-Ixl^XWO%L-wsa$7O-F>~0qJ zd$FrhK^1?!P||;0R@wbn>>2St0vOnHa)se6>{{r3A0Yr#MY&2es3;^rAOu#ot;XRucw3Wth`{1Tr$vCd_z?n=d=4%j4I|C2&fazq#Y;QT>ww|P%1G2ZwRo< z#<$I&bDUIBSE+?YcJ;&k=BIM}Wv1+P^pLNbu|xF}I^2~i(I=pNQ=6XgC0*g+keGep zF@fZ*ZsiTZ7=t^LuD|L48T_A@S3y`GJE{=%=CBapS^0H9<<~3Nd+;+|I8pAgzTbik zISJTpQLY_-USeF)AdBOJy%DDDvl#G&KM?lSyFU;%$D|N))=t#QWlK(#*b6!JNb6N z`$~}0Xbj(L5WbZ5qtSkk4k6$8wyr>$_&5)Rbc$%svJGGqSB4e$h#X^4ex~6e3!?a@ zUzVCrM5rAulq*pTkg3g>auGj*j>=x=C7qAPH%cT_N2jK3We(jyT{MblMQ1F(v5&&W z(p87*!+|I>@Y_MBhSp)*Q2w3%Xj^G_*9eCxfk{K+Q8xV7Rar{-OfcO46e_o3HdMcr z8!~WNH$37P5;`7e;l3YnGrE@XF=pn$geKW~HDw=J;nm{3;Js)v^n(sv2*5RFlLk2n za;!QwKTO|UY-2P;CLY-zvMOVX)}EU=9QAiOmtl2Pj>y&^j%a6VT|}UHX9E!Qx|K|g ziZpQkqaDyZ0Q}3y>drBNFjySL$I{xWQt};2wS14H6y1RfYnOB`EVr0VF{=;ie4tp4>XM05-&c=GE=-Drw=XM1x1l5HxRu&T z;$x5#25aT;o1YKJ90j16HwgH)5+clEN2&M=FsPy-s&ig9gJ^kB;buC$aMnCz`EIh< z6a@4rxHhZ60o@7Pym4VXz{_y4J5*Lnd~MbR%GKH=ul!gXMDIEHb0@ji-}pg<{5*C7|k|sQj4vLj(~9}MH{`Xq)sKqCRZw%eu66O&%@G*i z{E+8iURji0beB|lofLGOU!ohscIgr|G7CK0?m<;>Tz1$9o%_{wpf%yeyf)9Ttbc2* z-L_#P|G*xB4bhgU!!VZUczB#qo5*PU2e?rER%ErVRW_V$@wm>ARzRis6!Vh5b|Ljy z6D2vf&nb%qAAD>lcjrEL|U&e}XBu5HhwwH2Y}A{t%3^C4}j?bZ($r=oHO zbDIh_-Jw=u;J{$!wjxpB?Dxx(B@$;7&}{3Lf;(wBw8wTfD21US5`>G?k54yV^iug? zHwN7R>Ab>Z2!#|n-3eb&)3QD5t1!SJCw*b^`PYMP`<(|f{1<8MK~n$Jg$(QS5u^wg*i%*lFRg()QQ-je~f zoQJmn9f?k~B6YJX?|wpjJ`~F4jB!%;I;u|pGBahq)-t*%LEVC0+FKan`h8kfj2UrG zi0B?atAb^Z>@=IVxeH0Gl_&gKBeWytj9CMdbBAV!StYDr%{NZYv6#W#_3-wcw~H-v z?5f+v#A{=C;*HYJ*c&k2=f9uK)Hw!C7gig-=a=3Z7d#lpBt$hq`_F$j0#k$0wsNAFaEXaPy$gHRGGSA#Lk#Ev?+cC&A zFss?=Z#m{I_3*|2(l0T!r6VLc3sWr|h5=htq^8^7ap_c+Dt<$REe5D*v7IC8sN9#| zdui`u<_^BQ$kH#I>-o&<^vvykG(J(2Cc-0Rmox}HYeU_hOn9nmvW(b*B=7NobZZ7ikRWv%{%1#+>sOFXe0V;DMwjvD<#TP zXWaJ-shF@-*s5m#vg3cNH{y_D^3fM-+brmIwJ7ajS33POUE)}Nh0JtK$dx-s)D+)* za+U-a?Z1D6tDeR`-(0id|Gw3^7Z^HTCO$G{W-LdFqh|4HaLRtYWd64E1PX~cQkx9t z4xSt{SJx4?O*&fE6dbAwx=lb5!3=*cEdDPo=8Ng<0fx^N&5*xv)$px%pYw);*Ql(q z6wl5B7g+9fj|%}X&Mc9wAkPN>2Gz4>X$)n&`K83mH+X9`_~a)>Fac1PX>x3s-S(m< zdwm~*5^BD$wAPSFPh=TgIX2J*XT* zEq{vKQKu3rqtgg~SZq22YU?I(;X zRX&XeZvpr3?D{$QUAC5gDt4d9_dEQJamx@7(|tHl()2{R8162r4D;9NDuS5HHPiWO zJ;(*xd1LHgncW%k97;}`ZAQ!+m^njV?ekHqGqt}+g5zI>^~<^Z(u8ycpStD!j4opO z3~&kQmJ>^8cNsZB6kK9wv}31|e$RN>IjU@+ol}uRP4mL|;;Y~PxLi#*U#84^>H1xj zu?B_jFxnJa?Aep;7F)~N+0?J1e8;;7eS8f@)#VvRR}aHH?sPr*2k+2YfPt773f9s3 za5!iwJKKcA5yR*1Uj0Q?`q-XZ-JNHICmsv3(S6i8tYiyT%(8k#XJB-U3*{s$+mYfE zYEb*7wd0cNjaAw5Jhs~gF%M)m2aCNh_?PvY4*%#ROy$U}ths-ac$Q)rpFjv*zK=%x zfrpjgaTQP(Z_Aip!kNaz*)-b^B>`aloEtF(ODD8~2*`5VDhdjY$31V5|8<8fkieI% zN1Qw+Hcr(B^arRjo^J*`y0^_%ccfpSpB#*@B=-A*ahO%y73&!0MCV zH_c1*=y8)nM2agWlxu3tf7XlUUTYBzIrzOov;*_M3((%Q0`Cm8V3-WJ*XqJgt16y# zYQ8?&rb;ci98ff4O$JfjRNxp7GJ{D1+U4_-?4)g)(KdvgJ>jj;rkqbY1vv|w2a9#Q zzr6KTW-{f!w>Pf84H-62TMuOP{uQp4+<9_(xAluv(3aI;S7{6Y#&6QT{h zIdI9G%)C?foXjg1`RqIm5?V?7X7a>4c=mMBHdJFZ`tsp6z!?9{+7_Ei ztxP2mTvhm|7s4KOiErStz2c2o4dn8aIK^_?9xuCQ1Bz44?G)Zm7nw0~`un3zGFX@6 zp!eTp=Lo$_JrQ|HtwfP;LuS}q@R{@H1@^~d`QdDT!7JQF=#BqgQH&kCDyDeh5lprL z52>Q8d9SQS!7eHq$&~r*b!%*`Q?2&&f(KCJ!fhq33I$E<)wrAj@>`=cT5_CKu%OvO zX_he~M0|~9sXP;Z2uM;;VQv$-J=@kw)9LX~vHYTsnyftAiu2rX!=vEs6}WOjfMIon zH|yl0;6`PmDOM#z^QbmhWXebvc6{uYjk9vrpQ`a#IiS^^U>)jxb{M|va~43^w8ENS zIz-@Z2wW6ilRC-^4zwoNJ^ZZQik=}11mWrUUlXoN$rbxs{$B5K>n-o*>khODnPJEI zH_v|A+jXj5e+K3WC(8#(?KkIsP4u1*j-f~Pg#afnfm8+u*IXYt#zbl{A+j3zhd=zD zlROj1Cv$kH9D{SR2nb>M*rV!VJE9({3pcTV8}R$%dC?S1l#F~86te-rW%E+e2CN-J(3A4+XIRIlaL zpFmmmPyU|2U1wu;Uhd+$HMOR7rzT=h0MM#{!Jv8qaK9ztT{EnK!SL;1&p-`@%++P+ z+s7&Xud0Fv_*daJL-s2IZ&>%Y_s8qj&LbXGR;dHx_YJN3>_N@PX&?n@ZAGeelfc6* zbo3m3;k-+Dde&I`_S_N4tMW@*4c{k2@l|;bun9t*Io4S1`R$GnFRstvffI%`bgn0r z$^`baMUI~SB4`q+IX@A>Tk)_+7t0QsJ95RUtu`>Udj*lfe|2H;AOD4>;dCZDrze1b zYb8~#mgD}kO07|-FT9au!TQ;61y*T%55rubXxO6Z@7)OAx)6j2#Hln#K}x_m~t zQy-6AxZQ*E_({8++}%}{5=q2M$8|supSF#Ld#eF%A=;XCFJu6q6VR11J{6uDG^e}g z-8jGe{DxAh&fd3}tnet1TqRpJ3g$`{lo%+zvYo`z<5NqC#pAMq9*{ zF>V)Dt-Ti78s=NO2%{i%y7t8@w7ZCh(c~LA7t6Nd+u#{)j{&z%4V|Si=3bu;dHIZ7 z&FQ<}pMdjxxBQ#7NYFZmXwco7f6z&9cE_~A4N_@o~+gcuZ(Tyoc>1g z{1F07b^euB_XNkzWrF`lrE+$^i~)XSW3F^guk~X^iCXMLEh3)oP6Ucx|7JpgCZ31w zFe#6apr?D;<4J&MXTgA3UA;lywxv--6JRKCPW438`Pyr9MZdC`^v!T^#RdVM8Xkb%ogzBtK3miw;wS-J_ zhG*)=`&-*h5nr^?LY9(5!?}Twnr(!q?407yZ4d9#wViC0q(d9f-HHg*>VD7kyGPDn zvCXxm3hf>snK}B&kHRhL+ddKJP3*r~g{BYwI^GL9*?v!apw86zEdxrgsocjh4JMDN zZ)hi_Yd*K9Ov`@(=;RKf;ZB6K>uS|s*S^X9d;^0k-t`xZ;%=XyVYv=dRw&q!dBbb5 zC7VvT&-wWlz*qJe51uuD)=VWV$+hlnIIxYm&9T!SPQS76PwLh`4dL=NC!SML4%v;- zNi8#X7XjBq#arwQWX@9oCVRu;KK~$cY0r&^$jY2Vv+sn{`Y%1|)q#E;fDn;<13zfQ z?O2>uOy_JlvHozaG~y(=%8gFhJ56FjSYab{aA*;g{h(?nsVA8aU@p&T{1el)g&hqK zg3tE0cgS(LN_vgwy0|X?{>9|P*#&9o7Cf%ki)o|mt|p}I+~8^rTqw$P0UZGxbc=o zUvbstq-0We2AvQp-*oJxgF`BKImA&uryROy7C%HmF?7~bZOHVk(a2CNxl z9nl)IuWC)61}1!`RyC7WfpdCmoqPX`%6?2~KMt<>h<`@|F*q3H)5kM|aQqg)4mw2w zO=OHFXp6oLg;&w2xpzl=Gs)F42h0|_5Z(g=Fl0xabvVU(T$+APwMAz;lozH=Z;*kR z#*O!^{qAu&cEn~{F-Tl@d&+GK+nBqFaIt1n=*H?A*8ZSfm7gly#gQq zm!xErNMs%BXxuMke zP0i^)z-7?kHxZn%=MlLSL9G;f)tf3)f7``poVkB1h7!0XIQn83nJmN ze~$G1hkr2wi4pg{mV_ishDb)3K+`Bzhjg|Kh>Tp!_r5c+~tL!I%a$?)j~Bb-?5;~E(%72k6u?K+H=eIP0r=~T8lww@$XV{5`?Bc%4xhGc zA2{^e7%{@41}NYBs0mfQZRXY14FK!^*!cKcEqg{uVk!KMU-2qMGfnp_{b92(9|3&g zMfK0}>AeEqEZF|GZKzdD0}NM2-#p{v2kjL2Sx2E4#$WI>MKRDNf^P8SY1WigQD+D$ z@RhMHtUG!^pQ7S;yjS+8<)020spOA}9ijbx=X44ga?7@V4XYsH!`cW2(49J@u``v0yR#BLE^DJ%DhfKVlyp0TCt z%^5-_?W(amtaVbx$v^B6YIL@AGCi^$b_s*JIqYI;EEkP61fP4`l~ z9kqYci#+c^v0X>5!kX9k&vUu)lYEAnU1=V(y`m?j!DPER569h>TO!3U>&%4!1^{2$zXtpdKVOp1t%2gO; zekVk3Em6Jz)(#pJ87K_=rjT>?hog9T*7&1qXcKuwA6QQCYsJrSOOj*3yqKfo6NZ|r z&s6z&>9i!He^W7k@PeUe>y|Q-`@1e%)0VAhM=HPrhJ0<@FdA*LX;Ga)iBIfE2i!w|5f+6&~IPI-&!r7MLu zJnZt+NXIFW zZpafP;~#l&{*RtbO8mNbMBI*?M@FrNZ!<@SVL#FZ@x}cDoo}x!rBcf2?a$MXXL>E| zp?MV7(7ki>TC(kBE+7L_F@<;dMq_l8&@|z67f`Q%aj^(~cZdVl^x#ATXG&4oJo$Ql zY<)RiVW88+CGLbrO@PDD;v~OK3fiw;+5!ns@p@wBiKL1aXB_9QRMpVF6yT(>txJ_c z3Wg@C_byx5zCz6cFH!MmkSp?p>=z64i?6}8r_)jlEAvB>ChvRY-W^z<9KkoAGluj+ zFO`m9oo0JP^AXiI%<{Y0U+RU=cnj~r5o4xkefQBH5~>lULk);7^g(7y&1;cwNpgK| zez(oE4Rvk$X-~3Jp9Fx83`j%4joE>|F`yPi_jvEk2BSRBJ08Cv)0JMEI|O^b(|i?y zZd_Res5zy?Mol^R(up_;e`@UldZK(fRhYB4fk&w9p0fV+k`3Mcx5*Xp;@!?^yp7(W zfNn_Kp~LNiWoKO*Z8pH5-g4UcP(7}=k+;HdVM?Im$*Jnc+FDksuvrd6 zsH%c8VDVz)%0Bg!G+gi-^R3e^;0<0H&%QPHijlOjW0X3j86;gVy#Gik+}NO=>)m{_ z-_F_GXN?gez}wHA0_0k_Oa4(70Khf>Yd>)NvIqd{a1(5-lh=Pih{Pl=ONBk)On?2t1pC9~a<&VU5 z{om&IC_I5J8za5dn#@-6xN;z^>t{H?bN}x5+<2(#UO7ariq2ia<(4`rmI!1+#S|$P zNpINjwwC4<$|AmK~@j&(Zs)|Tm=V5nfFl6d$i z=*lWI1^4?LZ+-m(XfgNxI#cL>)R>SCf(psg?>@A|A5uBRKF_3(>uq0981-vD($^bkpl3E??ITT+`bz- zJHx39*Kd2#LVKGB$n322_{)-TWMO;w@e#Ble!)n2Z3bL9ncp)k^Gw}ideMH!pNqc9 z%i9g8f}xyuWQ%9=`kWSaRxwzXGinWY!Lr{YH~KBjJ=|mj-OBv|bT+;9TdY@QJO>X* ztDy)>`jKZ5YE_d&(@=Lw@K_x;uTb*X?L1>?SZ5EhlA|!c(lF}4XWXiLAkIHN6(r^n zuqIKBC`#Rys^POe%9V$~l)|@MJ`H_rK`w_u)o6(CH55^PgzO=!;I;>X2%7Py$qVD- zGqN4}IDXRUdDNBg6-d*+60F`4Jp8P#dvq2N%Qko2&rRw|p2GPG94;bww##9_odt9tOY zVszh!CgHT3^CO+DQ;4$!`x&=R*44u-a-)V603BO{e^on%u%@mqc$q7V7hZ`Vp_8sW zlUG>npWL2~%nqxm7z;~5>wHgwFQ}i^N7eJI^u@SiGtq}Dk!KF{^*o6;0$L`KKLm4z|&;Y-U#<%u){8#up^s9)KnmqFV- znUM`-(F>$~iCVg{AsU4u|0cOb^Ag0f=l6;CcUeZJoMhe9NItTw^W5S{J_k`=`z4l6 z=55viTJJJpETmPcfaL#;Zt84$;+-z#UVS+^bU6Lo9W3Z7oRfQGK=X$T4E+JEtzY_k z3BqA;)V+WNeeL?h+-4bTN|D8|U^Q9XMU*0GsqZ$s%y z6zvZI*u}!^fc)F%VDNt7dQ^4}p5vjQ9*FUD7&k)KsA6}K`5x+` z%T!2^;A(%Br$Q&Gr+#&N}%7EyHkR zrpwg;+Cd*lk=AxH`+$wM;4GpuMA`a>#p0{b z&NiwrP6F^|dErS>>m$2r#4L*&c+g*(O@Y5TEHT5T*oyW<37n0L+?4>=2%p)1f&9;l zeeV%t;D7J%F?Y#mZKT}Yg21b5j|#y()q_p~;bE&_;B?;mx?fjXWWvDQ)`vY`9l*zh z$1f+CPAEn)uJn}le~LI_%fkR`@HEMsI} ztPD5plj~%^s~iWt3#JJz%3EwaHDgJlfc<)oc&<@~hRYeQrfvKJVuD-A^Objdw%xPIpZ}q?$C-4o)C!F?xS6-P5qVw zC3v93nJQ$sFr=eN?ml`yW*F;q5FyS4yXK&^uO+Cwo+ZK7CmH#5SXdu*EId*2xP2!mc$%d+c5HlD{iEGtt_63-jb_!F&X*Qt4fXczNa9M{!=( zLibE!r5&dpG(vhxP`keF>&}Ghl_#hVTH*UG3w)LOwIAFM4=!(IPjO@~+wRo>LbpYIL+I|5 ztHcmZTd^VP%i9~6!z{eRx7ddW*6tMbl#f;sMS<@-Lx>V_8pF-p6TG|U370*jP zi`&-_z{kS2cIv5ZF1x*7H8fO3Y$uk2SZ>}*vT+tq&S0J^9;2VqWx+Z#V)b8Vg?p=L z5>5o%W4)OfvC|L17j2oO`J&F|M7#qfy4!r$l@{7o81q{_c^3WL*_cv22}SLP)l#n| zhMl0Iv56eYT3i<9RBbqB<#2Da%vUA`wSoSi@og6uefO&u9w+yEBRan!(aD3C zUa2#YlrFJGY9OCH_t`lQjH7+jgtMO9_tsh@Hl}aGo+32~!my$Zp{*TtpPjGff>u>qDu=j#G7bEe zDUk*Qk}O9DK`a2bkHHo%gLOc3+3T}^Y%2e}{HyPGflKwwjpQE2t1Yu?-aygzCF)9c z1`H*q_|QKQOP;e!li|3tGadYba63xJ4bX;)BFwiTvRfYPe;QM1mZhFu?HZ7NBroh@ z6U*)}ltgt8o2hB7T%P9(2u*Rqua#oKJg0F9W7nf+L9H^j0pEl{SDvsS!?!%7J>zZ& zWTp^k6)sXkTVZSS`DX+IO@MHn1j7v{kjXF`d1iANniv3>@Mm=gOAnXda5tR)2)Z=2 z@}qhofHvrsBH+I|pXYjKucsmyyQq;LhQ zM(;Z4@jx;)WV|pFTBT+ZhFMG4yu5~1V)Gple9e)EBOl7w2=SU=CCiaDD9Tse^89Y zt2DJ;pZ=tOwiS`EYp_E%X{yHdB3=ErR>XGg5^Wz|n0f~CD5@*C^V0cxCQIDub4S|B zk-*Iqg2Rh9d+r0~r;^i8J3kpUZh~S4L5S>yH3}+ErB$b>&y81q+ue{91AJ!@%;h{8 zqotl2@%xcfMe-3WXIZA@nw8YV<%DPOahGg5_5cMaa7w~18J$5f0GN-?`dcr%?AYJA zpQT(gv!}8wE!byX=c@6_BR<09*TxGeE=QQ1R0`9sLX9wuqbI>B*>I!UK!w%x{>#Tt z&*Ie=rffOdiXzXIKQPz7ZLE7C;{T3l9(VY65|F!zsy&2?oRGrj2iJ3s%F}Lz6+#pM zYKLgvp?OD^VJ2M1H--qF;q_hO{58=U8o~%L`YFZHY4UKfyMLTH)dED?>-M(4;D~uq zy{GSlh)l_^laaSec%J*;RP*ByEwSVD-X|Ffr=g?}vzXs4aK$ZNcERZ$JKaJm)?#s# zOHuU^Q>){4Qwv&(uQ-X+616x%D1NA{(Qn!{!A2Zmg1p5SU9G)Zy3o3y-4noAPiGaX zJvODi`OoxiR}#B5f7?LxvfZ7MQqAT5soBoPfskw=1@*L+NxpvPmH_Ls6Iq=r8_pJK zd>t1G>2w^Ik58+~aOjbp*Hh2P(R7PnU#m}oB|p9rR*G-NmYFuqe@G%SIdd%LCAt>L zJY>DR?J^OBnUFQDb2l_4CpxyNaW(esQhF}cYWu2K<5Jb> ztzJ5&JIR9-1uvBgnnY%o1n_GS$1WT{?0#Z7IHds1{oI$ssCt3N7xczhiR=}Z6g|cc zJ@DB5SF>*PGY2cQw5qst+Z%i0xckVVcS}{59%>JBJbtJ}$n;Dzm9~A?ic#rk!flvW z>#4t5HrVXBf!#*s@O0dXJ!P9`Z5z|Q&ipc5l9Ts5OtHH|l6sdCr_!ijDMf}2qqaLr_$S;y&(>zDRg(D>0s2&P~YVwFS#8R(J8+{ z0)0sQoGD^-=E_!8=L4BVQcTa?6+^XMT{FnD+z?xq$KmmTS}h-MhPP^Rs!mq5vVV^! z&uOLW@7Dy2VO^o{fr$S=EX+yKUr-_E?Z5JMcwT=s9(>67djN{065*Z}-*tW^8q)rm z+KY3YH&%v1`l#(c-q~qOd{Z*B%ZM^}x#+WCd+HD0lNfDzB7VAQ3l~Uvl)2*6jj#I& zrL`Y}Dymw$f2_Bl1a7hp7g8n27bVf3x-A(+%oEZVn;97HPwGThe9Xt$xlJ9~)6#lV zRoJYV$ZYYwPEJMMWE_6lj9iguZ9*(Ob*{cAe%6YeG$5bn%aG~dh<~}jo6p2QQmd5V z`5uB6y7tK+rVBi5^Th#Fg@Cp>BiMN;I@=+?ZboVfX3ZSch>*4~;gQ!E)- zU3byEQyhvW$38bF%YS~iuSL$HlZ4s0w{C1$uupAKo8m^~rt^(1Na)vWBU(oWjiw6`k*!$w!PAz%AS?>WQW+epJ0ThQ9tB)-@nxu*L=P_A&T(zZXa`c^=k!BaS>VpW5OLL- z@`bhiRD8ut9`m7{V!*Qbg=N;g_U?I4Ge{P@2|U_bsxxmXeTBdlkG})D!H;VgBZI4aO_cDGv<@W>`r1`j! z&dmb`_(1Z@KV#hYj)VU+Uv1JngCcT*vlF9VGY2rLUl{L;_lUT1^+R*XkYTMpE6g?W z%Kdr162}R_{X;(edq$a7Nb|HD7fX5G(9olMK1ZBi5-X4RvKT~eoF&d*H-tehLveFF zxOnBnkb^Fqg?7bL^vAFD*Df~e8G25-HkzuLPNgqLfmkRPJ;_NK5~E{3NtZ1p>+{JxcT^-RU&YzonBwYC^SF-`G$LvIXQjU#f z^~)@k+c269;DfBJ`FN!c81*gyBxz>@! zTZh8KVEZsc^7JK-;koYv)TeuS*4qttbp=;KvT}K{5zA=}j<*!xffbnUy%HHwVQmx- z0iRWkK9xOfT*ddbW^2VqIJ)+rYA>{Gb>?LIr;zu;c3N1f`4Ycp5YevItyyQ_Wzxs( z=h+4a_t9jPzse^v^?X^@e^1CJK|YB5#%lyCI1yr_JI|gN_C;L`XOY|0ytZfM$Q;l) z(lg+tBG&j*KmzOc&31k#PHhrPr}9oxgUfM&&&@cLkF-hUX?`@QyK>X-2GlA3_$2gW zuyzV^0M+htx&L+ky14h<%>&HVl6rks?jpoB$8n1*D?EitqXpKhZ*lEsEk2;K>ZzI4 zY}?oU=9$s2C!3u>c@r*BRM`OYMOhOHl@o#>qnsqHf{i zIF4lWP|^GWV|+d{A=}ip(l~Md0E;t)`OMtLDrn{2hzSn+xW1qArK&L?PMEu~Gfdju z&lhvgu{L1|!3+6f#n89psU5E?^uTtqhhs%JEIxRDz7IgI5K^7qzHMwjA+8aCWv z*f{}t|6zNG!SrkzVsM~5tOg;JJgc!-?ZEl3VD)Ct`L9=r;+$$BX?B`L%yoyY8Qd;R z0xSK%uVedjS*Wtd4VAoj-dXN!GFZI!66@W(${#Bg+e?5S$p5w`y`{R;b!63-XoGFeG`w^ao`89Qi*@MI|;Fhpw zv4|oz^_!Z~_QOu0a5X(QD6ha=b_8tkfS#Wy@X|d#p5d^BWjUC`!IbJz@{QFHlwU_* z-FQ4hJ>BETtZh$k{Qew;Q$@pSa%+@-tVvr)r#{c>zBP|r&e#)bs zBonR*B)`wJ$D<#}WUk^PA(DDW5*uDzTI}``wx6Qe(@JMsJxJUwivpwQ@wSG`=!CzZZ?!fEQ~b_zBU%?3K$imEt4rtSW>5& zWf1Dhb7M|>xWz+PT%BXC)@KoY4Nzlt=|DOCRRG`S&7&UlRxE0Q2b|V=GTS62U? zQ;dnq%^?O>@gwhrY2#m5t%Mb&H~zMbE-D2~Gn4JH72j=JHs<2o?W64Ir%K)K3RXIm zWIft1VBPRc7N)cVY)7Ta0y4W-0VicoY_QWNseazap7+8ywlk9scD$M?ee^)rO*qUV+*WAh2*>C$k}4v zzVTXYOFncUAcM4$5_xUvMOrronhEiJjRo9^?n9QDKTdDW;pfCZaAcPJJuJJ@@ouR%h~RBZ}x@=ASQmx?|@ZSyGf^PA=`G zB`rVxxXiCKh_wdC%^y0nO+}vm=M_4jgVX<;e)G>d>e3&g6}N|uJUT~Orkiw;FHxB5 zmV{UZK;DJ#j?XW4To%q-6fEycG>w21TqeXS^Id^mX+QC>D{y&E-5?=ZPZ{5%P1T!r zt1NU7o3F6xyZ5lYv_%g#yfr;m+#`Qz;eG46IeWc~hjk9kuO*?V9tKd+AdC0NVc0rU zibi5kXJZZc+q7w7ibD3cijF2>xgA5*e(hv{Vl!*A6u0y|CqK{b;kCpdwFQqzijJ02 zwojlk`NmGzpsP`r>#iwi2O&yo*$nwLZdC>)f>e9$LE+Jg-a&oS=gW+Q>AMSwsASO>A;l9PP_dL4#x2rt=f?!qd~G zMI+%In{-P24dhIr7E=SqMU9NyEi)XQti|EEhmzF#O7Ud4aof>gr>Sg1ZTdMFjXMjT zJW4s65uW{9GmO0PhiNI~N~oS8$&)FYbeN_{=i`+=oAfTn6{6m|XByV94}-@#G{pVb z8$3Bjc&by!^^E!Nw2K!aE)Ij{`~fAR63?HzD4<(ULRwzIlJPGOUhE$&eJ~X0OXK^3 z=(#no`>@5f)Bqz@!cX%vO!Wt;*)28e>F;tshy`FJhvb#pjKOV>WYN3)U>}_);^urR zg|=y-swJV*Q0D=KL&V6-HO{3U*XenFbdPlaE^lUhp=G;}Nv&1o_5ALMt*ZB0Z38|& zVeM8!c!GObw;F%KYNMWEBgHy^%I$TMa)A{!B7%#7|4g|lTV5s&FYDb5cJq5RavXWM zDLgKnKYMb#J9EV4*z(eD9$X$7lJIQK&ZSfOMJRgv*B1dlxc27w4ai~}k){k)O*b_p z4>Q3!R@2&Tjd!zUc2^p87T2kzeA`A<<59hTxw1clk^fF&ore%f1(6jZ9gydQ01A?& z_o#-64Y~}&hUP}SLD6CockkK${+|0pO{U$7qO-VoN7BIM#%eTs6=kM5mf zaca=%JpUW#xe|1&7f_Zd(<;2M*0}%h;G-7P-cqOK4#RP-rmIJ-)9=K0!lXVursrEe zJF<0ynj@u57P2f>^75)Q%RM3@bA$5VBBvw{v2;(jhj~DlDn*EX?@d$n3wYU>C9BUL zj{TwKCI|a{>pu{V8HFkHbX&C_%~LR4A#a&<{Xx=XlI0fS*~BZvfSt$G@k6Q)QCWI` z$+M^8c#!pvdD_kebu9s9sGt1=WP+$J4>$===h*j<59LLCic_7^)E)B+F0vU0;{wf- zxmruZ)RFulWI~&!jk~1g!6p}MXnrWnpzUc+XslZjteT_#r6}fN3%OuxNc7H`+7ES< z^4V|jA6N0c(Xd-BdhK<(|0gG`m!?^%RgyDPd(&YxoA-YK=Wcof$@iTs%uF)eT$%(JIN>qJ+H zj{{MMG$(NZ&HXa7Uw@CP9H$_#NW(Z(+dT~}s3s>Kuqpe5_5D;iz^ef5u*>E8U zT&ue_Ko}vG{NQ^t1v488Yy}j`KI@Ki2gX*tWnX(EDBsTv4k_A`UjPIZBAMFeOZ66qw(j>cM&dR0#OEBImIYUJ_fKN+|o^r16 zZ;k@)|4PbVGk4>ID?R}dB0csBz$EXj)i-i>CJ zF0X$7%Sx2!%9(|4B`l$T&ZoSVc-{yd*tPvFN!5&||mJ(h$wl_;!o@7&12vVIr zt7%`B-mdkhiclf5G7SYB@?z6FnF^Ozqg@Ck%*l}hJVkzR?5T(_>`f@xPXKm}4l~jy zh`Jr)cuh{vzGlIHJu>8U{7aI=3b#)fAi$4pkXIOQ!pql& z9Dcp#F@6549CXWQd=p0jjTgTlXWVE!?knxu89LD){nXrmvJ9$Doz4w7?60R#f2l}Q zGsYIo#SF#jjY4r%5blFyLdEDjt!}2oFmNq{@5@SCwP z8~7Q7dXutnX|m*xmXJAnYM*L`#cR6)t0n?fi$+N+0cDelU(7jdvH zfwK~4_1Fvn%2lb9PFQ+2f$dWCFG`q^JihTv3hQFJREkm@QjkJM8gnW{{PvX4SxrcM z))Q#699=7JJ9vA5@o-7}M!PGV@!~xNpk^58% z_SH#feTw>TNQRKHzO=eq?ZHCW2%9Ht4A=rkTsG&QTgW}&S1efBG;+w=KK{>=HlUCyBFG)w3eTHETf zI0_TMDIR0RTI&$c&BPDtkQV2iX1j65oB34$(3RHAMHXXQ81|zIR?kP{se?qn95GnZ zfC3{q4?YDhOo$6$njNE(F15Kxrvj=?097+oVp*p=0 zczkuWu)QH`nD!EGr^7>HI~1s(Bi=k*8hUQ*>jgcVF*1((i)~f z)FsDJSA<7?Kfbu5mp2dTSIN$_jh3g{gPhu~{k~(>`d!nko8ZMz5uv0yj~|R*Qm(2C zfse>*+{u(9$<%eM0mRlN6LS=LJk&n9FU6}=mL$qaPn^&_cWn+3ClGwv3bGUZ$am{Q z%7wbi;6Le0HywXCd!fJSb~jqZPFh(UVu(SdOMW{Cqh0=-D)A;?@b=S(D&l$b#>yHV zAsX*O++#fXd1bj(@(nkIz=OUbj~}&^{t9ZZ&Hf0+ZyHbg{%ih?|Cm4384fmIzZjqv zS!4e&PhPWQIu_QXN(HOI7E0F@iDdTKF9cq#LN%xxi&^GyqQZ z=sm-=oUAy7npo1;S6#bX3z`_cI4CuTQaj!pv77Cc{&kGZs$PM2za+Xi}a` zQuK)xzMVNgepi1X&2>jzL&D-NzJWv_8}p6dLQC2kojuyHXsdI)G_Q%%xVL-Co;6#O1W=UX z_ck=S*9%Xv768W{25bpk6wOOv;&Z#e@(S~w+}AVDDc@u-+XM3AN&Ff_St_4MBDk-W zTM6w56AI{Brt$d2*=lPlpEY9CQS8K}k0-HDH$3}3`)A^U=AV@~_Qos?xzz^JaB9a3 zYeL#!#UoW^KIuU`c5MyIPZi(wcQnW(uxjgY%kS=6bR0T~Pc26uKc8^N9)GWSv=?2b z=S-@uUB2+rii?zfWP2owvp%nvF1)tGNZH-j7~wmf@7mgOf8z=ty3Xu0xUOyC;Pl_7 z0sED|*_4_xM(NZzlq`WQ3-u8W5_O;k1gyS2$7^-1V0zBu=WGI)(VBr>I8FVvd7879 zi+CEOeO>GJY(hDU5gb_@C2*LqN?N?SZQK!ng^3x{vgAuJ9+n#gu0}Z&T?)56+D6;Yu{qZW&?D(#t}5{O}xN zeDmhzooSy!w{T(;*@|UAmE$$tP({hfdHc4IL*i~5>pvZ=S1Awb|CdH&m}aFelzbL( z=(0oI$S8jhfdGz@E|vh8TdE`Bv@ly=b6>7h27tF&#s7HOigZqzmwNSjDsh z_L(Bx=hGF7Q=5A>*Pn(4OCu;MR@5ExKYZ5UH(tC)-FkhGWTG6^5BdSs@p6Nu33q%H znY%?;@fwhKediQ3+tk~&TEwIn_pVh&b^ZS5Z5Dqx8Kpwy*BDqSQiHZ$*#I0hSU_Y1 z-tF2%P|>s6Sr}rhE-OvHPYTvIXv6B{dm>e> z$@ujn#C4j!pE1Cf^1u8`&X(~=>Q`xsp-yisIFB(%}9mg|n7vpZ1UF)8>_wI|2 zHsNe56`Q)Fv`|U+iM4P0U=i*s8zzsa zOEDlVdT)+hJf3AKZ;jg$eD(sH3p{?yXS1ZHpNF}h`vWh&LUvYE8FCS*R_ONZFvB19;R2EI( z1j>eHUK)1Ypk4UoKeNAi63wxk^G3?iC!R*gaQ>woDZCp#Ws1Ao-E6lvSr*-U!%DV} zrvPEg)^OL#mC>UJ@;&MiM=g^JajbmJRJUh3<7s&jk(EpG>+B1=4^>z#wk;z{0!P>~ zZF>QAk!D<+C3Rkx!W;=2CY91qa4y2HjQuf&|Ja&aDfjS~RWP@;WtMmh+WOU+7+nif2Ha=b9~M#2b=p59h+#nZIyN z`LfAWC78I1jzQQQA|DR8>W>ISHUX0$y`H0uWrxPfJ&6@!Ly#Yssb5qHoonSm+ze|{ zJ*`$lk#%e@&cQ!BESA@0P*s98>MeYIO&_mMso&X08IBKn3J$rbF8*A8b$#8v6f+;8 zgOMJ%)&lkZ5i2(uEnPyOpI)ngsB>g1CJdo~zaGo7_r-Bo1o83>l#CDu;PPK!t(@R) zvs6E;P+pcKl8v)6(giqH+IMNX8E08%ff?bERD6#W&xPC^o<~KG=9KjdNp`(+QtG;+ zb#$e7>Is2B6Ee#4v1*kDQGj1V`LIHSI^oR#i_L6V@n(=KEfm9(+ZR!#f7^WX;BY3* zP&)Z4k2YcN=p%G?r;C~3=S6a7&`+3PeSbP@|MTEKzT@g&2r-m#))5%#0Le9iqG&T?8bb&Q10F!bcm5?m0yZIO(;{A(9h= z=JqDXIR@fEMR1|Co5W4JUNXZB7+Q~-p7PV!IoQy%ZRY#t>)6tr32xP8qG|z|)#~~z z=~C8Lb~RnObh2%nr0j-ep`ptivJ9FCGJij2_cnNsYSuJm@coL4Wi@99X}1k>)uy_| z`s3LJQl)HySN~=0wnez;+?D5s1^VJoP6-xeM|_FXp+=i3!DTb^$SpHR?EkG7zW#^e zbr@-=?|)Ku@>Dxpf9?g#FjxjC5J>Sgs$6>OtsHC(5w&2=Wu+p;QpX8-PyvMr!K&9Z zdRSp*+9~4u7j#BrifB@``!uh8&nx0w^N{LhQEwCt9fxZIh~TI^m@4om8@M_3-oE{# zi&fMz-sabafakQxPr zYPF>Kbl5kK8gQe4(qKU~PA@@p9i@ z#CGv&q|N?*|4iv4<@2Hi;nW@52Y!aA1BQ;K^7IBC)EdPdX3le37jkXX=rK_1BIKjD z2rQWf_+(DsKU-ztP6$52=b^99dgJG{IIjLyJwT&E(7YcPTVP;9zWO|~??ol^K`x=y zs_Y^`yMu;_7BPoD4m)kv)|@3O=B@!6PbiJg&(=Y;T6H0v732r0P0ws#`He|u(32ME z&A#dr>fwqnlpgCJDZEw;#yxaC!z|0*E=vXVAmEgZlil(cO{Zq{`;V*-L~>jsSN2kA z;-uV)@q1b>&e^MxI!tfZt@e}i3LBUljO|_V@(nM?+sbxN7o^I~kh5*w+}xs9j{JRV zwX#-2jJ4;eURN;}%U)BMsJeFW)~iOU_d1IE zjx4sZ6_c3hs%pmMZ};lw^%y3D;XQGlqc^E6m9Be9>_^Kg8y{VLG7mG6qvFS z&3ju@RPi**N83Sbt!A858y99*r1{4OD&jOk856c5BBJ5evPrY@6Nt7eVt%*jU=nO!fB z!q{H^VZ!HBRDQ>cc( z*}opgFfnsaE{6Qw(0B4l68z~SLjmcd-Gq*^^zCEb**X>J=BHDKkzO@4yz5aCKJuU~ z{rTIoWkFsi%14|Werwbptc$4&iSLQnBYi4$V%jfQ-|A4axA{uUSgLlJekPtiU%`y& z>FJ%(b&)!$G@Fa=urRxRmwJz8_vh=6p?SDO*9nr}?bah$>dW0#Xav;`K`$}g%CDo* zJWbKGd|!;%_2`C`M?lM)3BP7bra{4V(zD4qcs=h*!nd7?L%*G>h!uGhc>qPkh6?_Z z6Lj7^>r(#zrI#Ig{N{1@d>wy?&t&u}>D3DRjnj<-${y_Z;{fcw3%cM4_RvrasR(ch zpY$Zg-|UzlFqn7I4ocwXoa#&L`gRzZF$Gq8DV6O%y%T!U&wr(X(s$l)sH(+!p)AkV zN;Y{nKT> zYsmGLg1Ci(PTa3I6j-6*h7Cp3QZ)BE0&%XQq+!pBUogha7Yk+OP zu269s+4m@X5WR)Em0iW>6&^=LQ*jMS;qw_34_p~8QF9C@M3vI%l+7_SYvt6ezIW{L z5^BGLZY7_s=5bOER~{ts3JAUWkVSKQ&yC{9iJ_9e^@E+5y`TM;wbo0N@VSot}1hpiuQHzK8<@K0CgO=CN;cfJzpyie?D_*T|w0+a>7ex zu?6l$hem&qw-#I7IOf)e@YN|Vc}*4dJCR=VjX@tHlowo%qwso437 ze^;hj0RTDN_lgyN%YB{)BCucB8(k8hd~Q(BpD}~pV~GO7Q@j4@Y)zN6tw}se$G6($ z!#~;RA60VjDXXtceABNAb+AmjL4`pF&UMb|miH8Ad^ySGo!py#AEqdryV#m|SK4R- zQ)z;+4)cW0FB7-arj}ExToPXW-`>}m%l?}spUM2z{{Z&!W_ zDET_<*-Y{T)nf3gW)c;S{wfHiN42lw!GCK*W`qT%>TXVZsXylU!Dsh4T`Ch z^7#`^sB$dCsbC=yK}DZ!BEJwIh($ame19m%A23L|FYm_*L!UgFAjP#zNwV0o-y)?V zD-H|0k60o1a*)s7-QYJg&9jKOX?nRCd&c#*tOK;>NW4xzi+nS(m@$!NXX;~L$J7nq zsR^XI$Sma^TAyWo!HtIWk#u=scU(mqJY3345mF36O^#asYxI}z9%}ua)OfvP zB^X|}&to`y1=^S0KUBEYGM#E3`DYJ$=^N>G#CC7)pu8i`T`SIg>d}v`f1(+XJ!X!3vQ4 z>0S_jj^|1nb6MRh{EWNEE031tyZb|rDV7iXsCMNY3eK)Ghg)UXCo4`g_+EoK9qQp2 zF%N~W<}+6M(ezrZ&)^a)&*+LrpBm7f6n#UzFUGw~Jo#ZJYX)_eMl4>XINPhoR<*qR zT0bAqhxq49=l+38&raW{1uT1Oy9WVR3tpEz@Rn9xv~2)NFdlPJdN`l z3=JAcZ`8itNPc|8)`Qza)_2u|E8|SK&VMKJc!v1;NOiY1bxd7a4O43(HS#sAT)LT| zHa$vAh5FX3iw7*#3~8*$?f+5h@IP&z*ZGMC;mVY02M;wf6e5fdpQoZ|Ed;+1s`A?1 z?`SiJc+BZYoWzdH^6xcvK~x=B0a^*rBqlUv5%(cT4c+3bUJmK8r$jzznbf-k`>_L@ zGZm43Zz7xt##@u3eId-Dev>y~c}eT#D*M8gUXyUi!nL{c*4?T;ylSLs*=|laDNbu% z-K(}u6jfpBV@a2ab{L`dEqY3d!g-Sp@Yb4cLa;JjQ1DNLgo9-_qgs;;3Ay91^mw*8 zOCSu6CO2Bq)uE&GwUI|$1Cm82zL7ymu8bJhlf3U}#*%+@8}lFC(hYF$T)9ve`#|>o zpfex^ykMFsW>H>-d7A*<0_7vS@G}&dRO2ipPV(}dL*Dm-!Jl9R+mZh4vcPQ;UF|wU zQBf|3k5z_xXni8=j==L8PHm$w2Hd?wv*rdKY&CU>9Y$7oa5<0-d{zIF~`T zCN-<$Dqj9rCbjxYX?R2P@M~*cjZwp;5p4vMrDkA7-2HN$4Bj06jn+N3Wk*{mLYGbQ z##&?PZ-?MelSdl|_T#C)YUhE<(YiG7jibs==2w1}zg-Tu(KjF1|G9B-8J_-U z0Qk&^MS!R{HcvRsw~aw)BaEEQf;N`}mGJE`4Cf1f<-eyW`KX>LkLBKS6rxhRUU_+f z@Kk;DM87{S1xXGUutGmv1Xnh>MIJp-?|7Q0OAptQ)$$QGl5M^?8xj^+4#bE_1fkk! zQ#mI)HeEhnjTpNcF$rOOI6?cIJ<~^oCRA^UEb6N{pGeYhqi`rYiXHbu=TUyPn2|SZ zYjP_JWP;U`SmY*v7zL*FZFS2a*yC_tQ%glUMVHC>{fF~Qf*n{{C4G1>l z73cE%-8jq>x6W==1lLY~4)N!%t`YeoEBxBOdIhjm!rM_GTVBam*Lo(#sGSsL8~1)) zDQl}t1`@_CD_FWDZALK?OnYGOK=$aI6{Y)1<+b7C#JKIIlA`#&n{y?w>N?k`nA_QE$_Fr zat8fT?+W+3KPwSuU%6<~Y%K>W@O@lsXXgteR8d)a%#&mIDg4W6JY!Yg_^rJF zZ@(Sh%((Rt-Q5ZdNCb{}<#oBz&|3&GNl( zQDO?_!Q=0CuR8vcu09%R5$aosbBdmSaxo7<_f_F`xlo*h0(jzsmlf57Vj+L*?ZM4s z3;R6#pW76b95k5|dVOiI9T(vob;R)A#Mt+8I88aL686JdYXGb_?bKT_-X2>y2Av5~ z-QbCLZFw2K_6kqyS2-K4AB`Lwj9f7-JjwQ!n*IW229n;hNp`D)S10VLtkYF~71Jq} zW45nn&;NY6v(iVE?92~gUZ}tKC&XH&{71YC6|P!_?LMGD3cMId2OL{{g?B)!jKHQc z_jarwAlGQvvHNJk#~f`SwBVYIA-WUz2CLR1JTEqK-iF&3dIAP_XVy01i&92u*0;SF zXq^-RwbTn`wi+h^=51O{DfTZkjOq<@u1Rn0=xDd*Cc`tORWJF4`Bv$9h6sGI3gQLw z@GE+WD#8M7)#^cOAmfUHJd)lFVhYAs{G9E(D|Q8FzIg}77dP*051L}Nb{Wc>+xvYl zvSl^{z_PkW$ymDuO1+L@n^eKXkBoaY20AqtA;7c^-!%USe7OB@-J^c%i5UxyDJEN1 z?DJXy9=Gsz$&LJ>phtr=3VHN&#o)Y^tRDA;6*uA2C8BeyyXHpVc7)4}rjlW$2X z<-U7!4_af%Kc@<;#OTsdU4zf`$o!xYfU|?q_#KKB$1kb?ykFvV4i#w)E#&NOfWR-+ z$+P8VAOfkrMn4&d8kPYTkcvyMG5{(8Wc z_Y9R<6#U_56Kjyt7T`BVm$L3)Vp|={jv9Dl0pVEpD$!;yDmfDFFaUgA?*4261?D@TaGd`JUI@B#U2|LGq`Uy;5V7AU|W%;PlX3kH6|#tJf(y6QVu z4$;OJu`8M)hviSnoM5COWg$x0rL*siEH=W!cZ`Pzc3 zTB5`qUDBA;aid0YZ_0b)ce&&fqBuRm1oJXBCz>wRtLTyp!`JCx^&~~0f4MtvFe-Ut zBmrShyc<;299}6T$ETBM)CMVog}St`Zwxt-LP*Jf0?$tW-<9jjE0onVy zV@l>M4`!ikWXH~&1P^C4h^9G683#xeQc$>f$%kSnt>WkL5Uk?ES(UMzIX9S;6BH6< zC{nxRgO~%{tUGyJm#ce+G1jo%<`yNkxGDR-QD);PS;f;HuVta;a1X{N_y)^GBF^}i zhr0JDFUma}@d0{mU%XTmvE0%Tbqps2;L_S8Q{b;=_i|{ z_4sWa65^oKOWG;q`DqXJL>iezsg22Xm@MyGZ-`bXiu4pSpZOzXzJ%eQ&hF*A{5i4y zyKxI}nINjhjV;b>&vJU1i|-OBI{M+W45;5^;d7O#uX)5D`>{M>+_zp*a>hrevurA< z^(P$1yA5!cKZi3;w5WSiX{v0JdzRZ({I;ar6(;M0009P&cTs6JtF2HirPsvv(5^itfzj5A9}zJh4yvL5n0Oci znA}gwxNvT;8}jH6RFE&B{U52*eUUBOrpwF933~QLW#9BRo@bi^HibIozPtJbg>P50 zL&|^Jr8MMbTPG3D7iIfQ3;_=ukrlds-SU4b_)AWL+FLA<*D7W+7jmW;rG=Pzp1qZ< zPVb)^on5gY0La-y1?CgwH z2|5-Q*xbwtWkp2qf-W$E0s6R`){PQprwTf!7sDt?9vc`N|7}OP=C!vw_vH6ydkREl zyL7vF)y&7RttQ+!bDZa)XwX*!j@%AnJO0F2eoNRD6y`NFYgOXnN~b4j=yOy1< zav60AYbDEdhJ?cYl$cO-R>D?E&P;0)N;K>VBK^sfQg5?Wn>s&l<7+szfGdqS4`mLi z6KK=KN72W*zFuXio{&C-7dA7wwm=*bbFkLX62LmMqQ_hhKD$zEDPZ_=JbYcNL)mF) z*R3NWYuwK-aDDu?x9F_2lvQy65%v%Q9MC~{zEX`gzZ6(}E~|hujaEE?z2C@ia#w6s4-lbH|G6TPmgG-$STveehh|hs4VO@ zYiICwK=^kms7$(N+u36VFtojoST6n~aL4#1HkD0AyG&XR9W`9bMJnv{hj(|zLD@N) zBJ2Da__YTxk8Z9bl~fq@QvP_XR@y&fe*aSsT=Xar8Ht>Em#wU2RYahcS@D%I?xcN| zQSbyBT5^j>po+NrAkRt|-TDd60vZf3S8jLgUF8UTcH0x};V&AM#oWS6b$P-*@ahL2 zz>s!OA#!h%&?vAv=VC|0Vb*pyf|w7`SBvWsjQLpGjJsvt9?Nhn9SPFiFMaxCE+_XfvaYZ|XpnWF ztk9}RbFV+R&v;3yJ)T8rX5CtkmmdwSb`6K9@KCO*pu$7YF}9k%6tPE{-SzOX+WOl#AkACf#XCkd4AK^*2a0x z8K&i_y`@4i-8Y#0JHghI@#!8RmXA2VIH)qSPM{4wr&4h8b-Uz7+tR1=e>05#RPoVx zP&oJbk0LOMq>E2hQA0d}6ZDcDQ!}j_>P7&C-)p$ZFh0N;4&9CN%ch6tcEV45R7bXy z`UyK&4sr%_Gv(U|9jrGZJ?*?wUqW*4BWblUT0|i|$ePQuZU~9*qv-db>|#CU0lV#m z$n4k#Xm+)+Jtxn|Al^8pL?AmCSi~uBBQb^#YZRf0hCc^OU=mM$>^s#BFzi_&N6hlx z5;kgmJmaC-yVgj)M~P^E>K*&(gx$Upj$iy1ZcB7qLzx8}@AM7Vt#kgUG+*M@zfmVQ zY64_f>}k#*uDm&E|J&r2$5$_gF5)5M(F`kX*>ie5?rz__DZmLx(_Fq!`7T~CIqQ9k z6$vzHoj(oce1{}+2fxx0(W@uuT}0Ve>mhgVq{R=>0e0C zWU4Vl1)vd4i=bCc@sb-XpO=klzhSo4070~ALAP%9pnXPp2Kv-Ob5m0KMl zYjLbn#XkyY9dmcJ$hx#ssL@&xLL7shfGO=1oMvc?C68%}z>z_HMhJ*q!R^e{3V!SM z2bk5`;<`wAp~^-Rn@L<@fgA<&eo=K}TKQEj$rgM?8&9Sz4JSb?zhTZ8?4!9wKa&W9 z8Mzrnr~8qMZw$$Z%1OqzHwiKX<$2Cg_uN3|=X27q{I1Ow{<(CBN zTz1$e>bWr%r&D)IJN@hS|El&Mfcz|t5Iv5kHo8N1d^qno^|@-MHDRd^;J!*7W&M!836t4c;0GRiRy;|*@+h}9{=27>$33iG(p+j* zJI1)-L`7)wh&%k};(a{#$4`mDmGI#yAS#uheI`Bt3 zxQ8QcFMe7XxEV2hwRp$GHg2F%wq_^1W`eq{!SlHW$NqN~TJAWS{VP~eIj*QR=tu(Y z6R>!K@#K=X={gp$FgvfO>}J3AU8lkI#i8@{58!Cu-^tfQb?bR&RXXfv@`p%rlib)O zU%E1d=V%nfVOi_jXdU=kP)XW=fYShx*f16GtX+7`7pHUX(Pms~!MHOkpkK4s*)I3b zeYv}qrT?}o?hRbn2D$r_yyHY3BbE$wJ7#wGW0^sNF+brV04_KD#RbO;7ZRf4X-Ub9 zSQm*facvQt@~O_@8ReT@!(Ig4h*)4&97Y7!>k{7g$gyK1{G?vY%FD>@L3wy4IH;uS zC46F6*4x|=J0z4YH`X8vIyeE1E6k`eSbX|4&l;*YadsQXCATLAzi02EtvqmTd(%BJ za%;c9C3sXT+?Pzg5p@j|0-b*7sj8t7jZzFFIdKbZUduf$_C4N|9?2#^ zAbzI|v1CVW`2oKSF|#ffjm%5y)$`Tp(KAh4pMw}*8j)DVn~P~NaA!7vuN5L$dV;ji z$7qG!ol!GjIm_cm+Xt#&1l~cMOz(%%c(sM~4?>h>1a@>bd1+VKw+s3J(II}fg8&Ay zXgmQtWc$Fj3D8GNZSbw7#evqg>3mnMu>VIIx6Qs>k`qo34w zH{^}bQu%JjE$w?D$9>511ns;A0ofkt&acZQV2PR0G6soh@d&UwvC7j<%PW)PLZbdVYWY(Ife!e>$8iBu<9_T ze$3lNa1d=e9-^Zf1>qu`WE4Qk{tx>cs9blJeUe z)=^ajA^gziW>QfdO!I%kki^}8GmM-V<>7Z>{t+0t$gSn{1=_{)wX8C=Q5n*=AbCy6 zOKc38yN`A4I6T2!Y5`&$)Ak11QfqNMr89F4jsP|ITms&gYoUA6V34^vv>PNL-0K2x zy70@5&T;VrE6o*tn2;Mo0QM)vth&K?Tshi2%8H_yo{2ZkAMHpX@fnzu5(<;06gkKDDzkZ;^U8sg|lM>hrAZL#jA z7q(rl5(s!pOUIv80;)@N@Mz|$$A=zVF;TS+#t}2TpMEspNKtQ|HO+x?8Cp*phz9KlFaJUw!jOtF7|?`M&4hUff3$cF{K@ z>(tCWIQ9h6aK7hu6t>g>@7RuXn5WN04W|zSbq$+N0))=h2ZajCU}&)b$yWl?6oR37 zPh;aj^L{@(FufO>vmqwtM4%OTS_aEWAojkXF~jXnyC9NyF>ktSu_}{6YIDUEu*Xcq zXVdV#UHHPywK&?(L)uHU@7v)ovOMo`X>Zf$3qy`~rxp}Oc2aEzwp8q$`PmmHO$oY! zk~quMtYwyt4a5O6_7f9FT_c<1mX_lou7G!-31bZsEUr>TT@6Pxm^-^*Ck6k+T=?Dp z_^5;M6zLmYU(A4rIql=A8QPg55i zHmI<9VFyJPQG-;8z!`Q7V=WuT!S7Z0JDuhdGHZplv_9?Ay1CnIWynPP%ZlUtEe$}Z zsLf?5WISK_xArd<-uCK`jzJ-p?1xzaugI|Dov<))-f{K;ir(9ZYL}wz$)3)l3Ve+k zPic9Pjjym6X6hKl#q*jMU82v-H|c0G@va0LL5>_ty`tS!04 z_y#gKctRCj4kZ`=oGH(jc=WH;UPaUc=q+zOGmkw{v=Y4Kj_@lOU7EV8Isb{1UgTc4sHBNO;>fSim-x?Tlz&d}E$NsIq!)Vyw0|MyG370DeF-QG3dB9iYg zKOw3+k?o_tXldRO=DGdE?6VS=i(R8%9j9{3qggVAz|3*_hz)yWNtEIXKS0_>^{$B| zlCVvcO<(JW$aAAx!{t@XaAkvoa&Q_CDzHg$o`VS-MS zk=(9dB@6nQ2sz=d7kKkd>N4c~(w_N62BCsqlDHF4~C z8nK$U>gT<&mbIYFUy7qttPU}w)jqrXoWd#^J`GZPA@aORBN9qEpfhBiB)=76aBn|2 zy#>W-Md8a0QkdQ zQ3!QUuwc8>I8iUnlDw&u-wwR zH58u3ac$%5;vVZad$pt5i0Ni_tLTNL9I57@0YHEqbIh-%SV%2|626IQy@dxzaOfoLlP{{(sI27aw1h(xf|cjcMZlNuDRU!5@=@@1 zc|y5w`Hiq&ya(J6p~(n_+~txR&V*+lecCRmL|CtBWU5_h{0Pg3#_*z4P*BbXwvAKhMY#tKhF7p|90v=QBz4U>Crjl1_Bc@2KKjQ*hU3{B|KlE{a zaYKn*8z#GXR7pYUsmiB|g;%3@Uu=B3^w96KWV?dT)$goP&9hMjQQ8}KoMW;#VE)lP ztCY#{zh9mW*WejGbd5*gcoX0hzigkG7my+dO^N5rzb7PZH3%Gner7G(fzKb5(TL-6 zQe7E|2pn&EY{q2|YqfWl9>=Rf?9)u@yH6}$ZOC3IRn<=YCxeXqPX=T`tGrB*zR^6D=Y@&BZ~==O=~vZTHW2@m9)dGJez9o+9jN@a#rh>OwrDM z$^qGsfmeY_U3+QvRs4tsu!tK(;AD}L>->ED)|?rTqlFx7{)n%evb%?AJ@-`MMdO4t z>!fuXFXX}?3s4Fgh)Une3r!2*?;drg0pin3f6Pr=gd{Tvwo4lwJC|o?-57`OcD&>}~qWhdmF&tZ9NcHU1QuN}~ zAT5yYIfeDlm?cU3h*i$zNEk}Dq-3@tr$indXgxSH^kbG$+sis1>dw5-fl$@{1PHHi zW43b7e11%&p2wfx2P|5Tvm5ZFLkF-HwaoD(8R7?8DC_xL7(U9-r_z4 zSW5R+mn;WmoGzBk<)_U6-leeBPtr-JD>fQoKV#BsS+N?BjV;#S;y-G@GkT4HDH!(E8rD=+$;|zU^`7pWz()rTI@1y+i#kni~-bI6RTjGvW(6bc09-G`8?Qnh_McybY>u5$f3Pu5-n7%V2vCIeF7RN>+2Q$`vyPKd>}U~gQ1Hz(}m4z5IoT8@6+-Pd$$R=XVHftY|$6AtDV;H2t_wlPCM7+m(|KSL+s|IQ}^ z-+Ra!r3S^_e8u({CZ*=U7^T_B32#%p4&dMDi zDiQBd>XE3uOk6Iyh?-AI^}!GsjJZ&yhn+1_XZU;uxbsy{TSX^}Kw=huXKJ*$cbuGj z`*gpYc1t@Elp#iFufIEln=u$@-yWI~vC^C3sN`@9_IR3EQ6fALZlGaR4N`qmA#j7` z&Yv#E;mv;qRlmn5NFtup_dZDyRyH1 zqBVq)jA@`}rGmQ7cnSKKQtize^CHtl|NQ1*=zl<6gNU;$n{#oo33Q{ml#XKOG8UTJ zb-yMZDCba%aMhycsSXUxFTd?}FaZ?Mc}mC5(Y!=b2C|4)1N0@h)V z0h!DXEw)l9-rN{@XK&`~f{UctFGmoi#grC9G#9Eg736%4@XuW*)ccx)A_$+q?yiNu^8w&Jz^&$t|Q1r}&`R zG)j69Z1jsbQygd&Hnv&KyZSW%^n^Sj%_Mf1;I$ZwHUqEv9TiWsQO9WxgtGi0p39eb z@Nb%xL*Wj|Gwi28a5*Bp;|gsd>_WpFK)2?Kk7BXwt$xgM)KQdpWD@i0Ro@lX?7CUb z-GSs`^ew7JN?+66S(3^{q1|Lz6?}REAL9~hS&+5bw22=@$VD~YjEjsATU)x+qU*C8 zgbIXe$8##oEHbLfbkH|#9oHt|vF#whI_?)Gx&#baoB-~?$ zQE!nF@&-N@G%jl`)3Z{Oc-9|2KZq3kMY$m;kl0%*?(6M6t}IwB1Q5@=(JDR65mLiZ zyVi=?d>hyX5!u?MS|IB9(4^_5fV!aFQFvD^1=E6>0*95@zJzQWFHzLK!Y3V(oHhE< zrn6VjM%(;9y52k->i7E}FRe;KCA$!X5EHUjwz5{X7(<1z4q3)Nw4y8{`>qIC2g3|A zj7s)>9b*h4>zF~7!5Dt7SIhfzUEk|Bf8GDgACKp`&*Pl?oO9og=l!k^hjgJ5XONrD z7izqwTXNs6=^R55I&RnqS}vfNg*#{aP8h4{Ob8`~AQXqiju2a-lYWdx{h#=A@1KCf z!8Fl2lj~_Q^P|@%Q7PF+F}WWXetI>@$Zk~0v+=W!`aN*EAnc);q`)kvX;^e*Z@Cu9t zh?!hql+K}WwXV!;w{~r068vUJiCi*gfaRy03$9#zL&j(NSjeUzhcsvN>swg zWsIb0^btBAF=aSwSN#7kWgZIX;${TeN`WnEkW?&WEb-9z@Eyj9vDY0bOt>E?Ze5Xv zAJ9X;xVSdC=b3qb46dl;aM2;pAD=6dsWE_AYFvNG=Wb4<*DjjlM5uxuE5wHE#7^(?7m#_jp`i?8Fj{XC2igow4+9RkgZ5_O#gBg4I^`p z-aTx2^y#`dtEpm4#3(2G#H@1wt#{%lrFP+48w^%*>qFP(K9Y8YP$_jUO+d_x>r7S3 zQsvhtv33y=d?&-dXm>x4KXjYp@}t8g&)vu|rdi7=W@ zMwH(egKjfs2gdfgTzo!vB_~iZ=?P#yr{&q0BGf~tnzmGwZj}6ijA$|34)A(?hCBPI zn)^!@moz#T0zf13NxR&6ZoA%Zvc~w)Ha)q!*>0 zvo=vIX|uMFsXG&Q5ZgqbH{HM+1AK)O3InXn;i};pi$LVCw#cW=LV?W_a6QaC+_k|pZ^xm zjVEW03g%o-zPjY*JpluCd{U(UFW6ZK5?M;AuKVN~QB~h=#?0-aKgjj%gKza9?}+8}z87DvmLLD|0U9gofy zUwW~KND}wr{}0|F9Oqx4J(mWG^oJdiiY&x@%b2q)(RMrDiuao9e@>BndW$4T1tl5= zfeu4yYB@7MV4JI#0YjkI)YjmM0cVI&5GV&Xnj9A>DXyhgP;oUSWWhS8 zOvC6G5--6{4J_0c_Z>KT$T7_lhGtDi^(Mq>ImYO7T#FNypUsN<}5tc0#Ek#)Xyt}m4 zS+!k+t2B9>a)aYTvghvQNfd0<#Zl>)e%Y$6M*y`LePL3^npUd}dnpsD)Yt7;TT_H3 z&a|J>OUBtlBE9NE@4Ta>zf8`Mk9XV1o8H*P<8dBiGgdlDYP{9}?niYCkv@7mH{dWo z_i;M~;v7)POBSjV9yeyUTTgA{(>=3z-#G+jqPH55ZA(hoSWhHkFyM#1bDquSAO3Qd z@LyLx;H;kl6%ZiPM&EEr<-<}1D0q=0PawP@qaTWH=o6r^y$7Ra0`am^M6|(px%Yu` zltI@|`S*5Z|BxW+Hpem`)T*; zTsq@j0+;n(L1Y=LeN6quw=%&tX_uxvk_sp?+Uf-t;NnG+jWAwhJ8M~PJ&9T&BXLQH zo(t*yz9R7*n+;NN?E zm*^Ejd6r;?3ta5$^@KJSqK@ND=Qp!l>^jp;Y3aq8Hq%awAbDvr_9fR6OVQ_C{LPY8 zej2>$$+feSz7JvLxY?RM6V3Bmd$3l6>d|>wl{i zOE(T$n?6UGHaz#}Q_;HF2OAb}aXjN@Q7qCRv&QWt`zs8piniWAp)Lq_>XXdN|Ji9M zn%bo$5tL||{qZUA%By7AHq&YM*`-@~+WO6Y5gUfg+~S#QvDX{gVsS4|tItB&otLIZ z;C%_=7J@^29ADMfvNW3ujxd?0dyh@k>FV7fb2(%iSZGg}K~9|C(k*tx8;!lQE_NL` z%uZB?6xjQ_9&zFKU&tT3sz}SvgsnbUtuaBJjKsHu8@{dYN$Ne!YcU+SX?#SrDsj#7 z{G0uhrzE?q5&aXLMlNbNAj9(c?=buYf8;M_=bF}T&JURkjQyxx8%4Re$+j%rdM>Ta z=cl*JI^_64mgOp?a+Sg^3rhVd5k)p-FJE{t^hRcZSD4jIN5>~1m0eXXtScsX?0m1u z!82fW5tfNn!lu!Q1D>BU@@ckq}1V0=sZFg^t`CWT0)Q z-85~|acS;;huOGIWPt;54OxKn%H6=MZ$58d)R)1{UU-NM^_0MIJ(r?wl7wEdSm(d$ z{gSx5^brSp`uht^Djxs)1(<&-&s8|&s`oiJyJjwOyeImQgqeWfQd92^AEf6yUFh%T zf;0ImlHw&Tt+ZN)c9L4WA{u?GiX+<6f>{f)C3d5@v(sf9b@r`5?(Jd1yzI~2t0K)m z6yBM%@%9UyZaa?Vz$d;4O>UN^JEjhEz?kQHS)c?D;m>Np?nnVN7flb5UIytywG1cK zfsrJza^n{#M~Cl@N4(Oz>`d4uQr0Z=9Y)I3H|4u4O+aMEE}Ia4F(7e)@({j`+wmJP z&(u->nUZQKknh^w5>>;+q;c8l1M&K+rx;s0|Eb?TZF~5r^6%Y#WfJqbDu=t0Oe;^3 zeyRk`j=UD*m8&ooOb6+2Cll%@Sr%bXez801p{R?4V(9{0z9KtG*9HwH;>ZL$5XRvh2GK9J03+ypDQOAE{^ ztPU;l$a;uULqqfFORkxM82ejMP%4_RLpindNClzuc9O(&cu8kBEcLkR7JHQt9d4X{ zF`uf0#D1m6M$yhP^Kc0h3vOsI-R#tP+_*&rq&z+qocSb&NTrAR4gAo5esrAgKYWv} zul}ag*L=Cv7_LaUUe~ncxqZlhhoiaYJ1xU@^B>8WzFcI#B=M$IM*g$vlz|sSw(=)- zI({^w^k$*@8^26B{7|=esZ5)o$SXCi6x`Z7Z;1`LN>ZOH{VG1$-j`T#8_&AnpPz}l z@NxPe-rSonL8Ni^Qdsz`hbBr(+g&TVm0BC#*>xzUyG)U{gVprz zt&RoRtO}U<#mX+2noiiJi>Xbmcnuvfo=-=Rn|fuQAkqoApow|KHfubIX2PeI~#i61=oVa&($_G*`| zMv)rbXO-t!FIDlUiG7WcN9^tMelJz&qI4JKy^b4x>4ptSQVK-mqHZmUG{(`^hb|l% zq--xg>+PH7RQOaoelBo1b!1=7>BCE51Na7e?|lM8?8U`!KH3A53IE@iSB7qV_|4qG z9GQmv1$@NURl54$g;Wjk6`Q`F`*7tnv~I>m(|aeCI1h{F5|1fs07~V}%_Zq`Ai$9E zz2(N_{O;w>HS4vVga~!}ZI_N*?M1AoS+bSf=1Ri>>AlaiC4cK#==RRI1DGiFH3u@H zq(8d_b3bNByX)R~4M~%CyX%v8Iyh=`o{6c31*B0R~dZyk>di>RcdULWt~M2+>dLVp+5)(ll-1(wj7Ikx9jHZxMXp; zndKJqfXzsq%acDyH~xpT>}40k{>JhhnQP6Wb;lv5$@|3RqSS{ zm8C#4er>I~G<2BGmOAQ7?{pruSS>Qdc;Lr7V>=h+!<1pW%Co)6 z>@$Sv)$-1#Jrq9(pw`_&#+Z3j&nh7V+^!$whP_y|4rz4q2B}1z!i+Sz4`GiFwx|m- zRGQo6@I=v=91kwM?{;)~4EFH*6Lz{_p$M1$@aXGtDYT3XFG&w)bdL9hBxxaDWVU7 z_pRE7t3vGfXNz1h{SULJmNxVw?nj*;8P}@?)&{hP zzenS@m4om7%b;JD#MiaW!iszo{rhzKA3hD@2Q)2G$7ctpq!dLhN2)}n2r8!)w2o87 zOq-m|KbW8=R=paB#s|Yh=4cW@@(NmYb5uM^*VKEnWHz-)%AqX8IqX^VvTO^c{qc4c zK$CGQ>=DyoU^F!Ojx}Jyo25bv!;-kcgCHf^!pw15`m|He5G_#8==H zx-lM{sqs=Dg+qADPkwWEQAzUslK01F|A+P#i>%U_ZQaqj^|Zt$O8CLdXyST`A+bbj z?q)EvuHjJyr7p=rYh*2u#g=KLsr#M1L2AvtMeNbh5d)Y%S|~ci=!A4x6|X5_1bAY7 z1T^N6x~r?wd9C24u~6FFAch1~QZwAU=9qo>3)-r(EMZ>>1{3`Fg3VpZDYsdzl7WzM z!IV~(x=O66U25F1!mtjWik*Lc$hi{RwK0ixTvJ~}IfZRx$lqe((n%H0(6myXV*Y6r z^#ZEo3r-@=hug?#?C>b0`K+dB(4Hr{UiHcJ3N>7{LGt{3v|SByWSgHO^M%8h57U-U z!+u+O3-ZsOnMC{SyMOHh2b6UsYE7P(oxytw>en=-f{NdEiJvezggOuRY7XdsmXJH@ z^cIAwkW7h_ac>wkw{HLDn@=Cys92xp`N&c4XHU4U=yTOnNy%mNZkh>`F#6-BCtr#{WB~ z)_uE>W5w34dA3vg?+*);)ze8Et2Z~;>@AlCg#Un+y8V}~kB97CQ!~dI%0bU6WrpiS z_KV6iy|Um8jI=Ktn9(=zTL7vcyt;S%8k93JS)T108X?$|P+leUK=o7Sd{HCH^2C(r zlj_XXl#9zO>MPhE%bjyB$ZX5S;hYJ(1{{MMSB>{J_*FhKDh5k@enPE4f(trR0l5C- z;AyTXoHKXDMR~dDxm9$|&Jz?OIm=`UJ0?-h@?|PF|Ha)WWw*IAwL;vS=aa3tqT*E`_h#C}#4T!hk zCb}#YKkd54`Cu0eEJaYoD#xrIc8k^fOo^+(=nyF%O}Q8;{AbR?<4qmM@t-#0G7d%_ zXJ0Ivp!_VQx314*bB>}m8-H${N7(Ib?W${pMUjYEhfk>Cgpk4` z)NWVo+gOht5~IwMC(dR$ehdt1rdHw^?q}KCp=xdkSj-c4sje6z6|MoUD1f0O?S*qZu0G*MdT3vRHY({!s_eg!9W@#OQB(T0bLy2~Y1JR4=_I*;H{;o>gym zRl|nT`X};RH~p@tV!9Ay&{zJDs@yEM zedFZt8r;@bK6f&GK z2JKWiA^A^v=Q-j8)9;GrB;cyh=gNMArZrcqO%8G;aDJo8p#V(B;C)ubHzd4OU0G9O zV6IP{n#_J0CY8|kG&j>X<+XoF@5!qGFINn17v&g_duNP!T0ra)}jJ_6Xf{_&N#PJ$Jiq#&E zZm0>|L-w59v0%tjko2dl`E<=lEWBnVT~JPO&$34uYRU7#RBVHm*9U;#3Y{%6$ZGN=B+jOVf(^NmkfG&u%;wKyWqO9~F0EQeS< zYx6f#lCo?z@!es2gOeB1$+b9M=5eOX8DqxP9!MxgNTe5sEJuy&-AeN8IP_Ar8Oo=J z>d~1HTMLBW6EG!1C$x{g9tMD@;hTBiAv9R}jo>qxc<8AC*C$Y%$F#{@S`u*Vx;pG?yAE>@aIcW%#Faj_uP zS4`G1yhhfGf`obUPW9D^mk%#**{QBPX<4(S)pxlb|GjfR3l@*fbXy6^6t`S3mGgb3$*gFIHm+9A{L<>kWH#6InXHCh9 zJAv^T?)1UM3Ikl(8~1cReu@!yS_?ruq9u?d8FxwR8!K9xa{sLjfh4q{H|!ZgaqSxj zggbw=ctahE<&M2Sjfp9ae>#35B<9|MJV?EBUoC53+2JgQg}@C$!~0`40Kq|$3~fp* zf_8}o-5#6FH0L;eqHM0^h$~@xsHQjNg}BY9Tq3G2)rsDyE$6= zLS&!i`_wi*M3&kg<<0e-9`DhM9xiHF9aaqm# zZF=XH)EBhyMo3&VlwqD782ob^?M_Z%wHeKS`2Thu9^22RMLQRGAgv~*JpjdK?Jccr zJ=azup74~$u%$lYUUiQ%3$plFb@$}!@BLW7rokrbeXeiB z9+657>cRC9cuU*3g|jgP!Lo)k!h8P&er_}r96l8Pmv`m=r4&rbCh=~=de!n3gT6BC zYa#$|58w2JWr=S=jv>zcJULFe_zOMPtRPA4UMjd|KY;U<5ZmF9K|NPMu$cocf+p_~zto7;4id#98-`npf$Q=N>`9uClXkx#VN7&* znW#AG0*Da0JSi;i9$jcNFobfm6L8E7hGe>xy*R1HNu!w~ylquLG1${5BT7G9ZLn?7 zjN#Y5Mu6BQJ!gk`s(YYKxSY=Jr1l?~t4^7w4t1*%Lm1} z*X((P=d1{y`9j)kl(z$FyIp`9oT<0ssMiTd;pc9fxgx0_(%ys=BKsND3V>|&?Mc=z^O9;r0yTqp+xH z`C0L=c5Vo}nO%%W`zZE|iM4G(xf;)qe4AgbMb4`WE*?J3!Tf?^UwOTi8JImG(76X? zfQzP^zWx&;>cCOkUG5cTgkVxZCyH7Ono)8@#W%~g+qWRsaObtXActWr0Ej$BXsPk^13w;); zye7$AB#8W|5KOuL={?5~h26wQ|A^H$_XE-5ga?SS(#)Ld0$%j{d!|-4#m@TVY93Ov&Xrg+=Bc@}?$=)%W z>+*Z>QmSPl-cZuDx+Q=De;!t<26LnBw@M@QkZSx_;~=ODBVHGi@~{R5<>`PuKtTdVNkU#We{>OG=I|CCp+^vha4;xN^9HuM4`qM#P)p z9A_bJaY{`%4=A2zEc`8wC&9)PP(&9w=GLw$K5rBVj`XARNNJ#TA`*NSl4+*X2k$>V z{(8T_WXZ1&W~$9{_Z+TmS}Bc?#+g%X9u(bh^wHo4?9o%N*Fi1KWFBn+ksPI`H*y!L zS=3i*@IsUzxi_+rbvdZ1^k-F@wepZ;>>;U4L@@zRkVJQ81GHO!jlKx zw<&VkG_$1}<+AJUsO<-gMd*PP&hS<7(aa=gO6jW$K73NMG;0eRjEgcUggPJfi*GX^ z`WxmNV)+63p<_r;&MK3{{? zvhBZ~kD%-%n>Jv^T@&CNAJ#r?tO=RC2={PkR}%M!PAwJ7h-p^8(K418P6B6GVr1hCalZPL!?+iYsnUxr(^pE3Q1_RB@4zbwqW&eJ-v7ZM!77bzvOGiojefvperN^u|{ zg6JG62TzCS^sWQV`%ppk^Pb?~7O~}EvaWJNg?+UVoW%KXaYOlv?>!!KhSUk}%!T5Z z2OS#K&s@5$-Yzw9gilYD9&z`IsRB0n>W_QKZLs^!j}We_&?j}9QTQ30eX$WGBy;OY z8BIIe*)9rsc)^Xd6fH5~o-VojxP)Bajev~XrT+pRVV5h$673`(|ESoz2k9`%mg*>W z_NpT)HDNbzd1$Gq)Mi&wzt$+}E=Rg)I;CqK(cYki4T;qOp1R)z{D*Dt!_&WDiX?-&Qxc`2T8whiThE^O;Rj~Siz=y zj?!8W;VH%Sk}CChNt$KyNrRpRtYN-Y4>+OI?4#SX-<7bQ!rE#4XelJ=uo9rST8HXgJjyHcuxNJKR-*Rf{s`E9D zdgYHaSH0CAdkm;Yc-vM-4q^_H+Vkxu z`zEIMpf|H2$#l=4O*@Yzv$v|K2H&pVxF^y7nq$nSNj_knWPi%N@{X@+TAzmq;8b;B z>NmS=!OGg#nMIiM0mFBermEFH6!$%DQ&R$ zp{iB6El?q#7?}LpNJ;6}i$;{PiPvZ|Mo+pSFSDMtCaO?sm1=H|d*j;S<%yD03qqT= zO2w_tqCt?AJcb1&#-Lg-mGbsuf3#v{w|#H79Ia^a(-@PSXPA zI#CK+QO*7xt-C0)K6y#PN^jZV$bi`=X!0kuoP(-P^ZlYgB2JUD`n+kQL0ueJ>@Ue_qppnm?Zc; z;AX!M-1$E5w)BYqbBKD*%;rKmP)wig4g<-3;~AP7q&JK0T=lHzXIst{ z%w)+%(Mk2A0`W<>oogK1&lVQGlg0WAF8#cOd@?0}Ql!Oion~?1%cq1tFN-11xV>N- z##e+mO}5#kGff0q&sLt4>lWJJQw;yp5xn@nQ*BM#!+uU+n9FE$(o$i!_90+om!WfZ zYH?pn!3RUaeA*ex!|Y`_6_=pXxNDkP`$@HRv{HTtYjPU>{MSqvuhd;XPgN8|D>;|2 zmdO%)WfG(n>L^n1ec7|8x)s8_jrN z0Jay8B(7_(i5Z)H8p4a-0}^)F5^AM7nA=>;Xel|!?qp%phrVDBW5+C$m=+awaR&E5 zEs*vA;BL%K8EPg7NNKfqhK^e{5^x+{xe(c(A$$^~B8aFj6yur7ggd3y{Pdk`^rZ-e zR&*SyrvlOmIXRhB_231oH)YHD6=HR}+##cB76|E(AB8R@a8fI~=0=7+@!gn=+L)k_ zvmL7up2nj!*||I86>L)Z$S7HX(S023ie`S~{5UH&tc~&>+H%vsS#Vx{0X2_Inowc= zLMHT6{!rKd$(Gfm{Pz@8u2q5qlP67TU45@~`sJ3s?M*yfyznFaa;ZFi;7QVoHOAl7 zF>*V$b8MVfWX<>Z@$cp_7O#+f>f~+KnLD}r4p)K`^SG&av|*0!+`6r1{I3x6^<4(n zH*?@k>8ZZ%_u~8_IvfGt2xNrI~L5%IyAFu|z8w-3xH4tSnhC@sqQLOzF zp(Z8&<(D_KqO4ei3cM;9o9COPnC#pRWOilP7o<$=I+&6M%y!KNB%*y!S?{l834?yx zI*g(^GN|(3+jRLXNsJ0Pukf4Z_h4C$VlRiZvhv+f)CMC#sxYXY=@_Q&fkUTk&}#2- zgL@%wLGea1Pl}G@Xy82qWVHCU3De07HxY;5jqFr6@BTtVd{quJo`8DIW_7hy?@~l^ z52l$KtS=+s^ghb!qp!@=X&&FJjf;(#iI%3NVKZ(4F?{avC)M-HJ0NpfMOKi*OOF}x zk39udwp3)fz%=Gu4vo+?@`%#Yxm~?2)FIKz`+IvI!U_Csff|1UoZb=byBy?8F>{t| zH|Q&hh`x&l`RTO0X7-a z#iVF1^V&_sRKb!>X!8yQ9|k%Mv^lHRU)2rS(i?86L!}ua^qK4x0*A95hIl5&UmP0Z zcD71VTn=F0P@I0KJ5$X&*UqSm^a4_TtrqVv(z-$TY`m}t9hyn|1Q?+2ojilOu99T% zCo&<9{Ut7w6(Oe~v$H~u3ii<19E{$Y>dmJo@0xrpNo@}|*bpB)(Ba$*w#Vnkn!eAx zQ>zu?HqCDYmWup|WHD&WWd_HYEmpE_Sc#VB1E2 zY6fCbzVdbi`}h2s_C%Hv3QR&F0QNbs$Z2I!gg-5JTts|p7AvM$JaX-}nq<~P1wgiL zz2xKD4+CjndqGoWS9z$R)@$-QO#-CJL*)>T>RXKxMH>`~>WUrKzxb+p?9KP;& zR5Js8%draIVer44r6IURiomEu6XlPMy+y2m3i@Q23?sBh^KDAO$>d;ad@K|cF*KubYN@a z5|F!PY?MxEPHgT)OF=~RIyF^=`WSj4Gdka1|gr5^FM}h+L;LWU-w#*%V zc$4CeWwTi-%^@P_GS(`f|*c+x8eIv!Xlkvle*?*G{hVC#{G{K&Hj~d zj;BAv;UX_ps}z=gGL7% z(DX{ z))~>RG z8Il=v7AptT?$0m3aOM$5V8jFVZt)%yqebNbQC;m(XP}S7uWKIm{llBm6_;xYtExG( zfZEE{Te5&!W9|vdHlWf+_9N1%KPGl?YHmrb}wK0j8$vMT>Yo7T#ibznZ6_Jcki3b zM=Ig3ZMYh4lYtxhL}7k@RRo^E$R}H1he^8voy`| zRgl2KYhsbCJTdcglswUvLi%o3N67wVI*7X2InM$)_tpx6*{e>d7P{qKcPHnZQQySj zW4Ik3mb8f3Cq`yq;`yq;dJFAY<@w=_@1Wy2!h273_va)zgj^9bT$g!OVZbZw-8@t# z#`5T8wOtmD6}t#36Z7Wtu-5&DTtPM(L));1!9;{+2HF@ayOk%u(p=~f?*t#6@U z84+|MYwAYnL}k24v6aLrqSQye%U(8sg_)}ab!6g12edk6XwuRT+MQQ&9uB70O)lI) zM9rleOq^6w2n*(CSX$2GGDD8ay`D&x$x+QACOhyA6o&hhrke_W)Rb*!akfYqyXSlH z{f~zeHx*2u&{k2=w(r(z2-F|2EW;OWy1lvrb|OZX&X(q^hx7(XV_;>9t8R%Ij!5G` z+iqYhHCf})^fkM!x`wh4KP+v!1@96V6+=IeEc?$FC(-|=;J8^VuicStPEy|$KcqiK zNO-diP-sMNMx5p(%t?(kb{qVl&_F0R_kdG(5}WcY^app$!w3wPIUA0fck;t*(0@Hu0GWuO(I_@ccgT@S1=2ukC z4<)!ht>zT+GHxs23rIX@|Epnvrp_rWOjKv!5qf6_;bsnUsIim-!jx_k6Obn6;tO2yFy z6&Id$jgt#c^`c@L5(L~IqzY5Dabsrd6a1x%&sMt2ij++P`D9Za;ikyQU^FTg$ zj)CojA=zzWEPwgMgE$vJiv_y40DwXdqJ&?W-x7H8@0vql7{CHLL z`RL-AAoUiAfap8##jQG=QqdDNFkl+1+n^QLMlYsp6D}6Nx>t##X22obhboP`5R`do zirv)omMmM`P!_&A>E!2%(}f*nL8|Uqw!b0&pP`x~7Xv_dJnnr>NE4GDv*O!)ADPl1 zIc@gF=TviS{Iw?MecpkViMv)87-uNRd9RIP3K3xwNP9 zS%Ew2B{Isdf;PlkJey^zoVu!~q0#7A_4Jm%!va%&KB7gU`4rA7*f#I`%J)Umr z7<83=nK5RzTo2iYC@^d+oKAR9P2%U8$PYU|Jb!n-kG|bi^XCAYeE45s${$=;RAv4) ztA!v|4bZn>bqP>;Goh~%rfe)*k zbOAGvw_cN%F$TaGhMVsXHJ3_D*`1rBv)N?H%YU|3Ozd3iC&>1F8JQU9vPFO6=DKef z>$x*hX6g1zT|0o}T45PP)G7;p+oCyI^a?QJ=_C;J-8n&G7m=mwqU;gCP(5jkKpw|ldseN4gXv>rG7CU2;N2x1xBkD^9fhmBh0N<*!= z`(%*~r3`n+TV(B(#$w}#Wnh@{3Rxm-a3cbjF&yrj?~mSaiL3(VFh4BUJ?6MBKS*G! z%A^~9d~s2lfd>?IxoYasu#ewK+la94sN>2&YU;KOZD4+p zydE3(Gl&^h+x$y)0alNQFQb_!Ua+Fx$*NZ=-el;-a?}9JBccw@=3VXv%9zp%VTySOV zr}HhfQh+IWV35QU0#5E*klO0lxO@sdLL-GyD%8#I-|~C>TJ~-jhJL=UM@>*d&0;%oJL5JhImo|b zFYRj(oGn%%X7cU46ji-l9`YWum9QbpPiGtMBlL;@M*|lbp5-Bkpa+V6&vYFv=@d#| z!S@Q}5rDbxHs;*ZV-c@eBab`$+#K~Q6+uYjk{x@_Z5|5y{P;Xc-F{1CiGi691l?g` zugru)jdiOf9S>bsBuc{*Blf9R|CE+JnE&P#=W06YU>uq$fd~=YTeCzDgt2SDh^Xz9 z^sg@{)MzZPj3V-he!O(JpCK7`>U%2T8i%~qEn_^tH*r`Mnn3WefT!F+#*ju$-|**x zdEQ+*la_WfrycU1NVjne0AC~8q`g+IGQ}@UhF_j&{?H*gElKfwKjF#(60J!!(%h?v zdiK_e9aX_Im1NoLy+Y=PHii0}qw?yvqZ>tGq1=WT+^%|@RK zr^6qFTb>A-=c1w$IP2fAwlcu@hlgd;Mr;=Y=0CjUdjOv{zgZ^vdq)SW{hRuG-aaEf z%Bg>CxnI^)4~%lVSMT{a(M}lTS07TETWU$Bp^OS*8r1CNf39|xUnryqUqLtzLR{C* zzZXq|wKp>A^j?;AGD>?|@So%5u3$1969!csmZY1Z{5wh%I+tu}fBp1Xg~JU>kJNVA zhrXpk1@q#&F0)MD4Ma(`3ZoXL>n;423pX6%=vHUP-1DF|eQM>8m)knE8Z;gj7>EAy zS9P&9%yj43XZJ48T|;UjJUZzu67fOVvl?zkova;gXG~YV)-5!Ci*ZD~8^8)RcYSni zn$vE-^yY!}-B6@esABhT%qzfuC5ofIFBapNsT1cMM0tSk!C@YISFZ?a=Aw4^Du=Xh z6`xma@;$XubR%7;DI}PVKq8YPg4=(#wC}K{r}h$x9??Gq8-{K66)39r%>^jv-u=F} z_CZuzL`O|FG7d?RXP{EclEw**+$)d!ASESaADXg{qN`10y+G=i#q}3>oGUzXvh;ZO z=BOG!i!7?s?#4>ayG{4_O~O*^FZZ`&o1q9a5;y0#S&gjH+!=#dDTX92qnH<24t=g* zC4hkqH%>Ov$2$*2V@27h0t1ZN&vw;aq=JM^-7idKf9BAQkN+(nJC-~2*>HbWyz{`J zJbSzEN$I|XiISDS#bHr4m1_F4-T&fX!v)>Uz8J-a_m=$*-YOXcgaG9l8HdqPFy}N62p7TUxDZ6$-fFjZMRx^z>6S zX=Kav^z8A$RPOOE-1X%ha!5oAk0g06f3tLRCKepz=Hbz#)|xi=1NQYPpPJm*#B}&P z-Z#qYQ^){h&Gfg4x1Rnx|Ga6unZ@K!w;V7j_AFi+!?V-c5Y=6doX_6YKY`@o$YXG+ zAoHf#`#b4uL(l^mZZg>qRcv1dv77>noU;O8i(zGQYB35RN_lAzGGlN@ysqJjw*GmK z7E`vyogPTcfGgP!h3zotqc)Z;OEc;!6;4~lsiA}Ct;V3O9FuU?yDQ$$OAe+fpi$bS zv(p*LZn(ul_0F6{E4V|;G*!LczK-hIR@39Ha$W1lDP^`h1yctztCyQU&~!PkLCZeG zNVLujQ#`39P!&4q4C<6vtgllCcB2wx$3|uPGu$|-|BtL$l1#B39A!P}%M}HeJW_is zefYdWm}^IFfR<)}%sc0E)F6TG2ocBGB@xy(bt3Qd>mQ94)6~&StVcoLI8nX3O1yD- zcRKDPVV2#xylrmo0i3OZ$7I|#H_zhs>xK3moEFkt5aMI!`-xPlfAO2n;@aI;HiRA5 zpzr3fv8lV_U{_K=*OCo>aa3lF`}2$LiI$CluigvebcNIyAgc5wEBN|LcsZN62g_XD zq(mRQy0zs6@FF_sD~)iTdNYe$j%{Tj<}ePeBXeuJH4{mq3N zW1LEc7|Tb-UIzoT2OVq{bF|^t?W1Cha!;4g35fqzEveH-d2jXnLWL}1-M8icZER)? zyw?YpMGT)0txl>rBL!?It@Lt;y!lO^u$`d;eEkWp)72TB%D{9lEZOu$hioDWzELyB zPxz=@?zpM#uBe)?b?{z|sE1jsuQoQ$g1ICIIAs3_9J~AyJGStCXzVbHvS&@wGSt~b zp~ntFS9pVt7>rvn2_deuguGiQx67x!kCvhh&!@lrkQ8qVOJs3xP^xIYzY02GOBa?uL<0hD!@CfmM+K8^*waR zFf=(j==`5tO5$%WWqiAUsGc{uM)N*H=6Y#}EEJ80CSJ5c5jqELro6$UE=nL{@Ropp z@%JAsDdP<1+j*Ns{846|L@+HO&1U$)&C`18R}=nFAUO7tOG1ok?bbRk5k% zZ=+JbW^c@_lf^8%hQNlPviOn~S)%R5@90L&^Ls`tj<(e@tM#)Yf-Q)!OySLIb(P)A zo3(p$z^iw@pUmm?T!%!tToar-&!|?+7c>93zvcV&7gyIfzEXwli_U=v7l7m1RDk%? z_7%^!_0(5FJ$S$RD<^m|Kb+X=;v%Q)uz+iaQ}?g)3;yAyw12#GkeTPzEcKQU5<0L; zAnvLS^mkAhD}Up3t$oj?GRfTQX4RQ-rEmFj?d#;kk7}Imo17oj={&*=0B;Rnz};-~ zRFclnN8ga~vlHT(^7FSIBK1F+2Z$W2QTGew1~!bzM-p|@hhiKzD_G%Ve|JW&x_Ld% zdA7b8?G&)D>zN98br)tf1^uX}!>80k#_kdA!Gt)}XnxD5Lq@y~?lHKHPMsfqs!CL9 zRZtV|!lfR!zI#(^;?;1@C|IEezqj<=B|8QZo$T`iU)iLYEl8H5L5A`EfR#<~p9?bo z=V}|bmfJ5SG_mR%dE(61e+T^cNa(MmtZ#yhi``p>{XD-L&+m~d$E}t6r4VAIAG)YPRabq!$in@ zqMPqa^V^&jm%g@h`DqjY z5kZm$Z+wOV9!;gpc}xJ-#w6ILiUvgV*Ev>#z`LaSY=>FLAkPbwC*GSUkbtM(Q8T zEVO>zRWE?RCUwZ}+&j-Jo7E&g-fw|jKD2bt1xg`E^3}*?@0&y$MnzHrShsmQ3pOUV zB_WD3nCx}+^&{+xJ-by|ZJT?UQYdH0>jwD$i24?PrvLYSol8n86@?s&LI~wpIhAvc z$*CMB=8(gjH#$0>PmNHHISymP9FlU*oM(n9hhb(;+t`es@8?aw|KRm}JfE-ozV7S3 zuj@WE_S^@fJJY{L-y(l?%yXUCcC%^rcQtNLJEM=I{ZdAxvNE8uO|q_2%~eI&Nt^ml z)3!s_mG+BUkF)=vu_5!mYjz_C9G$z(*i9;B5)o~+;-cJ^e`_JBPaB%54JqgM)b|Cg z>CTrbBVBP#XxEpWwUTgAiyvPH5b(5CeNk{mK+~2sKKDqE`$zMtP%Ty1JDFB&iGDVw zbnH?A_J^Wqym$3jYrE@;SZn_8vBT_Dpw1 zWnPtgZxyM&ZlhRl{K=rd6b1j@rJi=%&aFpho8)%+5Aw!Xfvb;SLis{8Y}d<{b*Qh@ zHUoU^(BYTVHf&sFXO8B%H_OiyC%mGAYbNr*>)dRsw-l|^7dS(|oZlJqyw9lPWo8DW z*Mo_1+SGAsLZ;#fH)iU?J&BUDHC+pyr>YG~_>C*tdkSE!d|tp0AhYI4(N%7^P3|O6 z^8*19=dt$8-2hehK`Z{3N$dSRyS5n*W3=Q>}d z|H4zS@V{!{`{zt0br(btTjpU)(x3R*DCHX85{D7LuE8|e1ugl4WgEQML%Ni(vm;S^ zo%fcG{FeU?`UyvK0>kuidue~_&1~$34hg0J>``B-kC}Udbzi*8KwqpY09R-ATH(Co z&__vYizS|ZgT(gyuWIkzmqRSkes7PNya?OC`7}@-1tD`aUxu&sjyGLsQ?PC}hcrTM zf?>c*lpvGOAjdl`V;k|F{z|;?$qAsjwRr|_TvlX=l2%D>0DBg#F0OLL6$ZqE>zBiE z*CY8STIU+wr51_4U2}}wKR?JfEi(e(N`2quqRH_!k zvqlt3PDdqt0N>CbJm%uNLG+94b!i3wfWGA(iIB^KobrZ^>`_v@*pG>ybNNK)TbD$l zhr`Tl|CmB{Om2S1pROnXI?^v#}%z%E;0x@w@z30}er{MBwfh z49AtR2ktui5v&1K{oRKM1&Q638OCDls!gY-MvqlBzpq<#yB-c^qz3 zsd~1gUDViVvMi&>54zulqVy61#6FpCSyBT0h4tHgpL5PyYQkzBOk94}42O6uz3yCp zxiov1GjllQzKT?=$IC_?Qg0g~<%1PZC9vG1WNF6c^v=?I8m23C5|;s`@(EN~Rt1`0 zEz4^~l5{l95lrrq^Nl(yW_v2ycnpB&n_X=ztKv~V?UnHM%HRjbulM}PHeMu-&RiKU zvs885wDt`d-&XMGVH2v8)3|{RQ(+H$Cw{2>(21-!*VeAp#;D--rZ=N#3L#%pW#7RwVLQJ}8Q!;5?~d}zmEgqij`8I| zQto`BnAMZyzhb%dm|_o(hT?VNgqP~CV6=J#y8H_kt3U-sx8IwjIxo#;)q|_7#{F$K zJqSM+b9)kB$nrN+jxMPD)y^9YEZ0J*qw|j) z<=*J-Q9=uK;&}1x6gjBrhg^@V;ycVMStC|*hYx$zudQ6A`I}tNg!7){Y=BWxrakor z!Glc+T-HaNbCtoRowdQwIy>Uni9Vy<@l5ni>uwjz@+N*qa(8c$L^HvjS0Lwd|M|@b zqTtOizDq1@I|kz^mdO?E+nrVP-p z`hx6h7#w5`Ch;-)-n;pSr%IYOZHVieT0_sAxV%5Xq^(YL@7bu%*dLQ}uvGDyLhq68D?S3l6P8m=y;~&0e8=<`{#fE(~9xtc`wrD(4VT2W63>E=k{ zv7)qf-CWklhd-1K4ZEo-Q=s*=!1FYJhJEx`1xb897~>!#aA?XwHzDf~x8NuB*cuRu z5a-b7_pxVkdAj~;YpkVL_*N;t#+8H7E-v08*}pZJ+9Fw52DKq8a12nkwQs5KUG~$( z34XF#5}Ug+P*=V=#e$p=-(=ZX#i+5XY`khU76@L3hc1yaskV?Vf^pXFZ~1^7Md<_o zk$umk&}^Z}j)C;ESYK=-AK4sG)Iq(dzwS*+=JsaJ7-^w|qRQ1&wQ_6e3#w{CeJrUW9djj!ONT8pQf?)y$CJp_A#t z^xHPoF{mfDV>Zt^<=Dg`^;Ps91)g`dh{*SIEmC|gTf&89PzUD>j&?=R&H zn<{QoKM~DOq?(M--HyiF0vqE9oioTdJQ&h^x>eypyU(?Doo->X2a5xK?}Pn#F5)J) zD#2ZyT)JQEQQ3@cvSdK-#{RgH?dAUv-FJf=XuR@X*(V3kp2zUZTZ{t4!^ASYpA>Y( z`5?u^s(Oo@I~y!f7WDLK9 z`aPAqg?Dj|G1F=f=-;XfiYFC#;uxB-1KK^5ub^YRFOd;6PkAGj-|@o&@7A|qyA8X; zz=!%=Tyr%Va!W?Et;v8MJ+UO)=HM)OD@tHmN76m%W|Z~IF#B@9$T;bNfx`J^C(A4d zhPp+Kt$p}@dkbPS8KKmzk8_xjx(|4U7mXbXGNpZfT`p( ztZ&lwaEUt@ujBqY^`i}1w^lTr%0?%TWHci`hGt#Sz5dM@ z9rk<87^0O*l#}jctoCqmkKY}haBGSKT#v(?Ce^hCnzXuS!MV#Owk_5_uVhvGH&^l9KkDRVy;{kH+MT6bzz>w?n&-I1uqu8&mD)R^Er1W-y=ncT~+S( z&=@)s&{It-M+wy-p47XGCI&UTXHPp63?fjZmLrJ0NiFw32?>g`v_|!8ajuU&;3S&a zp)(?GS4d?B3A0FF-l@Doeln%*7A<%pvgYDjl~>E>pV^J9SqZ^1uqwambf{bYXJ;!C zi6z_Z6uoRxa%XByel+sz$2#ADh?!dtIxHhmabvQ5fTj~aXM#?^)eAbDP~&KVY1Vp0 zmXyG)5vj7!FMaVxuEttD_m1?;XkmRf+D5!;;JhQhyBy-)%ut;9&n)bFHtT;3L}>OG z$K{^$JdY69w6!G?=0pZwC3Tb>#%4K~0g(JM_lyfZWU9zBO3c#LFX})xlucrXTvY;-mY|ZT5IXA;tWJwr_q<~sW`dt6PjKVtrmU#({w6KVYacR zS*tBA*ng(Kgl2gn|7YOV{KXB@HrQdt?<2$JE6=nUu_WyH9q3UZY=398Mn~<}J6v6v ztP<(uukl!E$d>XT;=dnzTXdiF-gJJ>qW5rCzCB`$qO;cHjBfqW zzJz!nK>AoEl!5zetAw~sOm-EYZ)iQ-b?3tn-$c3VhrGz<`jv2P>BcGt;qDRLswaAh zM#iBv$qZB6WkyHun^n+wmOl({ewuNYGa&WR5DO&5TBf-QHQcPp)(_0c{{20P2`TxW zCZ(vE7Vu<3VW7$gY~XNwQwD2!BzTQ0Q=={MuQErFB-zj-%mb%VtjsgERytidyr)cn zux>5AEf=5kJR!kr^)~X6(3T5YZvqAFIO$*4;I~_U#c`+}?CgTT~&)2u_yD35m z{}nbNUi-WYG;*xkneR|huwOg^DOcJym)hLiddNrZY z%h(*fovB|p*-9$dz)@Og>90(xKp^ z`ye<_ceIhIPZPm>oyiA1c%v`OhZHSl(Q6bNna&@qFKloNelibQP8_6vzJ|0?MwXS( zST3bBl%Gk0`*gm&?ROhp@w2`=L~K{DYhe*d*rl*}kn2bj_W?Q2NWnY7N_NZmwwJmD zmC1aOx6KB?7;*+{T=Af)(9!RdiQAMR)QzRI-5oNl$NS$q|ChLPK45-{Hc_L0zZ13- zWJk*Y-KMosSAgGR34h`^`NFZzX7Bxl35&`Asyg|i2S}- zlSH{kYOa>akoHOQc#GHcU05FlYEwziYqNhej7_H$h3Hqp&MS{lh|-E*Sf;Y-OBy+S zB`sbvd5u#npZzwgT$W6k5Bk#MJlxu*W@`%z49SFpJO6QT=Wi1NYVQt8K)NfM^f);?*FQP7$J_Kn`!dG017 z9PYHiPVs|JFMM={iVfR_)W6mGY2kFaD&~_fI;>$4{`@HY91T0CWhy`R_jyG0Y>ZdQ zXCn+K#nROU;etS?S(mJieNgy*rW~0=k!d`UIs?vnOHW_3(%-nc+RzLb8j16;c_<09 zlFf4!a_F4X?guinn)Y(QS(#~;)aZwx9v8dkmhN z$kBegFji-moJfPZb%wrY)m?e&mwHuTz%3=8`Aw?Jb(H&P$#oVk9&7x1lt0}+giOS~1 zdZ@6A$Xn9ZbOOlzS65v+iKptfP8Q|i;L8s}d*+r^*vmN7NQ`Hau9ZxL%;SJdiQ+Dx z@hB}O8X!b{3u$|9mFkc9F9u#xm5>q-TyfO4|luFxNPUEyLHL zV9vLJbbEYp2Sa#oJt!}(-%lX$)Z(Q%!1T*fC%Lrr@P6B?TuYQk*Pyg%Xlc)8>36_= zwQ}6Wzud`&Z%%;6@5$O76>@m+?zs9^2F9XoNhyB|A0Mz^%scH12c~X(5@=g`EIt8O zRr49G8si{aW1bb@OwVuKgoUV|y4&wwP&PLEi51D-oTgS6;sAvGXh0#H>s@~Vn#JMG zPEf%u8COdkCGBr%*DakgiQGVYiCoh}!`^D6Kyh{;9ej$_UrD`V_Rqk_`V$p%EAKYz zJtSW?!Bm&0YgvCtNwz?K*Iwt40<0@1%195D@dz}~5YHN4xukx`Zxp18%V=|C z$gW=2E}zBvK1@TOIsoNUYh+5$WBg>UjdGzG-=lz0fh{o!zsRg=jecC(_xijzz!Sz} zwoKz{a`~<2XFu?GseT+^j9%Ub>E^mB^EB$$LCg!>2Wyh_=;!^aRP26=MZY~O>^yC^ zIT zbh$e55L>v(Tmd3O_D%_+loD&P?Z(!ChDkm8pi*@b7=I3vv*<4s-V8G@R`>Nd(aL)@!s@T454Wo2V#U z)1+^T%t(4~G};H#Ui+D_nE zGI^?A)$ifw+4)tjbL$fJL9gb6$$7Pt!i^C>V<7;iRDa|Uk{LQp~d#jM79fc`olai<^0N1QivW;$UyMrca zH+%75oawoUw1#Ex9t1;?Rz`TGU*tZ`Rq>qnWfHNqn6|Mf)+qZ7Ad#`G18Be3``gVH zkV9N{9uKnK_y(BAs?$c3hEaabsY!r(1 z`(+;_LWG8M9PMK+FAU1sT4lprag=Cfu|crXZod}LJj6xhq%0XAD;)e=_s{yo&i2mU zOJ#-t#{QGwg{u1P*TkwFv-QS8%GyVfCaei)cW-NZ%%j^f^0q_tCO(nlE~KO`CctvX zMta`;{Pa0*8!z2LwGqim$83*bf(b>qtnJN2q0^eLIj1nyEjriX!^h(%=WDSSJ*t+2 z09C#uOH`OHE-zrG7k2+*o$@NtsnRi3lNQrfcjfG1Kt2YoB}e>2cMNf2UrCNk(|{CMDjN z;a0>+v!91Hz3*SgPs=)Pigvo_Y|Y$~sU9K5>{uIVA5D$Bjqa`3Q1&!AhHD+EG_~J7 zn*bKB%sG6rnw|e`002hk&Mj+px3`{6mr!wa$hD*pmRi37mmBF71 zh&AVdIph9?U8()ByTcK^&@mhaYs|bBfEB|Wx$9l^Ga>5LS<%-?W>u_9ZWYaG(y%qgGu=H!E);i5`?Gw{{%x%>Q^g z^@zS;ALcC9K(YMZrnpKMwO>%48$;rmJ8`%V`#Ft00|1#ux2MZLM6ft?_v{}}jODw4;Odxqy|U+SbI9@22; zC2wHQ>s0}4PSdcbJM>M4W7{iaOyz=s+epDq+UDuiz1Bv=PglPVCxlO&I?K6jfX+{@ z_{1tJ_*bCVYGN;tdIVURMHpr~Cs2|EiH7|W*q*j8gD)E^0813t97>&d*S0bBL?h$6 zfU;57;C6xziXhwb2l3dh zI42oaKwK|Z_CB*w0oB=3xdjH8wg1V{5pYT@_*E&l`D&pZ5O7-36UAQR zy#88yRjC5^#iAHhxxB8b-cfg{)*<*b=|0Fi#{Tn~QdbwqQ>7p>3%_RGCi#qqC@|Ad z{^uS)E_cx5$ao(bJwe?mgU*muh~GiBv1~q>H4lH)M7YNSyEePVN7mE~tRCGDPC@Cc zuHWzS5dT@m8fdw((_@#p z%X)waFQ5FcrL}jR(CB=KdQO3>-pd*%4Zr(uPZlMANBNwG4Rd|Y62Q85q2yGg;Z?4g zl7wWgyb_INBXaTD%jr+48*APv41e9#OL6^EWxL|rfrtg@1T3c;>B&t*F_a95+;5Ip zukv5ESCou9%^5TOeCf#9mALP}m(3LCdt6VcoZ8wen;LRo=^m>DI2M}p;^fG)T#F@L2ooye}8nk=}1(ZC_7QzP%fHlY5_sYuFa9=hgLKkgzs zt+oXEDUt$?^v)1y%G#~@%E$k^XOdz3R6Z3}!*0E4CEWsyq*e4%%Z;oiWhbO<(I6fk zaByab!#EI^yV(2E3-#5e#k8enZmStxz0W;|bRM9;dx!a(QCM7X-?j-JTt82YqtzJo~Fgf!pt}MHNy{X3bvn$V@sZtPaDf z#VE_OtEqk8)Lp-hI~Q{n+tFJyOz86c9X&BTa@Ot>v(yvRoaW7dU5jgc zyvT*@ziOv!oAQ8{8#K^PbYKez2DC5&RX1 zFucTML!l2}t7(g3*%Z+EbU-sN*$y1-C=zu89eqGaupFE(-sEnXm4YR<(OX4Fx6yF6 z6qnammU?M25zH-5&}2Im>=x-_zSB!JJtI1!UP|JE@&BkzKcBOy(YCO$B5@2AJ(f(f zu@=3N*1oj__h^I3IPdLJaY{C1<0^j1uJgI(J8_AM-N8`V$?LwACs%-_3`rALT=0#@ zOYQ#Kx8MqXuPOuhN+5wGFCkozUtpY1(>tAVPYG(o=G(=>u`&GIGlX zi!5}+@~51jHS!yVci2&qz}H)xch9V?jZ5(h^9hV`}gD z2mhRiSG+;J(W=$gHCC+>+(GCyA_r{-#`sU*r|YcA(W~mwE+bDNw1)Sehg;O9JD5B# zFz{zt3Yt%un=l2~)FD2c9`Gb?@&c}hYqI4L_-!|8cxJ-In?a}U(GAM`H8%_EK`nOY zJqg&V>w25LsnDz(?WOmXD@8AQscX;S4v=HcBb9VZ4PH;1ZVi4_d+~+%pqkK12P;jq z>SIVrllF;^3&74{rw?Z$-1j`xG+AHa2ve@o?p?%sxmMD`6C%<;@7v&GU=*<0X!(h< z=y|`ov#+~lYu-2*!k_{+>=_>H2{9*bElc-N?vqiTr1~y0R>KtO>(r=bw^5VkV@oRko*kdtuJalkBZi^ytcj7OCWSd4&sYyN z(@`N6&0EcT59jp3Y4`VNgz^bF8pBSx3J2SP&tgB@%J=7oZHjnXM}r(cma`2ct28;e zqYt|y9dX1S{ze(%cv)eP3cRoTN&aA!;N@Y>_n{}h_s3JLKWscUNU3_h1#Fv_Jy+fy zrF+@}ZjC;jk_r&i@$>oWkdvW);hED= zsT%dznHcex;GOaErpyZsCq&1CoM9mtDpsn|B2dF3V(#zm%6n?ol3Zdr;{f{(*V>$ zOr7v>DY1|8)>h9yeAb3geb*8@J11>gpYmm~N$=D(`;gP+QnSJJ{#(rRd$^S06{OE_ zW!{Hx*>9ije8C6Z$|A}#UYW;50mifxR2S$*Q46D9&mK8^jSxy+J$p6N8ji%P-(k5~ zsjMjYU|LToY|{SgU7jZ-w%z8kQ|GNd(c9}reM@Vkr)a%yOo3-Qe zVxMXAF;_dYED@#d$_g}^181dp$_vw?~*IR|;w}E|{)0#aGkOQ$V zvOu5X9`NDcn$w}ZE`RUqd|0+dKtdcsXki{}+o})t`;y;-4yuvPXS$C}h=e zqp)H4Xavb0p4#jZLmoL5V&a18av)Bp4w+TDrqoRs-MZVYtPXL)>ZE=E{PdMEyF@ka zpxoKGIPXT)eDJ0_Eg^sXurF#j$w zGN+C{4y@lLNCvE6;Ik6a^@S>T&J18>I{4z+>%)*vLU%10f$rYWQ_WCuey8p}Lg4Ww z^lfZ6B3Q1d4m>6}{jt__0<&)XcA#vxlwe9}SkXx{gL zoN_X}aqa7qJn@d7%Xtn4&>?MChT!=b~Et7)KU0*6X0pLEyrrn>NzB{ifZ z{Hb?PD(7(AXB9A+c5WtPe7WBB=&6~uZ%J14Dpnu9_Owx2KThJ74{1HVS>;#5g8#;q zk*%8YYF27YU+kfV8-;=%A>xTvSs%s#RYzNh(@%ree6lTFqn;E6Qg~sA(j&HU1MTg> zlSrpq#Z44EDe>6(Ji$1;m7GAY+^3kYh7E0hB-Q}-$5>~ER_qmMl%2r6F6&gY=D{t( z4w_I;Q)@G^iIq?O^vsR_ti<+gAbPHmWQUE_&F$*Krxd(TeeEuc((UaTL~IT$=~-!b z7}rha1UM$EAiQ#Liq>0LbNHoTWwB`kp4rxhjLru-%>|Fmvod%kTWW9pat|}NEg5mi z$T$;Gj@=Pmn!p`uqTa3xLGVmv5i2)VqkrTPbwEaa;I+x zmuI2Zr=K3H9pR{)7=HRtOxYcZNj~@wkt!l#VO0~9oGt{y| zz+W&QZEXe-g6MtiRQtX^!1nd@hyZxI!a53b#sh7`iZ$7&&%X5mMGDB5SVQJ}SXA)O zluGYSQRx6Rq-K%bY2ECShvsD7S!;yE?s-@rW$g*fUCcbQ5PCEX{rjgul01E5ocYqm zZKS_DdZ^(NL=IrWf!%SwuQA>^YHmB}@aypHu|w@_d{~U^=wbCm=G5A@lUYDR(fm!+ z5f6H%jGApVkMe~N7^Y2J6n@Aa{GB)|E4&?EEyYPQGW^tF*)ysCTY{W^%l%c;kk@C0 zSB1n{X*3k^pK}}wsFw zE(D1ck8O3ez092GT$r%htpmLMxI`;2AFt8Xv4xiDfCz6;;W+xxUz~2?>$t=~?8gdL z&5BEZtzAl|t)*Sv9MeOVYH$^sWcO1n44ZI`o-Z7<)rMJR@qSU_R-|-q5KHe)$q(NV z#v{x*n3J^K_EqxHpxw>k-l`?#Tdl&`lrR z8@tl+#zO=RU8&2t2Fh+tkpW!QIO3_kSMj-Q@wP+XDeU`X7Rs&j+u<-1>ckdHUXVfYKcdq#Q_#zs?rE zF3vO2`)$&G)w4RN^y_CnUU})#?t!9l9Yuzj_1P$oLM^^**3$MLLbpbK##xJRZ~DuY zv#K6Grd|95n(~b-C}SunpwL(@7=7t>+~Y( zeV)IQ3vqoyMxyjw0^75NM!A{BIBs1tne4w-*`A{0lPAY$W%UZRZ3VB9%#9LB3G&z6 zkSb=%9>03PJAPL^yFZi!ImfA0>8M}q8Jm8*F|Juf$bLZ9nEv@9gtgqX85UBow|v(z zW0@F|eaUL2=blGDvH~{IBwWhokPuW;%&${HOQ7+f-f>mo8tB5hwIkZ>)q`ln zH<=Nz;&S;#u-0Q``u4A#M;j{Yho5_W@fo8^pkomPFE$%Dje}6A%5!jr`11vV@IXKg zhCW7&KG&K5=;lW-NROAtu5_jh@F}CKwC8rC8wr$?ok4>JZwtlt-@q)5U_9f->KGdp?jbf&O%G>DO zBqLO3WUjP3p@O)>IqzOj0YrySgB>j~FthDt_7L@dr{el|DxHqVRBpT*>%5X+fotTw zb;GcHxmA-A-QQ+$;>N>>+h*chdILpfvgb8uq?#uVb$gvY&EFP{9De<~($kGUeaG*L zCYhG#;+C+AQ6dzJIAa8}E^s@c#idRk9viY_GuUL=4Sw>D54zwd!S{fxsn%nqGWdJX z?QB9XlrQx*Uf5?`b@4euCm^>x(qMtsgS(-RKQpF@f6lYEVyUv{liN#p-VEH5M<>UT zxxH5Q8cjQK|0=lb!~0CijZeU6#xu+9U*`sNewM@bT=uLLG%6(vH?9zQB}qOVxJzqk zpS7`8rV{+Ke#f;xK!rjkPk9dp3O$(Wsz)Yhkd12MS`rhU8CPM-6&Ln;t8xk;jvZ3FJA&kz3 z5<>oAC{>>Q0IvF$|D_viRoYFnh$iW;(;RB_n~ie;mNnbTRVKeb#;2Xvt|izlNVyJ< zyykc*=%KXinCC!MKkb$oN|mUyta| zBf8g{)dMmzKzz2l3nl|RPwoVN1$*>NNoMu%db|-=#E{u(Bo*{+?=#g4FB0z``AHqG zr`%?fn+2WdaLuM%(>j*=sV6u=M{Ee5OqRv{+BKaN>_+7{nN{wLS33Bs_+hTU`qI08 zWsnx#U<4G2njOy`xORY^viHTiQ#Y>U%$Lc;Bs^Sbm%vvw$e`$S8!m!fFmS{kxAvt~ zzpmkDGTC|Z>yDDTS;oZghs&0`F5It>Ws|)k;8V&8mH?++${+>R@dycjBFwq|nY-{( zC`Rj=tY20Wj#fo#Tz@&s9Ta1}d?ta;4?5D2yN1#l*TR!MlioBzEb#9tv!X~3y9k~Q zG7UeyKRvmwBT6(ikESlLaf{cMWqaz$$3Xz)LTeBYXGGoIiX%_GuFq^juH}mp?~_-F z@!7VJ-DJY(Pr*o^|RzvBKeXDqOZM43v%eCb3(5=$Ck?p@g?D3?TSaE|WJZNwe<5bifgNf*j16($ z7}LJGc4TkBDa*%S)SeL*2z0WY2oiE=X+s$VZ+#AkbDqd0D_$kgJ2t4OsWbvt+$W=n zxuwgDs$-0v3zg070tDN5In>6(cY4&f2!b$Dr#3pdUq;oxk!9N-(^TNL8*=?1E3F?? zW7pHPV|w%Ma_EY>wCe2SJ=X94JWzwk7#`|?SqnGR_ii|##$qRXkl|woTB_`$^;_~->|#$K^fsN}TY zFJjq5w%T(2Z|-ROoY-6Mm{oh$*W}W^E`N#krYEC4>8Z@z*siwa+axQGXTlUQDNKvK7tq+ zhdE@G;IcV43?`OLyLx-lDK2T|D{41t{6y+`*;jzkj+}P2e=c){dola`TB5%d5gtf4 zJBn<~{sf<1so)q&v_$0SSthkBYbsiIJ&q_Rt+6@;DF2<#AJCkbZA=P5>(Xy-c?_!} z@ydmJ*Oz$khwW0YANe05oI2smQ#yFM`w+CI!Rdph&Mgm18%LF6HA3-`7gK8ngikBN zO|4@k{SYbmV%;EqykCo>oOG8KR7<1*SraEQ{Ygam14H)_PYpmy>s@~RHS$Gg!FP>q z7#G94I!IUq)h%LE92Ej+*S_6)&#Zh%kBcSpIBv#GW!WI(@Hm2iYBiUGW*)jn*;z@% zG7X;y|Bxa+;uIynwYv0D*_-RTeHB=**1i6-S`%h(1KH9!oDY=)2QM9IKyS~o?~6e8 z?uz|@GB@m0n(ejr^&;Kcx;p(#T)xn1WZ}25O5+ZhBd4w~xm?bTmlyTVi0f-RC7M$V?$b)(uZ-81~vBNdsl2XU^KygHmj!O*UM>=~0S(cQ6p zQ~RfY0y3lXepwN8Y_XLHz`xpadLn^4;Y%0NG`9-6X z>uG_`OyQMw_^?5QPK$&wENlojSWAN|WKllXJ;EQt$1-PWyDvhb_FL<3)m zptPS?gNWiKixdI)Z6AIB@mW9xwaaQMyE;kZQP9ohiYreisc*hNK zUn9`xWy(UaMV$g@gZIvBM2Y^r!yG2s=?MF!D3@lK>!{lE^sZ*wp%X03-q9a&GdAPX zMr)6)*S@&x-6!1iwIBxi(n7BV++EDC94_v@;u_bbAVxJ-=+j8*^bP^!#({dl{yWn( zby@BBe<(bg>mYb1_IAdp59}QvljIh&kx;|sAr?RLl%^<3RJ+H{L4p?TywjHV;a(pA zQU0WdEZ(9))G&%m>$<*I%%Z>r7+zH?a%Ci|sPWCAd;C=0Pi zlP?2fRdxw7ub79wwbZ`-n6-x(-u-(^fP=TxDG>_L_vtFUSEZ&_l}>EDB_KDN`>hnr7}Jsa4TdrBR# zK!F0wte~GXmgyc2J0GcaM@|)!L{%Ikokt#okt^}W_29`MCQLpnky%g6+9a(?9MjY+ z9#ZpBX;+)m2_p0A!02m}@&UHLu;vLXGAu*}id2V8dMPo>Z&&`utjctw@u2SbO+{`YI?*d*g}DY&u)#W%F|nVS;Gq zta5(;i}PZKF;wWj#Ub+0S$=}^^`4AE+a?BEvIVWVNe)8sJzIhZt7b^Nc4$D_HC=|a zdqtfLkGJ3}_hSPd0O#&EFrJ$eqWvDO(=YKV%1+&CXJ&Va)m zT4O&XdAPoaX_k0p^8wwtbgR{DEc>s4>7Exb%j@%gmICjz=%GZERzEmn@`%aOf=ERh3si49`Y{PO0RF*{-Z*We_;Q~ zW*}G6T<312W8G4+mkL{lmj-`Zq=kB=)V4oNFK-;P6K_Z5d1}96nnr(y&FQQAMp3W~ z*NiaBrG-DYEQ1PKwfjP|4;^=x2CpxAIM!;fFP=;jYYfZxH!*n#-7*g{y{G9)?6w7= zpS`^TP+jE4o>cE3hTKv-l$d_%FU3A$uBp8Z>}L78T`x4Ea~g^UdhmH1DZyT%A2Vzb z#egSj7TuH}QMb@|f-X0%ij&CIdp%pHLg!fAC$1G}K zWxt(R>d?N3rO4nBg1jkK8%ZlBSl3NMyu*fd_@8n zR+#cFl{pN67oFC!p}l&THJme+f0igT%KyF0w?3E;vo{1(jT@8@o37e| z%x=D&LkGFr_V9ivLRScRcV9?dg`&A`Q zx8_U;h^nVSO!B31(ND;?CiXDzz)aefVzsT2L#D(+QIol#GA}L{P7kUlrp7DC)bNSI z$xT7%zvcGErfrCqv8yRTe8xh&zURJp>PfNJ2@1OSz6+L+g|xO0ErGgf@xe+`JLdAs!%+W=rp(W|MQ&Wp@YorT$G>q zs#L>Ww7|Qt)?xSDDKNJr=S;o0cdt(I8GcULOn*YWFLlwBJXv*VtWj3evW6+#LMzGu zBV^({B7F6>CJSq$KSWaWbM%nlnO+Z5jBN_Re!fA=?(tgkvI-I1+;r^G5Di*s3CzVq zbwV{tzo*>T>2JA-v4vgdh*-E|eRr!(|s?Y~-U>0jR>~ zsw4Js!(qwuX0rs^1XfiBz58*0&W2_4(LvuO9-4&3=7%X~9Q6TWeyyb=WYc;nBnZ5O_w zsJX@br|pxXz*DC2`fnzHJ+zxkm^;cS}eM*lK{{YwL&+y?^=OnuwV!d|AyyO=ywBi7~m7&aMV^tK08`dOu^K>PA#+C}f#jhKx9x%sOJuHm*ZaoIWVAJiTfg(C{9lHT3FRPFP_^FCCoXLa%h6#!{fm@ zr+A-pgSbAOXw7&&X{zmT$rs>+x~n&np$8+=vmLUCPcxqe3ib&J%9<%Y_isPvqmY`A zqmN_u^{nTHweC89|FP7q@ZJ4(ZlqU25@$ojn2mzx>3batER$b#q@zQjJ#<7s2uu+K z@YPZ+6t0+%5t*TaWU^jEv;G9K`BNO9MW;fUXPtk0|Mo6$`%j+q zPoh2LbkhRGHALU7p#l|FK(7qsC%Jm_6A`X%tCq$cZQDIPgFTvLHW!)S1!itaLl&>V ziJopjT4__0vozNp>`0;;P7eNZK^8UA-U2^X_tERj)(S*?NuXDHIV7N_(eY(X@$ScJ zV}vQoyNg@y+>p@A3^1>9(65yHSuGM^*zCo5n;X7{ddFhbow9&mba$5N_Q_InJ~yRy z=6GY7JS)_Sv!fPXs(7xghKBzub$5{m6ILv?-1`yNpnvd9bCoI(rzV{Sb90xmhdVs$ zxHu!{Yn!j3%g^9JnhqxTt!rDQK%zvKH9=5~MP+4rsm|SP=>X^(w}IvaCgjH0Pn2q5 zAs(ZbYKjgTcc@=Ds~K;QF;Fq$&&Rd{3tJ^Dqo%6Y|H;%Ub5E-+dl4Xt6V1z^$r??<@|ZYZF_lP9LT# zHN`E$q;LY?tYkX%vwuKpI&y`^2YW>4@sRW z8QVuUWfv1_m%)6fnK~=^0M$WC-o_T!_nbX9l0ujaGElD<1+sMK5jl+sG0 zUjGM6r`nQN*@xJ@f?pXv{A^E|IL+GkZKxb)6drx9-*VD22dGISHqo{kP|dKr*{%H_ zKb>f+w0F!z?Qwp`x~~oQ6q^@p%S>-45*!XdU-t3+$q_ywVK=8}m0w0qp9v~{nPb7X zS{0Lg;^m$RZFoQ5v<}DoN&K40fKmF&G%OoJTN;TbXMuf#CO+ zA(XJ@U6KFaDB7t$$OYFk{~vo_9uDRA#yydQ&@OvB*@m)Y*CLf9Y3yr-$`)gc!B~?@ z(q`ZHB22cy7(OYSAPm9c)U-k9x4lvr9PtX)N3O|KTZNL#>sVGM-n{n(hJ48{~) z=I79$Z3+0VPYJRdSWB$-fA(K3-y0L) zlAialqylaIGcqSUuJ&N{5%lGY!9U(EB$@b&4^dgZk@@&hW_soZ{We#b(?LKmKwRc`YR(veZ)=cV% z{e|=o=6P#1gdd0JoMTn&4w-+Kn7%(zUCZHAxglG1_J{YLQw;2CJJY#i40Tgb)bTuU z%n|*s3v`ITP9cD3AK0C zPiroP2#Yc*E6u(cHx&8Ku60m8`GIw|mfII=EvUoR{sv3xnGw9|G{J&eTWU>kcqZOF zq##JIBU*t+?hUspm7>-Y+J^3pcb>g|rDV}wXe_mZPCdUE_&tutQ?+rg2QSCKCxcI~ zR~UrAH@2p&wr}FeU{06}Um#Y>=Nb>cdg}v(oZc#Z>O&?4x>oCxoKU_7` z;`T`Gn{G`?iomG53~MS;lc(~0W6{Ilmx#~#9J{{dwGvBhV$J5ScagK$H;)R_d_CjG#rd~!{l9f>y^BpoM{Dmo>;J6g ze_5CR+;t%|HLe#(jdLzWZ=`C>+3q++-+a9VR4Zc%^2kZ~6QOj$ZWNFRt+>$a^ErM3? z0O{mEQD*#qF0ZRMemB^*Gz+zY*?Z5goDe2iT~#lBU-D!UtOQBKPkHLAN*>&{j8A{= zW=T8z3*1ooa=uG}KARcYLg?5ilDB)W1NV0)B!)s#T`MOJjs`i3U4Yo`=m?VJL~V(a1z$8eHwKtC+&z_ zDR*mv`^qoIyvy(EAJY%-yq;Y&ncAX}HWz`VThD*t^uLF@fFLWZZQf7=oS58GYb-+X zb@lZz#%ylRyzV)=be|B|79dZ#S$s56wx^14qhBH+RoB`00!6uOdIWvyTg_H>eaFYX z&*^2_@>K@cwnQ%zu^T<61sLD*AAVo#6&{#4^7cBleR2!;n)qSu-xU%{uZD*#PDYQt zo6%0bF31xoyh~AG&E~t!!TUUG1Yt+OrxB3Rj)Jmnuu4q zVUzDps9C+Wk+hBNiiX-Sh6~GiWm{ms%XX)ZY7icEjYS-t8(BRj{+`PG)0FzFwhrmH zhx>(9AoMZF?$?&G{jnOE5ZdikviI)Rfqi#)h|WoG2_4&Ru6J(iY5uca9}{3Rgqved z2?m!3ue1JLP5$puo%#_vTAr9>n&~p_;$pN`E#s4)XZAJ7dVQ$G<Y?sC1ok8l$YmtpxEh;B;m;Y-CGGa zmf)?`$rslSGW?^n_v{ZBAYBQ2GMOi89BlONIFTViOpl-tWv+0zFWK2*R5EhWgGz;$ z-BUCt9paB44YF|Go7_PB~8WApL|m}Y@BL`iaMW~J3rCd_LpX9i@jyDjoygy7_h=9eT+R@D?GXT?e8z{7j0V{;~eMio`gA)EOtYh^qstO?pBxRixnyWZ`8b8>7*Sr%94v|B@T5R)y(ITjK428;#R?8%hkC@RNlVY}8~~e| z#cWV&QKBUlp$FEgCxtgrLHz3KH$i`nY}k=pURa1WXV#dcH){Lkh25=m*^v1WDNP8l zwC8-V%C(+aQewZo0IVARyBTnM{-2e$L;LMlejhl8E^+($zH1gs2$CHHlA&3oSDsNW z*#{u{SivVw?S*p0o^h%#);E>6?%p2;)4=GaPHA;ns>Yd`+d@UA)r4Id$eND>Mg#{C z+6#49DX&P42=@@hxOLW2$2eQ>#@IHLjDHy8jFHzne#=?%MRwQmL*jK;MwIU7QX~Se zVnv_dBLu7#*Ehf(%DvQa!W2;v9%6VD^XS`bW*u^SsRRdX7Tf(#s47_apSZ~LkDp^( z8J-b3u`2y|M5-pbIx*O2`pv%iqnn?x>G`@3Wo9TJ z&kV%7yGDqq9&G8QM5gq1b6OJv%O}LDim<+Ath_=hn%uW{3$11lE|?bR=aOs4y5^WI zMHk`8fM>Py*Ib1g#Rq}gRP0VwIwUfLKRh^31fYN?hihP=F$E#<>K{h~r~Hqjq3;}B zlAbzLyK2`X)0A*iDV`B1TT*J!8QF5%5y+msHKC<;ximjl2_9y7+N$N(&l8CZm7(Te;1aXAp<7&DMhG2OinpM^=9I(yJ8=%8ohoI7=2(;>CNY{Hv&~WJjWM#|GcA4 zXlb@}H3qHe{<~TX{zu#4vre|rlot+HBq4&R(Q&`Lw-+$gnL@vhuJ_MoB@JrmTeM$T zvm*`H5#=udU>Ig4%E*xy7&jyiH9A3k%rMkPM(d9aGPKnY+K zj-mukFTCUPEaTc9(YUtxEZv23{yQ~Zy=jB#1PZ)e;NXpK!#oOp?H|V@Nv2T_T-9${ zzQAagtOMBf*uU(W_z%0jKm1K)Yprr?OR z0>2|p9)j=aYN=IC@WG=adq~7n$Uay+GEpo3F%fd$$#XZUAL&bqPHVE9_M&wUYl^wW zttGXH2YObO_$%Q{ewB`0-5%CGb+a|IN*f-3pno7%{=l{36Z-DIg4br`_8IG>8ESmm zzeXL9W1eY6KPD2!*CpCXfI=fpt_N=bn_Wczb219F>GaR0OoK7Cus;3Q$;|PF`#cjz zYZD_z28Z6qZ&3#f;?d8%+Rk?h1Z$mk9rnkNt>)FdH$IM;QisXEc@Ou5<9Gxvs)2mH2Vp&Q&+QC%EJDSJ*xun`>H^%9Vd9wcdh#5a#g5 z-Pj*$X9WExoGF26ykE&A`V@gg!HJCZV7E&utWyE-L#GIc(U;rm%4gnf>`l%d zIIAsucgS+rRsOOMjv{Z(-d&OZk^EiN#jD~NXPlWt{jSr)x%?K@P;)O(z&oRdjiY`? zkGhS-e4W0@8DM5|d6$Wq`AMit&i8jWuD!p3T&Z43)1a%<)geZ{AGS;&TTGrJT5++4 zy=}fFY@5!gh3W_zzoAu=v{^*lgV_Km+g%R<0c+ruXSqA|Wf$sF${vwzcU!D`sCTqM z$e&C72jZ|2_b$UBQ|nBb=kmP|_M=tM5|7kAJ&`1E6Pi{DNEqDGQUWS#-)_|xq?_+L zTiC&H#!tdm7AU1Q0SU~$rc`DF*HoBGO|GC!+k^dSc-mzhiM|dSdN?y0jT@NspAK4i zgmb7X{TA?ZB}3~9Mj7J=90{&(Hty-JkJcKww9ooMc~rp$P8+7}w+$a($KU%e)mih6 zDTk;_m8-X_EBp`HK(ae3(yk4gL<@~HyE!E@>gLLAS}sl&MYS!M=)2lBT^v#<9Kzh5 zfe|0pb%aq03N7T@A(UfgU1r$}B{G%heX|>1szoXzz;w&!o3^Lz1TW0_2jXf|3LZsE zHgZok@Yz~f!lGvPobz#faJXG=O({!6ysK11e0nbJ5q7Xa6rv=F7#XoUa%2{!?OAOr zLh{8OE6Jb3f6&NEw>nV+)%RncR@B}F+^px;bnBIi4SOf&KyaplM9l_l}!|4I{~9ByVTuj#l_f@r~Qr?Rs#r zoOlQ!d}wZV#QT#(cg4LoSry)PW&{nb;I1`=jVuBMc?M?rQp7|KC-IyTUJuV6Mh|>> zoQWJU|5^!`Myt@Fl6TjRe0BP|UE8o{gyYo-4wK#6jiT3@^9Mfrm$N47u^!e{2Ifkm zf*vzLX3Z&}^Vj;m!M@fiZmB2ViPliO6-{Ij5TKiI=ATo0IIr&^JB;W`wUZad4ok}4 zoMI;r={T6d3964PKa$5mIM8?h-e-vkReECxR%>mCrRxJZd_bUqEdTxf213sKR?+58J;P`- zg|ec8M>spP*y*X;56Wu_ZHp)?wA7vYyj+V< zda|O#Hq58Ygm7&%!XWqizKgw)(f9P@Uo1_pGG^vy(^)Xh)GHcb##pMyn4z}jo6~R$ zX%5EtA^#1~ID6dP<{f~)$>tByeaEj$M%3s#tu7PAa)dH1>x$BP->8?IGJi#=uBrKS zSDxeRNgB1ToyRjV(Hwz=*uS)jJwf~)+Uh@d{!fhKPqC3wCK$?G2J(Q&El3L=gNjZ z=}cxV7AfEhO^?Z1mhQrF+Pb_dkd(dvcREmZ28feL3Dz#qA{Pz7weoBb6vF=rxG5w= zo)SLW;0{v)`w8S?Zgy{vW@jzVw54I_*?WIwCGcS-0{6vPmIxBWl^&Vvl#M31KS-18 z#dqrzj4BBIgk%z^TJzoDqCz|RU5tk~!oI*GY9qSc{a1cEQ$D57fDVDr7hD1^TN1)$ z(#-D&uAP(2-n8u&!HL%2>1;h2HDT4|A}Ct8hiv^|L5$8lpq$Rg_;~;AEf4%Czu9cu zfkqtn1hnGm_(;q%c6jC~=MK}nlEGg{s}s&?=#^AcBiPmt_j#F5jD4}T`C6NmRP)NC zZXs{3R%FjeV*y2`z|ozl{31=^bemOwO>r}9uJP4emI(F<8e{$KI9_4eI{kwec|}d| zb7WuXR8?5%wOT5-U4ZOTuy*p-+CaGp3HK-XM5HThVOfP>REwg`g$;Vv%v_#SIQ6D33vnkat?)Bu0VAhWglU4s z#GG`Hgfx-$YWEFHbJas^pL=!V7wzt47`&E!VsMJHP5#S+{rgwP9qr}qV%u9zIB5K! zWP1}_^TtNG7px;uWYi9d8iI_+gRx5Gcqf(jh$y;VBd~bza(TXSdauQ@8d2d zAf8GIMaP-=6mNLQq!TC#-#g{Ipo;w?qq{pO**9t9GVKL_?o(~|YrAo$uRYx;Tk*$^ z^gr>%UF-XbP&v@oQ8&HX+qfS~v&u1_pi);W6l4}pZ3L`6eqi5ZzxxB#mjLUy_uDt} z!4fI7!G;F$VhxhUKY?)e`-k-ia+$HRUG2L>!)G~OJr*e_kgUI3LHd=wUx&5Q5)N6? z=v5OUF)en?k@ayl(;Llkl$v$5g7_{ni@1Rt6fPbw;^LY6a|u5}jHr1J1Y zA=)v_!{Iy|B%^l)LU4&l*7~+>`06&O=@tZ;O0eIT@gfLS|LL~4^RMtX2O7!F<|aCx zV}|9yrwV59tSrpc!-AA9LM5HK;m?aFM6j72rN6@~IXcB{Diht18*2rZjyzU#@m*vf ze)PiE7zlIsSpSitLRS@u71U5Ie>JhV^8-_ICTNtaBYYLVGMqY3IAp8hYaVLX?3TQq zXe(1ViHW!!-wXCubU_FWHKY2q=(p@st%aJi>;p&6EcFeKBndqw=)c!ZNUm}1wdXIG zXKb{~unO?9j#svR#%U#^k53&xS@8@T~;J1uMN5b zx9ZJ!fHb5Id~@f&$QNGD#>)S&H*bP(xmO>7ewLGy=bQ>;d2#tezI!{>o9$sjAn~RV z@X(;*kaQ1-c(}ssRw|}oxwcLvO;P~~JWBa;iaF6gM zG&+zw!#4p5|7xW4W$DeyF?u|q*z04uAUt<2 zjOneSetbR#qP_1MbGKFjC-*C4@q_(C1lZ!AS};_myYPicS%~wSwI@C#fB%pgYO2Q# zO8{AABJJ)SLA~3AXKUKmEY#|rTB=Vem^o-t5q@!l?6R1GN2{e5dhBnBfa|;|W5qA9 z(=B<#@v`meD-#&>eW4+=Ka~@uMfVb@WsYGUk%uABHK!4X<>L_rOyNhG;TYysZ{=qM zI)S!YV__vgew9&83au=ypfzHvy%th-aZZ@cg;R@{#zI$rb)ZQmWg+N3Aco#UMUrO1m~OU z`C7nVl%G!Vx5%|xIcH_*Ho~ec`be9;BjILYzapZaF!BXVZ#mA1hYafv*+j45_{X4J zaPvgq$h}PCw-kDX3EV?Jo!ANQTW$2GofHC_k*I#q*UYAlJ<~A45SGrN*sGqgg+Qcm z$H-n@t=T8v?k<{>u1E?k#%|1P#su9lg2du`r?1M~j-I8$Ob~YZ!Z`$^N81M9*ebEg zX-7)m4=Z4qzBFWBsMknj$&@X3sF&p2bahL!u%Ez}_N-pungijhaMEg~4J3AaVVUKW zJR{aK^|UxyQd>7mCSKH*F=udqfW`uH(7v#)}Pt(Aq!6|uctIa6DA!q0zK2vThs zX3%qq%Zp(JLCcrEj``ntK@yZmsPqDJcFk}rl@m49QXiVJsJMi&W_)`tEqlDQdK~aDBrPW6sj3;>_6}I>L z(5_vU0qE~5gMCwawO|x2oLTxCBb}mfm*(HKmd(37)5ti#01na`h<<`1DM4#%WSFX4 z^rI$69AQfDkJE!yhQpTj8t7aOZ{QDSnm0yM%#LMW;zLGw-b2m|lCZTdBalyx(Uat$ z!P$)9u<3?l;cm4o%H3gXHI|l6_pD`lrEKB;szKWh_Oh6@qFbXK40@2T@<(T#@)){O z*NGT$D&N{1(!U?)VP`K{R52&E9;m1z!D|7g!Gr?iCz z9uPB@v}tlMV9T7K+u`>lqH1 zzuK=&wQXW!alA-9Ng<5!I}N5FPp1u=y(Ki}8quxcvc;IaS~XLX4p=+9W1yY2?QS@1 zQe?S6MEQkBu-W`Ad&BDC(wDckbxh>GGC#dS%Eurr zbFJ@1##{ICOMHsT?QfhQYCjrv2svNv2Hdx00*5CIS{`e4vC*Bmf03*Hsl#o_WT9~D zA+q;KTDH*W*7Y42znW}jsw1F> zCe6avKjg>IuTU$Uk>2S`Uu}`A4mA3U#CsTfI}HC8DC|j9$<$0(>HS*%es1W?_`dlj zn=TXl2vtl);Am>&W{m~X{^h9P*%w+f4x_x!HHEt&t7}Ee45jvFAEdScc?)bJ3NOx= zN%y5fmC;a1pMaKd+adDY*g5O9)DsG-Px!votU*Wf&(Q*SL&~C8eg&2u##li=CM`^Rch^+(%8t*XvPlYXfawd&;by zn~SDf#X=|}m!zj%JPGP0M>ZW$^~WE+zEsHco&&ZnB(`=@)`^jWpKcX&{$u!ne}P)%`q;D({)LwUPf)v*2$VDD;@!b_lbFYg_Qdd`ifeI z7GezR)OfRr$WCZ-43GnPDc*e~N`8i{DhYwF;liINAIlJ_hycrUXYX5#a+jv5+raDE z7vR=ieD+ zATF{M`34l(H@ALi-Lx;Fle>U3yKSiMjDO-g!pc+M75~FO2-y>+&6^=XX9qo-cXznL z?6-Bu{Cis(T;RC-qSM>knQx``9McLes5`H1oT+%>%++Q49AByntKD# z7z|dw*S!DJIS3`Vo(~Czn%vQ}Gql{&7E8DTn++D<()w9_R~wxI?xlG=)idu)BXoOu zN}RqE6LbJ(+qGAB^CaC+eJn$!U@&{Ycc8@qWf+Gi9n+C2EckLceYC&aoduTJ5q!11 z0PGn%>SNnskh!esfcFpG(#FixhK`uQFhkF$^rI+&uIg(D-roFh&Y{{mji2u3 z5;KYxvkvz8mz*S?+%el0*dweAFLdVo<9mr)^_bo+OV-D8>Amj^CidOVEX7=^QIDAZ zOX3=vLeR)+m+(Z{F&KDbaKlyprk`ecFsPHYamJmDS zRbRXl*f8sZy=z|W`#mx|;Z$xblysZWuWi4R*Jao{_wZ8Hq8#G%YDs%Am*R# z=ItRc0Qh>0XlH$LN*`&V)j>PTVI`OqiBGi^zpq`(wz+0cW}Ih6l8T!L?f33XFS@!7 zATil&?FezIb`YZS>0=ip7baY8u!d@(HZ`}uEY4C77H@nt>w76&_4igDtSAHXZKb#r zLyD`Zk_T6A2GvY+j;IRA(oVJYPfsLNx3vbS3>Oc#1>MmerQQ~sJHM0i#OZ?K8#|)%2UrT`H$vRhF!$V+LNn?AQ@2cb@l!&qesoqUnY3* ztKN%P*k1%Lv18%$AlZ8Ak)Nt%{cl?m0|W~yqNeAo?_xHC<4+Qh$;%$J#bX^K+C_d6 zl|gT|$4%sFtX;~^QJT{3g=3mf8kHW?!X>XHVQZf7uOj)AO1v9<5Wpb4mPiU;t1 z&mn^B`3N1gG8ukHEZ_T{-Xe1@tg}FR0xV?n1$wW3RNQ!= zWnq)fJ^ngf&B$*%YsYCv#qa1Ih<=0*!z8{48x^P$*#c2XF|F-z zeT`&<$FD`r$Py_H1wWd)d&g?+@yc2XG8Bx=V1eh$wBR_MlK2}wmS&?;?bQWASme)T zrEnur3H-6`TGv9I8h0diq-(|BLpqUQ4M8xOkdFo)HKgA3edt^X4|9o6ignmOHir1> z&{Do{x5~m+5x)NfNKl|15-qDE;7pi6R(l(*RF;u(v!>mGSzk$`5p>UjHRl?%^Tszf zqh%y6&hdyN^+;~k5dO<+Ug!MmtnJ{z^xrJlzEvDPuJFFXA^`S08+9IS*flGL6uYQu zd&m00rH5W^&c;s^(4X9SY**Q;uompE)z96WN6Pp*>u$uPnrN==Pb%YDaY$*MU*=;i z5Lf&*adroHgqmZ=T00+c?_}<)*y~QjtjG@~bL$J#H%D|p)^H{X)-p0b$>ulBk)rEf zd0Ns*#V%H@g41?g)|Le5&4-2e&uu;M{*op;PP(%M9gd8lI(|Z$oqt(+`U(nwF3tYeLxvHss^8%Xn-fBbNmAWh2PJ%UOSs zn#qnfESvL9W7wR~X|dww?~9VF^az{P%Kx(vDp~N!z1#bY=FHY3{1Bk3BfZ4ju!TMt(FgZq-B%%~z%NX<1@&QhhRJePxw0((-K9 z_jNPJBuYneD(KC|vC%XFx=x3+cb~?d$#B9o`h{Hqqw+U2L^bcMkS{?}w$Ca5)rR+X zr1DD(A-?>P%B~<4IJQV9b}--Z5DI$xi?NZ zLg0NK4}6M7iPnXjO+oRDh?q**HvVJZfAu=SHPv-PXfZ}Uu`?Ie5;f`m7%J6#ghg43 zTdjjhQq`D2WAzz~fUB>Ee&Wp%OVE&+iFE?m9sIBpnj@2UAYl{Uow5_4c>5ph01N8j z!n;2jt?-DM2`f{@Qok*FY%>%Fqc821M3}t0!U*E?jtBtQyODRMdw2wf=0Rkt_t4`k z;qDXJ;P8@2X5X`x3HK*;5&|;Ph5bO-S*gsmQD)_S05^4*JC?;Dej{JG+f|*0zJT^C zA*LJH0v?hq8Ph4wwKzgA+Q)PqS691p3;cGoF@WNw+KJe<-ig)9iLi0)@ayw7MFljb z!bwWlRAniK=V^AbkhVD#?%qsEAPNWBJRU6y{N)#TG2U;4YvRJt!n&SZ`n1Cr3Y>A|2(Pf@xZks`pNP-kt4m@McjR}Mv8WV#AZU%wy$uowg4e& zZ|xuLdrDf)hzD~XY6UL}B=?$ZhGoyp7jLIf+QXgCrkggc53)8y|B@*EH=@=z^+~_Q zTClP2vEgDt;aJy+`DK?0MU8wchI>B zMa(Vhv~*FvL}k<}$o!(@jRd4$0f5i4f4T8iM#yie>dSS7hf9c8OyTll$qjq;j|5B9 z-hn}H5jv4`_qEl}dQNM3HZlq>CNy=Ys-GQMEM)58JQ+H*qHbTFkhSdpvSHXEHrh6u zbg1UH;x2PCpBfq3kA8BBF|1Han;5#(V%;>hT6!MC^9(bLypt}W{+(9P+%EHHSO+W8 zvD;4T%f45XZtrZqhQeZg=A+xoHTLc0?~&MKviiwAlun{~=a+1pr*^M>kne}AIdp*4 zA_?tWQZRfJClhm9=sVmoV3~`I3=PJ01dZu^?eUE?h#qG~)brZ}(z7ozS$}PF_m0oi zJ6G4~??IF(bMzZ*L*7dn<*rex#bP|g^&6Lh8X(C(*ZS}i(i&0=6Cqg7?zCu5T0v11 z{sesVO@ow=ez;l|?3-ji~ zAfp`R?4s8)UBT(x^1qr4f@@Ez4hSVY7^)okD;@g;_5jHG9II4f5ofzGwn42a9Q0)V zUMxsZLniPG2CE`}DTXUN*l>g(;tEmByxB(o*<(fEVvJN{Iw6}nXRd2?TLpYeB69ZY zdIzF5&3|*iD;G#7wb=MT&E}~@rlQ^N6n776u6+`g=k&-w{<=j=pJ=rcq^e;6rm#zW zU4De--+w{R*nY@P5n+cccFJBh_w5vAwk+?I{r^6F#8!?w<@mo(f3h|CPSN}KX~qd4 zxVlq9{`>R_+obQ5|2}>GFA10beainY3I8Jy7_R?~Ae(3Y$Aj!q_@9sfgYZ8!!)As5 zDQfm8{LhjAgYf^iEj|P+#0{WtOK2Yxl)z-KZ*IEMn<5M)xqyz#6`qO|`2KkU{{3Y| zxYyK>Kf_K41XxZKZnhS9%Ps|VlIcQdA z34jdq+zh0o0hHq~7|Zz$N-oEf;4MrWkb|)w7YB&1O*#OmVfM1?F{u9hLfdZ8Y64Id z6asm#nV^`yz5l z9fV4+N)iOAUD9NOGqcufslBy$F3_rINf2mE<8>*UirATyJ)oyZyCb{w_O<~a%|d>5 zi~91$#bT%ksJ`E?Vt0L=&-8ZVBHfsjEzZV$vL_&MtU;k*Lda84i1leDkb}Jjl$H5s zZWhDFb7q%#JFq|_Rj}tL{@!f=KgA0S%m2ILb@=VTetkaUgMr`=GF?;5HB#_<>nZMu zWZhuRkmy|Kbi)IKm4lgi`WVX`+%!lvf&(mVM{>0PE7;OoSpnw#c z_RD2s z?ha||>*+R{$MWyO=1*^mn*ZQ11=tT{!Ee_9Om)4EYMLt|`)E)7$A&Wi3l8l-dz9d0 zbzCo*In-uxN!_hu47indApP%?ljU!p7hR~@4FX9cxcPza8(zC3U_Frn5U$#e0e%Kq z+?hDqBh@dEB6+j|DD5=^2fbT=Zm)DuJ{b`Ly zQ>s}{Q-F~InwjTn^aH-ZF8_b)#{ZeW|N9hsDT0m;yt~4EpSlp*N;X!uPq(13+)}kP zHV^rdhTKIJ$V(M5Qj(N#V)3myTp-M!*wiiwL)#_}uYJpn*-?EC`BSbLQfCQjy@c6Q z=SqS-fc(4B?UDj@c!G*8eRmat!^Z)iBNQeTGkO#-QdmT&pZCEx=_$4QZ=G0Qb_rlf z$zV|_buBiYc0PGRIkS{NW>f2$UEsIQb0o1mMv#Vuv$r*4@uiXc1FehBn`f0$vma-4 z#CC&3fbNBid@P3P_|3nWW?cDzpB1@Yqu@Weux!=hah-5Sp^~72$E^f0w${~j6M|UN z%;I!V`RRKYY&g*3ZzAJD(1p@Y%AenFYH6SJx&C~j0TAhm`(A02M@!m5TR9jV<$DKzhHKLc|u9&%9+Gg zKKy0{>J8-Hn;g6E3|;s3mCEL7K<|OvAT<*HtD%^rZ=n}HP)@9CjGwo1<;@i6w3*N% zJ)7%Q)JFOOXNzDQK4Wo{b4%bHAv42m4zK*22k&*dbe_7vt<{qlxr7p)ISY+*FSa)) zQ;ag#7kbg%;=Gg^Y+mQy``pLVJ1Mg+8R#bY*s8covgPH--7v*e&%E zMx)|KtLChDP~N~8#;Jh!(=~qurkQ(nM#pBWrw9JI4iAv%MAQ|9^qqXEuSkLy3j5RweYWCjZ<$_knVH*6POG^xCE?&b|19mhL*p;@ap}4$-#QX?xc2f$>3! zxhpH5mrpL^j5sjyLw80#-L5ozqV1f~(Lcqz;v$Jb3wv#aR?V zp*uFU3L`7HZCt~TZJMZ5nB9ixI+HbfU$3TqZgW5ak6rQzq)M?4f2k8nyC^ZN!8*E2 z?S0KcDlwn*jxQf43991PzgKbmP=D)wO3RXzGAa23S;ggZ6 z&s>rLF3|Fh@aLu09*@8REI|jdj|;nR6$u4T1OhxB!u5{#Wt#t=7qn!|=_BHSbi;JF zy4$us_i{O-06fS{>5eUQvB^v$-!TT?>P#2Fl!&>f7WVW41_*>=_N@F|me`u-g!6Q* zwN%NBzz#Ze@BQhRelUeDi4a(klGN#`l{VTn3J-?qCkO-_H_y#KN*{`26HfEe_F0@P zSPo3R`c^=WcbCTe1v_b)=dAv0>-}dgygjCc@Ldw~#hZJSQX_T$P~g8ywx`9(CxB+> zL4+$p>Bq$_lsS9`q$IS03^oTJtodhNm%=I{eV0Dk26syz=u*Z1^&c86%bS`P?qHkv6kPVrXDn{Fa~w9MkHoX>K+S2SsHDhD%>( z+viThh^wD}Z<-r#+i7jrr#37Z5^e;otdNpzWY_PdTr9{uj|$jq3O(}inq^S%Qr5S< zh8~lf){?tXe%^1>hB}dyCekAc8^jR2Xv-suso-soFXDGERK4nazM` zK?9GsRYH$^DCp{yHXK(^&O~a;RW9!_v4#Ux6Tn9f=B{;qzHI4NH+1)F1H8`9v$w)n zMFZ8l8O0%cvO@YMl&PhOI56IHG8wjAw8m-SRxM(SISNu8|lOnDT< z0%_{E?U6lR@n@@#z^bT54!l=hLnLvETL@H(u$h4En9Q3?B_Y1DU;v|92z{)$wJ|m+7d!#9n!Bf50EZOiMJT)t8ERH*M+*WFxZqL#- zCG8^K4iPY%A8e+%TU9o8`pxn)(i=-}W`8kNsWItix5bSphW47DkIPdvG9~4@PJxI` zIAzo`@8m2gUHIuSXYA%i1t`uuX~O6Q+vO>6%_~tRsH?p#j&+?Ca1+|4A(uG&sC{DS zuvdE*ZaoOpE{~RBc(M&&;moYT8&$$(NNSm|6!A7!@dpsP4X1&+>h0%I2lap?u{PT( zRzPv~PattM?-S^Jz~U*qtqh=;3Q|UShqbVB4mY&?HsAbNjMqJ* z879$X5wuu1yS2F3lP4=1*>iJY|AaNzjyI&}Zm57^eblu|BA_+-9aeJo zkL-12zu7k-I6T+^r)fwN$7c;Bxs^7vVWFAb<5 zmkbEuLEViuCBmgaGvgrI^$X(l2k^2Ee49-nTzN|=sc)xsjG-Bvg|d*WbmUkuP$$G` zVfmE7#2~ofu(JyQF5m7KA2=8+?{FzMxFdo*zk6JLUXYajY$pE==>YILs-@@nf{TQ< z2@C`TvD0furTRR7AN%joWrFY1m2j<%~AlP^?_DP=*Za*LmvR`hLQr_ z&2qlkXK?E?@4o6VUcTcM9%^)T%=o7Dv~J|q{NyA_l-kNB!TqrwdLc!BWqER__A@=? zJxKhho(PghQ@#_KHm%3KivE?>k$f3=)7NmW7C~Fq-W4Thgmih!{g&saV@&Q*B`b89 zXt^hMsdDMY_wI0@aggS@2(pG}sa()X=69BSQ$Wl{yY70MgZRms z|4L$eFazg|bpo&Yb=`fOSI30s)o}uE=ilYC?IX`0r4mE$KA8#voM-lDiSkDTw3$r- zoN=9rOu?qI7zFKGkd$7e_ItalI_v7tpQQmiQuMKIE!SAJkG+P1vh9K4*+vibr3V(E z&yB)W-{%du$~@_7TA+jTcGm{o{H!u)x(CW0vuJ>0j43s(J%;!Pz^lRPOh>^SlLYc@ z(jk23w|xbzN&!}67eIJrydCZ+ zh>@fA46n6R!j>?Prs`fehSqxX1|w5<1=WQ_0nVhOU`jRpPQ8c!iaaBoQ`AsM{oY>S z-KS-Dn>*=&i*Qb}&fXY_zG}hM6TpW{58qATd@p6qp<2eh%N>LeBynZV$PNGn!D=I8Y&^=sF`!_SpT{ zYG)2+3`pF!`|||4`AV~g;D8Yr>$nYdfC3hIM>D8W8YbWgYbnU_0Q-%HrqKfPf?d7? z`oNT(c0i{FGr~awuK|{HvI7I(RXr2&Qg^$wzkgm(iXiaAG#!eRT;&5u&$_TC&O6`^ z#s#T>R4JtN9s4$REv>sI6?yhZ%Q>x(txF*SnA4r_esi6{P^SnLp4^pZvBJOJ0|^jA zDC)4yH-2|j6qvUFq}XwaB@@y|o|B$`&z1!gu?qmdo1{9Bg*#x!x!7{LGX(A>1$x{b z-vAa9{sUN)`qw_Gj6{Qo$a&A=i78WnzaP4(y0Z>|%9M8QUOuQ$Gc|3eL5j^5U1zZ&xBt0UW2dT8>DE>sxC1Obs;~#kaPb6Qt~ob*FF8$CI%eHpAmc8#NBFyqZ+m9Br`+|`YR$+gNM+2{kv&% zUOHU!o-P1Oc0HB7>lDfkDue*G;5?6uCtsyKZ+kk6x%S&rim>FHArH6OE ztKJC&72XID(43zfk_rIQJPL#z!Z=nOL>UF_#pJfzKV4xaJ#ON zDDo-44LM-wg!#%Buj^LVRrEvQcAastjjbn5%~(VCjo58!vrc!pn4xFCsc5OGJ71~K zD2h?;1x(!7xjr)Sq%G%-&~;;bCN-@NuMib<_idULgSjfzGv!M2BG>ATB9H(FaoKOW}Id#cD~VZHdC*T?sI zQj9DlHXo%0)2Q;BZPX56sL|%$TE9(2jwv{9sNQU5Bi%|g7(3k6 zT45VIrFjm0+*)&a_4G2fSG3OEyVN}$*9$FW>urm>D~Kc#a4!mhvAyiVs`U|9>-Eh) z%J@vFzYudw>#Jp6eR$s~y-4xZpI@oT1pnAT2HBGjkCu)M|9nuH%gQB~Rs3fThjnqL zEuZxh^6@&U_D6ht_Jmr>gthV3L*~J7QjFys|!Rl%I!yPURQevQ_N$IayFxLI*+sybdaWr^fww zT&KO3TyK|DDamAQ%GdCu<5*9Dil~hq+W?sS>Bc{|o%*reljznMYHQdZK{W5dvBJ!wLVx)5}1*dmF01jok6g;W5$?-3=^ zf!Z~%g8*jZF6&u2^@w%b}{qC1B4FX1Ww4ZlU-1SGihXGIXvA!46lO^|7I(>MEciRjBQ= zTeJAlG#m5kqx({;jkz@BG=U8rC_0iU6z|hI@C-ccvRefh92t%7^3>Hd&r>^*0atHo zh^0NVRku3t{QIt4AZES?RSU#miY+g|6;K&HqS}xdwbhKHY&0)B+lv3JL%N={O(lZ2 z&nAGy(^(52?76QzzPZ~0aic867J4;AKn|r0k3Y~$fO}Ija8vARGmH39;g0y4{=~J- zjkI7Ywzb(aJWU}8HEgqs%eS+&g2>@u^7%3;#k63jS8agxZEnpjCU$Q$hcSu@}+33qG&M(C3c?nc4S0GXeTKpT$Sh)hM<3a?;5RDqU)HrD7| zjNG=}eQd9w@Dg)%JuP|n%y5d2(PoJl?pjUINuV>6b5ipeQSmzaoV5WdznB?zz`_B) zRiWlj$mRu%tHXL~H4C+?2b#d#?AK-ud4_-XN!!)ljC+F$S18m=m&Gcw7UN?Op#pMp z?!zT?0NAl(jO|n)3>R)Wt%HNH@tK0Of@_M#v9OXxm2JBPiy!;?S1z@oL$%ND9LC+bYZlJ9wnkj zkBCn6J|ajEg3;R`B6^zWy>}vd?{_46)G%5wf*E}0vNh;<4calt-Xw10w<2zQsm2wt*|~ z$xCCAZmoc;9BhnxPY9z&*0^2>lFDggm(sle57pYz7r=x}0V&(Cl-qIO2E_B;lVAnG z8#$&V^|&W~Rnp4jzGjcAf_f;mL}=o^wECA;VgZ!sk)fdrH?5-#{i}#OyJ1!b3x0%sx*<%xjE_ zUY(8jpLx$1(?pWgSXrIDw%+@&=U_=P5!U`{O{OQHdN0;r z{J={7wuWXU?;2m<0_;Pz%tRQZFcKT2{`a&>YxAdvagDt|f$!(7{UY5`rKrNyA>N(v zL-!7Mwj;>9@FP4*VuKxs*2uXmmBz;=vu@QL4%9y%@Xi`@RE~{K+$s7pHAONJ(=7O#gfXoUr3cpwZ7^TbE@9|rywLA1kIn<5G zwf^_LtI}pXBWAOA6meKgcxLji)^bg7L#&DYVPR(@ewyS^`^!V-4J5+9RCPOKQmsYv_2tz%t>u;liaaeOQ*)ND9toSlf<1t2=PQST&v z$P+t%z?L!MmaCUY8C1(OMJ(Hj%U~i)>z+N>Cg#m0x*YWNmj}gG zT4C!eu94QC=9@YJJyk@O*8kq7si5qL8y5n2yqOzB9C+ac=7T$&jEUV{*c1~vMm?TP z&w9|(X_=D!vj_6|O(-)oSspXgNixQ0cD`7USj;Xz|9WdFU|-5(|HF{sEE>>7P z=g_Rv?|gO!0pJDHl@cmumyA2AUvf6DBle8N%yf8g;njmqtS|Hm_~)R#(CPQ8Hkv@V zEEF4+kV*tO`M`jxd0=(?+WK?PAs%Xk`WM6;{alqFPQpvwkkwWVa7WO2dGdiv86$qW z@MX%AtnHz{edPBRZEXx9J6;$z;3oOIry31dQfS$3+2wjJ(<+2dt zS0Y3WG-{+P09b!tBL$FdkDvcQfw4eti|YUzijmm}5&NJnjP$0bZZ99pl z4gXIvEZmw002Du3G+%wAT5?vX>n!BJMe-`pjy~|bj~`^&@j3GikmZ`Ku9*^}a422q zMQEi4cLG*tb0C-jw0Cmmc z-K>t|)k3&Xqqid70ss%3MaJK#AK17^pv6LCs0TmZ5hMKaA7%eU;y-!1U6Qmpy)>tj z+3gU(kJ44*H_a#iJ2z0=C<+Am+&2?);F5&=@puYZ9lZAN!QnsS_`!j{lu7Mb`fwA?; z#;;DJu9)!JUtja?;$++Z0Yd@dN%%f9O=Jetb}@T0+IeDw_sGe{Q^jtKCl1a5rVu|C zfYs>XvF)Dq#MPC~Q}%s)l=o@E3JKs?#lX2-ARe;<2r&$VX&+hvoD3fr4@!kz`gF}= zI*v3r|NF8$fGeXGgh@7C#avCQ-Ca!Oe27OVK(m3Rz6(RtN*r5d!|uSHNu zmzPe9XE}fh=fJLnci>{R%EnXoaT;$!@K_rDFI}isJX9k@L?BziH-(IY$iO)8P~u>8 zKE5&l@W9Q1#d!drf3qoq6c5zm)rbn7ci_P)$(o>9;IhFEQRyw5i{jbw@3rhUXc6gn zC;;Z_sQu@~Th~?{W;X4ZAL~Kc@gR7511cN_fXDKeS0^Z*fssEyXiqhGDJ5T5d2Z(K znye;5L_KAmIlX4?Cc~t>|8S#3)ji-QH&mjMlcpq@L+4Q@{XjI=3&p& zMa#$Np2(Fqlz$i)0q>Sk*9@yqU}TJ|gUeCsi-Fq+OHA-6n%De#i)H3=z!E0oFf?oP zfj1g~_sBq9unMa)dqPKGr^$@2ZFwlRaI{+`E=nY`DM}`TphiWhK${&)o3r}_b#}*P zAjqGtXhu3Al)9qFpFECss2-wG>h4Y_KS3AY24+?lKO)ELO?`IVwwzZUiUGu1k6M%Y zWx?538_9Tu2O9pm(?;dk19%F~K&H6WX2Q|Eb?g{WH|a02x(bABFS!YhfvO#{M#|^7 zV&Nk3&1#-B^tV7v5mBHb@J3AF4PPLC1=`S0tOo%(kXp0d#z87nrf<~c= zT=i3ozXp%3;<&#ym#>f6}|!d-;!6=dkiQZFPrJTc9dLv90ykMUOD2HOVDZ z)Ad;Z;1d7r9ZJ%pt*JAq4xr2x26}aIJq|_1Pi*}__OJfs`qHNkep-ufpaV+4qRDi~xGhAQJp(mT#Jy{Nz5!_30qlkBXD3BVL7a5I9Q( z2izid$XxmSSu>ans>8Y=H-@H*`k(@Xnzg*x8icfGZk$N>L>Tz_$hLd!TjWhHh2W-% zLG*$oIX8*7KGJr-rG`M`iEt>Cf~y7TQ9e=oM>h*5UG0}+8su@ktA&X)nQJ{I=_Gm4zZhXSQHwSYtD+WlL3o%kD zzaG4$l^n^IPZI~K5PQ=sXBw;&S`~^!y_MjR7y8xeUHFlKDT;3=@D~%NDz6K@BDWYx z3Dgqgdq}+H8+4UiDTO*sL!0aOmok)AU1T}1Yda}vLskfTfs2v}~gq#4Wf__;_* zw57hHQB2}ZC)vA~fHFij&y9}Q>KrjxBN2@theLW$jInpVhz$%q$&s)#!%4hMd4$L# zTI8gKZ7z;yioOdmsR~L%{vM)ZvI%mZ7S+U*KaWM9- zwq70h!i~+G(pHjg20BY+Q`r}Ra{f_U^svS@E+zB^+ea4Y^IL>1a)HW>0g8HvRw;;R z{LLJ*32OLfrmf4J^zvwgktUBTtT8ztm!8n>AQ= zvH3hl&a|lOxwht?-xRJcgH&kUCAs~6VkQ5ICW85(&B7%l`Q zcw8fy2w=JI+1vqve-Q1Y$b$5SMldXQGO}j_!PYb^uIk$%(eCfoA_x3yTBXY~_sfZ3 zBq;Lz8;~nadK6%@cqG$)t$ie*j(dd`8DJG?3D?yUjByW;;s2QvyAIf(#k1*&*l#!5 zn=f=(eaigJnoD10DJtWWJ81Q*T*cOC}=!51V(Sf13LSm&unJGeK_jN+J%>wiAB z+@Q4K7=oNAHER{nQ4Nyq=y4(y4XbxL zcM^?35qlu{lKJa7jQJ^z8*my~bK4WfNU1RtY}%Z zWh9-)A(A+Q`44tbTQefOZ+u@}dTkYlVoXmSfNpRrfsx8;_dqx+vor2-+aRsbQymPE zN`Iie3*ZdR$YyM7zno1IhDlmloJo&obB*c(HrjyWK_1EYC@zs`%i|*qbgRFLE+?va zFg%n=& zVmbq0-Ib`NQ}|3K&mOBW?n8AEA$44%I=X<>u9X*~=YG_Z-G=-8P`E@cl zK)y^6q)3QiQ*4@7fCj=n+K`V`$Oh#wT6^@KZFZh%g)#M8wz$5==3KgOXWD&|yGbl; zEtwENZBS8Umc5+HZ1q5jYRTW_sgCxntV?3uOEDeZ6NQ%X?c38CcqcQKJ>=XMdniGr zelpjpvbFQbZYZIGoweGS8>M%3jsbg?xG75nb`%jo;0m8j6g-q(n%+ZdEcR5Z2DOJgKNE-r#+Kye0b$@!0O6Iv*r zyOuoqdWAKNIzSx#0{DK|H#OjE4iO{DzNa3V z()32x>%`rMJ=Q1{=F?==gt@Enwgej#OM`@0L=jWq-kW(ChS48}7>Q6^ZGhUTOw4mP zG0(u479(};RXhV)?>fAm-Z7frzE$+x?rNDGK{Dx; zlhu)d-}ZJuuwffLNndyNpaNO2lBMoZHl^azN8)MH1#zoAS7(3FLH2w@tNkv~D;aIL zjiU{FTOCYxK;tP!jTlb#^)k3m`4#Jhu+0Tu``$FR^c!OT2Sp{>c(&hq`?N*jj>iwN zaLh{eQd)MZGb_5zy+X33clxMlTy5MWqhJ0IsHE0uiS@5Kj^p#mj1zdA*sgz((eGcK zaJ3(MJRu+Dv$>R*ILqzuT5kC+$dHa5WzZL9a6tx$({QYx-TCjnH(NQ_QMn2m+tYA87wFZID5pF45 zyDc%Iq8*Jz)D*l~sVS#Vg6*})o|i2b$lrHoyb_AhOZ#ySgBf=*E2`^tUb3rYwfAGW zM%cVH^+t|4f*srywu7tc8w{Sww3rF1>4%Kw%5R~j(TDbC;(aZ*I~aLZl$!A@X3NsM zQTRujs&*ytjFJ6!0nEbXc? zzYfcf4R!L++s*eKE>yQUe`$|V@-PcLII+C0K%79`zGVl!FdyuseSTx zFwn{wqHyUVxOd^+xYV{T?o~kl^*%1ue{({e@aSdCM$GAPk7X#|y~l}H2*RUpu^hPN z^HGb6o3|e)R>5=(+l~7pYcH9dporo3!BW5#1Slaa<-=(cJLGVYzgGVr2pCfZ=`&Vt zK^=`7`F@#y=F|AJfKJI&Y`_}c5xl!b5qfcmnM}M~58h_JrNz`F@3K~k*~IC=@@Ik{ zdJ}K>Hd4Y98%}(9-CG@y?{n|G4s&npQ5yY$luV?k3Vg>Fh*@x8yK%kJ$!S)D!b9?K z?WZdvU00$`;5(Zq$*(GmSLNjXoVvVWME^l&o<6;#UplU=}wV$~!-!5ZN#YnmzBFg*~48oFvuY(Oyjvd_2g z_Ri7tbe*z2T#^1Y$yQ*xG%HIi{_F0&IafQ|Lk#Xa;ZbdQ_>nYAw7V|pu%HL7SC0y< zr)@iR|9G~xd135e#Nx6tBd*Ss%W?nWx`W=TCn=0 z&8Sh7ED$HJ3)-&kU5=gGnubzEJV}wZS(I%UsnFY;FO_hm|1`Mbj#b{{ZYk1~UZ_Nz z#Y_#@AO5o}&HJ|g$7-RA90Q5T(j4EzSa;_K;`_n!69J9`kSrlO{ojti_kQ<{>e1!B zHb2|YjuAeZ6U{Dm+d=GYzQd>{D-5A`GiO=ixe&Wvt%~V0s#7)s2;9`tXdVq&6&#Uq z(Df-UFbG>yCGvH;{KV@W!s1y!m!iN&EoS8@;g(@`xsy%8M1rJKaY9i(Ut(Pwg`Mog zz%ciY%h58oIB6jZz^GmYUmOo5u|%oYjzmYK+T?1nPB&hSu5uL9fH6~7mGBIYd(BTh zB^hZ3b3NO@2)Er}E`1A|&WMn$gTdR7`=;n{qV1@TDQvDR@ras)A?kBX_;OLKV)h}JQT=z>m%E2?)@6V1o9Ojqi{#@C9RNe61St`z3k}5vm zZpki0s$}cTR3B^GHeHUc;@aCfrb|yAP0jNP4Jx)C488>K8h205+lHQ;pYwk0Tq+N> z*=#o=y=JQ9t{Vo`OxQ`Uq;jJ#F^#=&OaIN|Q#P1)cfjHDrQq*Zr}vr)k0Ty|S|*tr z#mn3%N^WCv^whn(7Honhg&7f6Tb(1B$Er&L|G1wA$UmA1*wnLW)EyjdAj{f3xtL2x zSb#i)wMfY*RiErl7fnuWr`P4eUF2uu1R1yWkvZh;3ZAdpL-$@t^|ldh@7ZL(ell&Q zh&J?S8oRZB z+;bmZ*#r)jtnk*Dx>Axpku4q#ewS7e?b|VJOk4Ejlc@QI%Jz<9aWUr?o)CoO)sM=J z!-fD@vEspm`$Xp@F6?1lN{vKH3e@=qp~J!F*Zgm(URocQE1)GMy=n5p8YV)bbmOQk zSoT|7iqK=F=}qno@Jqmg>BA{0b|SMov(Y?l+fY_m;q-(CZjlyC=b5%KV{DI zi*kF;v}_c6{vSs*}K@W>pP_TQ;w*!2tJ$)T@}& zyJ4E%q4$PpoS*w2zH8U%?HA$;99cCz zE<(%KfrY1#N&NY7>H{C|%blHAPo(YQ$O=BhkT#TWVPqP`o5MWb%DtpQz4YOu8U41Z zhRGTIP;}v+p@0b^1=9gQBz}5gH9t0%dnNg^&pU&3oxoisS>utE6#qPS9^j<()tU<( zuvu4kZ_kFdCeVpWjP<>l`_eX%!SxH>cEr-JO_y81rM7(i8=Ll+3a9Vbxb}Fk+ihae z7DmK*gfI*WC8Qj%%grIO$xH-xPi`zC`bORQuGVlW3ALgrRmbTzv5x7J_gt?cirIJ` zd*AXt2~VJezXX6k3eB!==})l86o3T1DgX*M&@}qF2xs2cdO9a%N_*cL&?8-s0GZ9n zzvkNayr?iq?|_E{z8ftJ1Ap$~;97nK8um$|zTOaMk$dYG>|zgPL^wLM^L&B?GbCPZ z-LRRve}72XAMjI@3xWPwvlk#yHodlU8$zZ&FZYT+Do&P~t&g-BWq%nDnIZg4f@~dC zX(KjH=K_%ZS|J0^zvfptN3H^g3@Qoih>tl5dDsPD7xq1xs3q*5C`ipJq#7g5!8FrD#ZE+fh2PD2X-FRUJ0*nITWm$i7vR z`TI8Z%VC;yN4xcXdp_s9(zsVq2Y>sqWU7lJ6~HNRex0(~gx7P)Gk05ByIwr+sC8B6 zxAzaW^+EhfP7BrZyYB$>i`HyDAZqHSrJ~Ifh?kuJ=93veu7fqtS@U-J`PtS$?jXiX zfg#LhO-Ig#6GN+@A-od)uLE1bwr$TKs<)H;j43|>w?t^Er=H(ov(R^M871HmYzbjI z`-Z0JGHDZ;O?ZMv#%(`|D|V#2W8KY&4Y5Yb6>r^M5Zo750KjtU%z<%Humf<)K`eBd z@m?*TsC7_fpn9?wfzh?rg{SUfT~fMixFLXFhPZmpq&k1`FO_}Q4Z`Q4S@ z9||N*%lpZ%s4oDBNf+Q%^OnRWO>dl~&RpFl5QRJvCyJQB&z~8y!2%#DR*SZFan<`~I38rr z+^?bxK`H|SWH#%g>V;HbX?eeask!vz;>?2{E=H+X_aRS89)O|e9oV5jl+^X>2mk1? z%8F-9^mGkdCHK@MunW6?fYPM{qG|V3R#W5+ZQdkZp^i}42jKYUhbAOR9oP3*KmQkj zkI91j4xD{fvqSaB*!S(drpTVy7VnvR6;E2pIwvh+2M&9FR|1hilI~kwT0p_91BZYq zNoMuh^72Qk)$wlNSv!Ltzv1jm54CUHs}EP+O0d|j3O+ynPI}#V)r)rJ%$GQgmhmdf zdhiR6%8|X|sc$69&(GiL^eG8s<5Cm(ys0r+>b$fdIT6ZJ@6Uu0etZ2|MJA%}kOlO4 z)$yLDemyywy8;h_Q4vQw=~X`I+$(2~JlMQ?-vRike{uiKbW*tAJa3r$J)(AGyD6ABzyVlvP$F$9@-hdQ|)A z4hRz3L=xSu)QZV1lWmvZI_SRhw{T z#B9y5W)a^1w&lex{eZB6`=OJ#9W+#|UhvU1a&T$N{Ma{HSYX_%r7S+BrZsHm*ABal zrURlh;IP%+)5t+lPDqm87q@JRiY9zs;y0Qt?L8jIhSX~0*kwhzz1&}wSm9tH8J9EO z9>e3Q6ubyASKA7A;7rB=?dN3%?2>DESxmOjn9^@vDLqR$WQOPLT>kWC9 z?=<5W>GRwx$-tvoooPyZ6V?xSsXF|CcOo(PQIzvCsLbsM2wLMMDCJNk{EB0Kz-SR9 zql z+V-Z|D?DaBJg8*HTxk@UB8U!KX|#WR2j2Rsu>M8x9Ek*+tC@-#KM1ki@+&UZwodvV zB;fCN=;qSAkx&K^<|PIGsau<~RN4!6PAMjY!+@6}2AtXWhQEl`QGsO+idb)gkc5N{ ztMUetcFTJsS)F;Uwa`JGmrQ2I!T#6}y4!B67jM4B2#4A)&XLx3+vTZdZ1KOQ$g)h{R!166?tYixw8G1{RISkQ;z14sAYQLgSCeo?!<4x2gt^H!T zcS5#m(fYEDTFlrplL*o4E%4N@z&U4wB;j|IEI6kcNhmul+x1gyu)@6MLgTzP`+I5* zOZx-af`&osR)>j5g$D$V#r?65n)ECyyjC-JH{WT*^yC6^BXZYP(t$8dJDMU+Ic_3B zHJTUwD?NdIK9dsV%`3Zhv-?cEQY|!&ni#HZ1o86lI|}VMPJ$(tJI)dq?D;m-C&&b@ zXvzXQi#11F4%omb^o2^m0iyjx*pzMf(VO>p6dxkDQ&~m&d50ZD6l|uXiuyp}WTa@tW4EW9Nf%!Kob(3> zRQ-IgXrY%XK!CTsuhrgOcI`@$Pcpw9K0hKElOr9&(&qTmOgrPqtl}_GxW1RoQrP9sRZEpwY7P zs)GKW-$}aGI~zU1u1rID@tBS6!asaJX5wdwbd333#sTf&-7)ZHjt;#um@v#QywP$p zc99u7Q&9}m@80<|EBY`c1Os4C$jedQA;Xum5YJr-f&gBEfKb9CUBaV)a>@((lX2l` z?tLru$Co~o!-^BuHhjwGJF!m3k)i&!AnDt%f>DK;TR%SgIVLprd{<8#mO8NdaoNJQ z6FtP>0;rm`RuBxxYG>Aed8;FMGrK&qIx0Y|WoUwa05k~N&U z-s9O4-9Chet-x-rbKM6NC9=bj8+F5Pm*+THOQTMwGuqZZAMI8z&8LXsK8Kz*K5RGo zsJe?yFQ32a^X24uC_M@~2R4ghA`|fd#hD@hcOjR5$v8aO*Q@0QOWK6D(SNSS9ZQUg zsK)B={ob|xCy>6VSJ}PYIKM33H(NN8=h&oDT@T@-^)gm&tvz@L+^PA~@PdMEwpCCb z08sc}mo=NIXIfwJ^m%QigD8L~K)mXYZem1PWN@p{f^!}&N9(yldYPM++bOCXz4c&c ztrUB*(Zl2B2e`g3rm&T@X|Mdufx<15Ps695)%*TviKvsI%hA^LcHd1k5k0sX30_Wp z@s96-3~-=1FOmAN+i)RF7iS!)4?r{Khd-KzO%3|dC(2zuBxAXb3>GX=tR;<fEUR=`O(j%|q74w?TJG3G2+FSm%5{dZ1~kSGxWrDQ?sc{F&0L zW~aDodujHbO}uhGo9}eDGC1S;1*)sj)qtBl(BE(~fHq}PPr^-Zx`@2edn;^u34Jtw zzhyL^BW9y41eImgd21}q$+PTmhVOoyJG|%))Pfi}CR%IO8i*TnHj$*%(SJFc-ztbQ z#G1SGy479>xs*rVl7~xCvzGa%6v2QP$bhvZa%Ne=Qm(#e2N7hWN<*CWNmT zb1E6nnnIpR;y6kzq=Ys^FB1KAZgy5%o#n$>pKP|;S%eL6H(P{hIIm*vXT_7Kc`9{W zR`@xleD?Fn3zW_(Jf&aCxxfbe!?udvoVjx9ZCPi(ysK>dP`Yum&IP?2>|**fsY2jG z*~!CjPv~a=h<#Oi^Lceor6l>(^}J~C!qj6Uuob9Ae4gs=uZTLck4E6sd^WQLEo>Uc zG?|@04nxxS>&o}D7vtF=`ZeT#o zuBGg*Q_;N3Ao}}EcDml7INhlBar@B^ef6mpm>b4|$)Yr?QS)MfWl2|YzwT=d`ta;e z!roq{OXuL|h}H0@UHNLsHX3`3>3qjp0%SPU6bd|}nkss5b=VMpHosKu&QsK+Of|(L zZ)C4Ob9p|nVp9LAT=Ed46x`RsHO-i7@zF?<-NMK4n(gA%S+Ue5LYBbUUJf1UhJIZ} z!b5_2Ugj*)d6sI9b!v~DejpC|NQ>U^OEj6G?86>^3%ue&8|Jylk4Tkce5}wni^SMM z4*gw@@4mgVGUh$|a~#fpEmG+aNY9COR-7eE7xa!A?@*>u+_dK?e z_rKW7`U)AbBxu2xJ^lMAX&nkn;qTf45B%o;R=(u;TfYbYCCC45`uE}!{yQZgT?PLW z=mH!T{`V8U;M9K};KtQ|Kc)VyeuMu7xC;B<@9yCfg8n`L5B~Slv%jTt@V`9%-%tPi z&3ndw_qQA`{sV9i5T9y|fBtAV7qFc@WPE{|X773jeAZfCx(eDr$fV|5_5f zK>TZq0V4eCEZ|w;UuOXz!oSV}o)!LIb{1%W_b2|}$l+h6{{Mif=RygiRhJaGZ4oPY O?$l7zeORRe4gVjNQ*cWF literal 0 HcmV?d00001 diff --git a/salvo/image-rescaler/src/main.rs b/salvo/image-rescaler/src/main.rs new file mode 100644 index 00000000..60c69ba5 --- /dev/null +++ b/salvo/image-rescaler/src/main.rs @@ -0,0 +1,26 @@ +use salvo::prelude::*; + +const IMAGE: &[u8] = include_bytes!("logo-square.png"); + +#[handler] +async fn get_image(req: &mut Request, res: &mut Response) { + let width = req.param::("width").unwrap(); + let height = req.param::("height").unwrap(); + + let img = image::load_from_memory_with_format(IMAGE, image::ImageFormat::Png).unwrap(); + let img = img.resize_exact(width, height, image::imageops::FilterType::Triangle); + let mut buffer = std::io::BufWriter::new(std::io::Cursor::new(Vec::new())); + img.write_to(&mut buffer, image::ImageOutputFormat::Png) + .unwrap(); + let bytes = buffer.into_inner().unwrap().into_inner(); + + res.add_header("content-type", "image/png", true).unwrap(); + let _ = res.write_body(bytes); +} + +#[shuttle_runtime::main] +async fn salvo() -> shuttle_salvo::ShuttleSalvo { + let router = Router::with_path("/").get(get_image); + + Ok(router.into()) +} From 88b5aae77edbf505a6cedea0333fe2ecf560b297 Mon Sep 17 00:00:00 2001 From: Joshua Mo <102877324+joshua-mo-143@users.noreply.github.com> Date: Fri, 16 Feb 2024 17:16:51 +0000 Subject: [PATCH 138/239] feat: htmx template (#138) * feat: htmx template * formatting, nits * amendment: add links between html pages --------- Co-authored-by: jonaro00 <54029719+jonaro00@users.noreply.github.com> --- README.md | 1 + axum/htmx-crud/.gitignore | 3 + axum/htmx-crud/.prettierrc.toml | 1 + axum/htmx-crud/Cargo.toml | 17 ++++ axum/htmx-crud/README.md | 3 + axum/htmx-crud/migrations/0000_init.sql | 4 + axum/htmx-crud/src/errors.rs | 34 +++++++ axum/htmx-crud/src/main.rs | 18 ++++ axum/htmx-crud/src/models.rs | 24 +++++ axum/htmx-crud/src/router.rs | 30 ++++++ axum/htmx-crud/src/routes.rs | 116 ++++++++++++++++++++++++ axum/htmx-crud/src/templates.rs | 22 +++++ axum/htmx-crud/templates/base.html | 20 ++++ axum/htmx-crud/templates/index.html | 31 +++++++ axum/htmx-crud/templates/stream.html | 9 ++ axum/htmx-crud/templates/styles.css | 13 +++ axum/htmx-crud/templates/todo.html | 14 +++ axum/htmx-crud/templates/todos.html | 14 +++ 18 files changed, 374 insertions(+) create mode 100644 axum/htmx-crud/.gitignore create mode 100644 axum/htmx-crud/.prettierrc.toml create mode 100644 axum/htmx-crud/Cargo.toml create mode 100644 axum/htmx-crud/README.md create mode 100644 axum/htmx-crud/migrations/0000_init.sql create mode 100644 axum/htmx-crud/src/errors.rs create mode 100644 axum/htmx-crud/src/main.rs create mode 100644 axum/htmx-crud/src/models.rs create mode 100644 axum/htmx-crud/src/router.rs create mode 100644 axum/htmx-crud/src/routes.rs create mode 100644 axum/htmx-crud/src/templates.rs create mode 100644 axum/htmx-crud/templates/base.html create mode 100644 axum/htmx-crud/templates/index.html create mode 100644 axum/htmx-crud/templates/stream.html create mode 100644 axum/htmx-crud/templates/styles.css create mode 100644 axum/htmx-crud/templates/todo.html create mode 100644 axum/htmx-crud/templates/todos.html diff --git a/README.md b/README.md index d3176c1f..ebcde9f4 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ Actix Web | [clerk](./actix-web/clerk/) | A React + Tailwind app that uses Clerk Actix Web | [websocket-actorless](./actix-web/websocket-actorless/) | Websocket app that checks the status of Shuttle's API | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/websocket-actorless` Actix Web | [cookie-authentication](./actix-web/cookie-authentication/) | Use JWT to authenticate API endpoints | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/cookie-authentication` Axum | [hello-world](./axum/hello-world/) | Hello World | `cargo shuttle init --template axum` +Axum | [htmx-crud](./axum/htmx-crud/) | htmx CRUD app | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/htmx-crud` Axum | [metadata](./axum/metadata/) | Simple app that prints the service information such as Shuttle service name | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/metadata` Axum | [qdrant](./axum/qdrant/) | Barebones example of the shuttle-qdrant plugin | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/qdrant` Axum | [static-files](./axum/static-files/) | Hello World page that serves static HTML and JS files | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/static-files` diff --git a/axum/htmx-crud/.gitignore b/axum/htmx-crud/.gitignore new file mode 100644 index 00000000..e8541fe9 --- /dev/null +++ b/axum/htmx-crud/.gitignore @@ -0,0 +1,3 @@ +/target +.shuttle-storage +Secrets*.toml diff --git a/axum/htmx-crud/.prettierrc.toml b/axum/htmx-crud/.prettierrc.toml new file mode 100644 index 00000000..3d14781e --- /dev/null +++ b/axum/htmx-crud/.prettierrc.toml @@ -0,0 +1 @@ +tabWidth = 4 diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml new file mode 100644 index 00000000..6e15b545 --- /dev/null +++ b/axum/htmx-crud/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "htmx" +version = "0.1.0" +edition = "2021" + +[dependencies] +askama = { version = "0.12.1", features = ["with-axum"] } +askama_axum = "0.4.0" +axum = "0.7.4" +serde = { version = "1.0.189", features = ["derive"] } +serde_json = "1.0.107" +shuttle-axum = "0.38.0" +shuttle-runtime = "0.38.0" +shuttle-shared-db = { version = "0.38.0", features = ["postgres", "sqlx"] } +sqlx = { version = "0.7.2", features = ["runtime-tokio-rustls", "postgres"] } +tokio = "1.28.2" +tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/htmx-crud/README.md b/axum/htmx-crud/README.md new file mode 100644 index 00000000..ebbc3114 --- /dev/null +++ b/axum/htmx-crud/README.md @@ -0,0 +1,3 @@ +# Axum + htmx + +This is an example of how you can use Shuttle with Axum, Askama and htmx to create a frontend that's easily extendable and requires zero framework knowledge, while being able to easily inject variables from the backend into the frontend. diff --git a/axum/htmx-crud/migrations/0000_init.sql b/axum/htmx-crud/migrations/0000_init.sql new file mode 100644 index 00000000..07eb5c7a --- /dev/null +++ b/axum/htmx-crud/migrations/0000_init.sql @@ -0,0 +1,4 @@ +CREATE TABLE IF NOT EXISTS todos ( + id SERIAL PRIMARY KEY, + description TEXT NOT NULL +); diff --git a/axum/htmx-crud/src/errors.rs b/axum/htmx-crud/src/errors.rs new file mode 100644 index 00000000..8bb17035 --- /dev/null +++ b/axum/htmx-crud/src/errors.rs @@ -0,0 +1,34 @@ +use axum::http::StatusCode; +use axum::response::{IntoResponse, Response}; + +pub enum ApiError { + SQLError(sqlx::Error), + HTTPError(axum::http::Error), +} + +impl IntoResponse for ApiError { + fn into_response(self) -> Response { + match self { + Self::SQLError(e) => { + (StatusCode::INTERNAL_SERVER_ERROR, format!("SQL error: {e}")).into_response() + } + Self::HTTPError(e) => ( + StatusCode::INTERNAL_SERVER_ERROR, + format!("HTTP error: {e}"), + ) + .into_response(), + } + } +} + +impl From for ApiError { + fn from(e: sqlx::Error) -> Self { + Self::SQLError(e) + } +} + +impl From for ApiError { + fn from(e: axum::http::Error) -> Self { + Self::HTTPError(e) + } +} diff --git a/axum/htmx-crud/src/main.rs b/axum/htmx-crud/src/main.rs new file mode 100644 index 00000000..d46d95ef --- /dev/null +++ b/axum/htmx-crud/src/main.rs @@ -0,0 +1,18 @@ +use sqlx::PgPool; +mod errors; +mod models; +mod router; +mod routes; +mod templates; + +#[shuttle_runtime::main] +async fn main(#[shuttle_shared_db::Postgres] db: PgPool) -> shuttle_axum::ShuttleAxum { + sqlx::migrate!() + .run(&db) + .await + .expect("Looks like something went wrong with migrations :("); + + let router = router::init_router(db); + + Ok(router.into()) +} diff --git a/axum/htmx-crud/src/models.rs b/axum/htmx-crud/src/models.rs new file mode 100644 index 00000000..b66c3c6b --- /dev/null +++ b/axum/htmx-crud/src/models.rs @@ -0,0 +1,24 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Serialize, Debug)] +pub enum MutationKind { + Create, + Delete, +} + +#[derive(Clone, Serialize, Debug)] +pub struct TodoUpdate { + pub mutation_kind: MutationKind, + pub id: i32, +} + +#[derive(sqlx::FromRow, Serialize, Deserialize)] +pub struct Todo { + pub id: i32, + pub description: String, +} + +#[derive(sqlx::FromRow, Serialize, Deserialize)] +pub struct TodoNew { + pub description: String, +} diff --git a/axum/htmx-crud/src/router.rs b/axum/htmx-crud/src/router.rs new file mode 100644 index 00000000..de84cb24 --- /dev/null +++ b/axum/htmx-crud/src/router.rs @@ -0,0 +1,30 @@ +use crate::models::TodoUpdate; +use axum::{ + routing::{delete, get}, + Extension, Router, +}; +use sqlx::PgPool; + +use crate::routes; +use tokio::sync::broadcast::{channel, Sender}; +pub type TodosStream = Sender; + +#[derive(Clone)] +pub struct AppState { + pub db: PgPool, +} + +pub fn init_router(db: PgPool) -> Router { + let (tx, _rx) = channel::(10); + let state = AppState { db }; + + Router::new() + .route("/", get(routes::home)) + .route("/stream", get(routes::stream)) + .route("/styles.css", get(routes::styles)) + .route("/todos", get(routes::fetch_todos).post(routes::create_todo)) + .route("/todos/:id", delete(routes::delete_todo)) + .route("/todos/stream", get(routes::handle_stream)) + .with_state(state) + .layer(Extension(tx)) +} diff --git a/axum/htmx-crud/src/routes.rs b/axum/htmx-crud/src/routes.rs new file mode 100644 index 00000000..7d4cd504 --- /dev/null +++ b/axum/htmx-crud/src/routes.rs @@ -0,0 +1,116 @@ +use axum::{ + extract::{Path, State}, + http::StatusCode, + response::{sse::Event, IntoResponse, Response, Sse}, + Extension, Form, +}; +use serde_json::json; +use std::convert::Infallible; +use std::time::Duration; +use tokio_stream::wrappers::BroadcastStream; +use tokio_stream::{Stream, StreamExt as _}; + +use crate::models::{MutationKind, Todo, TodoNew, TodoUpdate}; +use crate::{errors::ApiError, router::AppState, router::TodosStream, templates}; + +pub async fn home() -> impl IntoResponse { + templates::HelloTemplate +} + +pub async fn stream() -> impl IntoResponse { + templates::StreamTemplate +} + +pub async fn fetch_todos(State(state): State) -> Result { + let todos = sqlx::query_as::<_, Todo>("SELECT * FROM TODOS") + .fetch_all(&state.db) + .await?; + + Ok(templates::Records { todos }) +} + +pub async fn styles() -> Result { + let response = Response::builder() + .status(StatusCode::OK) + .header("Content-Type", "text/css") + .body(include_str!("../templates/styles.css").to_owned())?; + + Ok(response) +} + +pub async fn create_todo( + State(state): State, + Extension(tx): Extension, + Form(form): Form, +) -> impl IntoResponse { + let todo = sqlx::query_as::<_, Todo>( + "INSERT INTO TODOS (description) VALUES ($1) RETURNING id, description", + ) + .bind(form.description) + .fetch_one(&state.db) + .await + .unwrap(); + + if tx + .send(TodoUpdate { + mutation_kind: MutationKind::Create, + id: todo.id, + }) + .is_err() + { + eprintln!( + "Record with ID {} was created but nobody's listening to the stream!", + todo.id + ); + } + + templates::TodoNewTemplate { todo } +} +pub async fn delete_todo( + State(state): State, + Path(id): Path, + Extension(tx): Extension, +) -> Result { + sqlx::query("DELETE FROM TODOS WHERE ID = $1") + .bind(id) + .execute(&state.db) + .await?; + + if tx + .send(TodoUpdate { + mutation_kind: MutationKind::Delete, + id, + }) + .is_err() + { + eprintln!( + "Record with ID {} was deleted but nobody's listening to the stream!", + id + ); + } + + Ok(StatusCode::OK) +} + +pub async fn handle_stream( + Extension(tx): Extension, +) -> Sse>> { + let rx = tx.subscribe(); + + let stream = BroadcastStream::new(rx); + + Sse::new( + stream + .map(|msg| { + let msg = msg.unwrap(); + let json = format!("
    {}
    ", json!(msg)); + Event::default().data(json) + }) + .map(Ok), + ) + .keep_alive( + axum::response::sse::KeepAlive::new() + .interval(Duration::from_secs(600)) + .text("keep-alive-text"), + ) +} diff --git a/axum/htmx-crud/src/templates.rs b/axum/htmx-crud/src/templates.rs new file mode 100644 index 00000000..71043986 --- /dev/null +++ b/axum/htmx-crud/src/templates.rs @@ -0,0 +1,22 @@ +use crate::models; +use askama::Template; + +#[derive(Template)] +#[template(path = "index.html")] +pub struct HelloTemplate; + +#[derive(Template)] +#[template(path = "stream.html")] +pub struct StreamTemplate; + +#[derive(Template)] +#[template(path = "todos.html")] +pub struct Records { + pub todos: Vec, +} + +#[derive(Template)] +#[template(path = "todo.html")] +pub struct TodoNewTemplate { + pub todo: models::Todo, +} diff --git a/axum/htmx-crud/templates/base.html b/axum/htmx-crud/templates/base.html new file mode 100644 index 00000000..8fc76960 --- /dev/null +++ b/axum/htmx-crud/templates/base.html @@ -0,0 +1,20 @@ + + + + + + {% block title %}{{ title }} - My Site{% endblock %} + {% block head %}{% endblock %} + + +
    + {% block content %} +

    Placeholder content

    + {% endblock %} +
    + + diff --git a/axum/htmx-crud/templates/index.html b/axum/htmx-crud/templates/index.html new file mode 100644 index 00000000..39998222 --- /dev/null +++ b/axum/htmx-crud/templates/index.html @@ -0,0 +1,31 @@ +{% extends "base.html" %} {% block title %}Index{% endblock %} {% block content +%} +

    Shuttle Todos - Home

    +
    Event stream +

    Shuttle Todos

    +
    + + +
    +
    + Loading... +
    +{% endblock %} diff --git a/axum/htmx-crud/templates/stream.html b/axum/htmx-crud/templates/stream.html new file mode 100644 index 00000000..7ba981a7 --- /dev/null +++ b/axum/htmx-crud/templates/stream.html @@ -0,0 +1,9 @@ +{% extends "base.html" %} {% block title %} Server Sent Event Stream {% endblock %} {% block +content %} +

    Shuttle Todos - Event Stream

    +Home +

    Live changes to the todo list will appear below.

    +
    +
    +
    +{% endblock %} diff --git a/axum/htmx-crud/templates/styles.css b/axum/htmx-crud/templates/styles.css new file mode 100644 index 00000000..3a0090ae --- /dev/null +++ b/axum/htmx-crud/templates/styles.css @@ -0,0 +1,13 @@ +#content { + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; +} + +table, +th, +td { + border: 1px solid black; + padding: 0.25rem; +} diff --git a/axum/htmx-crud/templates/todo.html b/axum/htmx-crud/templates/todo.html new file mode 100644 index 00000000..68796997 --- /dev/null +++ b/axum/htmx-crud/templates/todo.html @@ -0,0 +1,14 @@ +
    {{ todo.id }}{{ todo.description }} + +
    + + + + + + + + + {% for todo in todos %} {% include "todo.html" %} {% endfor %} + +
    IDDescriptionDelete
    +
    From 1730b7bd41373825d9adbd7aeb97c38a53d0ca41 Mon Sep 17 00:00:00 2001 From: Xuanwo Date: Sat, 17 Feb 2024 01:17:59 +0800 Subject: [PATCH 139/239] feat: Add opendal hello world example (#142) * feat: Add opendal hello world example Signed-off-by: Xuanwo * Move into rocket Signed-off-by: Xuanwo * Update rocket/opendal-memory/README.md --------- Signed-off-by: Xuanwo --- README.md | 1 + rocket/opendal-memory/Cargo.toml | 13 ++++++++ rocket/opendal-memory/README.md | 10 ++++++ rocket/opendal-memory/Shuttle.toml | 1 + rocket/opendal-memory/src/main.rs | 51 ++++++++++++++++++++++++++++++ 5 files changed, 76 insertions(+) create mode 100644 rocket/opendal-memory/Cargo.toml create mode 100644 rocket/opendal-memory/README.md create mode 100644 rocket/opendal-memory/Shuttle.toml create mode 100644 rocket/opendal-memory/src/main.rs diff --git a/README.md b/README.md index ebcde9f4..e5eb4a67 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ Rocket | [secrets](./rocket/secrets/) | Extract secrets from your Secrets.toml f Rocket | [static-files](./rocket/static-files/) | Hello World page that serves static HTML and JS files | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/static-files` Rocket | [url-shortener](./rocket/url-shortener/) | URL shortener with Postgres storage | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/url-shortener` Rocket | [workspace](./rocket/workspace/) | A cargo workspace where one crate is a Shuttle service | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/workspace` +Rocket | [opendal-memory](./rocket/opendal-memory/) | app with an OpenDAL memory storage | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/opendal-memory` Salvo | [hello-world](./salvo/hello-world/) | Hello World | `cargo shuttle init --template salvo` Salvo | [image-rescaler](./salvo/image-rescaler/) | Hello World | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder salvo/image-rescaler` Serenity | [hello-world](./serenity/hello-world/) | Hello World Discord bot | `cargo shuttle init --template serenity` diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml new file mode 100644 index 00000000..e0fdbd7e --- /dev/null +++ b/rocket/opendal-memory/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "opendal-memory" +version = "0.1.0" +edition = "2021" + +[dependencies] +shuttle-runtime = "0.39.0" +shuttle-opendal = "0.39.0" +tokio = "1.26.0" +shuttle-rocket = "0.39.0" +opendal = "0.45.0" +rocket = { version = "0.5.0", features = ["json"] } +serde = { version = "1.0.148", features = ["derive"] } diff --git a/rocket/opendal-memory/README.md b/rocket/opendal-memory/README.md new file mode 100644 index 00000000..06a36220 --- /dev/null +++ b/rocket/opendal-memory/README.md @@ -0,0 +1,10 @@ +# OpenDAL Memory Storage + +This example shows that how to connect to an in-memory storage using OpenDAL. + +## Project structure + +The project consists of the following files + +- `Shuttle.toml` contains the name of the app +- `src/main.rs` is where all the magic happens - it creates a Shuttle service with two endpoints: one for adding new data and one for retrieving it back. diff --git a/rocket/opendal-memory/Shuttle.toml b/rocket/opendal-memory/Shuttle.toml new file mode 100644 index 00000000..d823d288 --- /dev/null +++ b/rocket/opendal-memory/Shuttle.toml @@ -0,0 +1 @@ +name = "rocket-opendal-memory-example-app" diff --git a/rocket/opendal-memory/src/main.rs b/rocket/opendal-memory/src/main.rs new file mode 100644 index 00000000..7e5d32a7 --- /dev/null +++ b/rocket/opendal-memory/src/main.rs @@ -0,0 +1,51 @@ +#[macro_use] +extern crate rocket; + +use rocket::response::status::BadRequest; +use rocket::State; + +use opendal::Operator; + +struct MyState { + storage: Operator, +} + +#[post("/", data = "")] +async fn add( + path: String, + data: String, + state: &State, +) -> Result> { + let bs = data.into_bytes(); + let length = bs.len(); + + state + .storage + .write(&path, bs) + .await + .map_err(|e| BadRequest(e.to_string()))?; + Ok(format!("path {path} written {}B data", length)) +} + +#[get("/")] +async fn retrieve(path: String, state: &State) -> Result> { + let bs = state + .storage + .read(&path) + .await + .map_err(|e| BadRequest(e.to_string()))?; + let data = String::from_utf8_lossy(&bs).to_string(); + Ok(data) +} + +#[shuttle_runtime::main] +async fn rocket( + #[shuttle_opendal::Opendal(scheme = "memory")] storage: Operator, +) -> shuttle_rocket::ShuttleRocket { + let state = MyState { storage }; + let rocket = rocket::build() + .mount("/", routes![retrieve, add]) + .manage(state); + + Ok(rocket.into()) +} From 20c9dff13b3aec4a09f7586cef4c8cc39b575631 Mon Sep 17 00:00:00 2001 From: Marvin Juraschka Date: Thu, 22 Feb 2024 20:56:16 +0100 Subject: [PATCH 140/239] --idle-minutes 0 added at start (#141) --- fullstack-templates/saas/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fullstack-templates/saas/package.json b/fullstack-templates/saas/package.json index 5fd9ee3e..a2589597 100644 --- a/fullstack-templates/saas/package.json +++ b/fullstack-templates/saas/package.json @@ -9,7 +9,8 @@ "build": "next build && cargo build", "shuttle-login": "cargo shuttle login", "full": "cargo shuttle run --port 8001", - "start": "cargo shuttle project start", + "start": "cargo shuttle project start --idle-minutes 0", + "restart": "cargo shuttle project restart --idle-minutes 0", "stop": "cargo shuttle project stop", "deploy": "npm run build && cargo shuttle deploy --allow-dirty", "lint": "next lint" From b82ff312e879a58a000bdfd4b41b6d8bad1be47b Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Mon, 4 Mar 2024 16:49:47 +0100 Subject: [PATCH 141/239] chore: v0.40.0 (#147) * chore: v0.40.0 * fix: axum htmx versions * feat: update pdo example to 0.40.0 --- actix-web/clerk/backend/Cargo.toml | 6 +-- actix-web/cookie-authentication/Cargo.toml | 4 +- actix-web/hello-world/Cargo.toml | 4 +- actix-web/postgres/Cargo.toml | 6 +-- actix-web/static-files/Cargo.toml | 4 +- actix-web/websocket-actorless/Cargo.toml | 4 +- axum/hello-world/Cargo.toml | 4 +- axum/htmx-crud/Cargo.toml | 6 +-- axum/jwt-authentication/Cargo.toml | 4 +- axum/metadata/Cargo.toml | 6 +-- axum/postgres/Cargo.toml | 6 +-- axum/qdrant/Cargo.toml | 6 +-- axum/static-files/Cargo.toml | 4 +- axum/static-next-server/Cargo.toml | 4 +- axum/turso/Cargo.toml | 6 +-- axum/websocket/Cargo.toml | 4 +- axum/with-state/Cargo.toml | 4 +- custom-resource/pdo/Cargo.toml | 8 ++-- custom-resource/pdo/src/lib.rs | 48 ++++++++++---------- custom-resource/pdo/src/main.rs | 2 +- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 +- fullstack-templates/saas/backend/Cargo.toml | 8 ++-- next/hello-world/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 6 +-- poem/hello-world/Cargo.toml | 4 +- poem/mongodb/Cargo.toml | 6 +-- poem/postgres/Cargo.toml | 6 +-- poise/hello-world/Cargo.toml | 6 +-- rocket/dyn-templates/Cargo.toml | 4 +- rocket/hello-world/Cargo.toml | 4 +- rocket/jwt-authentication/Cargo.toml | 4 +- rocket/opendal-memory/Cargo.toml | 6 +-- rocket/persist/Cargo.toml | 6 +-- rocket/postgres/Cargo.toml | 6 +-- rocket/secrets/Cargo.toml | 6 +-- rocket/static-files/Cargo.toml | 4 +- rocket/url-shortener/Cargo.toml | 6 +-- rocket/workspace/hello-world/Cargo.toml | 4 +- salvo/hello-world/Cargo.toml | 4 +- salvo/image-rescaler/Cargo.toml | 4 +- serenity/hello-world/Cargo.toml | 6 +-- serenity/postgres/Cargo.toml | 8 ++-- thruster/hello-world/Cargo.toml | 4 +- thruster/postgres/Cargo.toml | 6 +-- tide/hello-world/Cargo.toml | 4 +- tide/postgres/Cargo.toml | 6 +-- tower/hello-world/Cargo.toml | 4 +- tracing/custom-tracing-subscriber/Cargo.toml | 4 +- warp/hello-world/Cargo.toml | 4 +- 50 files changed, 145 insertions(+), 143 deletions(-) diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml index 20502aeb..95dd4397 100644 --- a/actix-web/clerk/backend/Cargo.toml +++ b/actix-web/clerk/backend/Cargo.toml @@ -10,6 +10,6 @@ clerk-rs = "0.2.3" openssl-sys = { version = "0.9.9", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.39.0" -shuttle-runtime = "0.39.0" -shuttle-secrets = "0.39.0" +shuttle-actix-web = "0.40.0" +shuttle-runtime = "0.40.0" +shuttle-secrets = "0.40.0" diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index bfa9755f..7dd86b57 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.6.0" actix-session = { version = "0.8.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-actix-web = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 2dc6b7ed..4a58a27b 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-actix-web = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 81f48151..25004d9f 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-actix-web = "0.40.0" +shuttle-runtime = "0.40.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.39.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.40.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index 24c7e4bb..eab9325f 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-actix-web = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 4248ca41..ada84ef6 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-actix-web = "0.40.0" +shuttle-runtime = "0.40.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 17c5df6d..c450568a 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-axum = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.28.2" tracing = "0.1.40" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index 6e15b545..1f46fb25 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -9,9 +9,9 @@ askama_axum = "0.4.0" axum = "0.7.4" serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.38.0" -shuttle-runtime = "0.38.0" -shuttle-shared-db = { version = "0.38.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.40.0" +shuttle-runtime = "0.40.0" +shuttle-shared-db = { version = "0.40.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.2", features = ["runtime-tokio-rustls", "postgres"] } tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index fca3ddbd..d304836e 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-axum = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index d83736d4..130e9ac3 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.39.0" -shuttle-runtime = "0.39.0" -shuttle-metadata = "0.39.0" +shuttle-axum = "0.40.0" +shuttle-runtime = "0.40.0" +shuttle-metadata = "0.40.0" tokio = "1.28.2" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 4b24e511..10ac15b3 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.39.0" -shuttle-runtime = "0.39.0" -shuttle-shared-db = { version = "0.39.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.40.0" +shuttle-runtime = "0.40.0" +shuttle-shared-db = { version = "0.40.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index 25ab93b7..dd0bef76 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.7.0" -shuttle-axum = "0.39.0" -shuttle-qdrant = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-axum = "0.40.0" +shuttle-qdrant = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index bb0bf96e..c3778e5e 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-axum = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml index 39824aaa..1ce5c054 100644 --- a/axum/static-next-server/Cargo.toml +++ b/axum/static-next-server/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-axum = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.26.0" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 5c1a30a1..1d8afcb0 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.39.0" -shuttle-runtime = "0.39.0" -shuttle-turso = "0.39.0" +shuttle-axum = "0.40.0" +shuttle-runtime = "0.40.0" +shuttle-turso = "0.40.0" libsql = "0.2.0" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index d6e430c3..56edc816 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-axum = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml index 52e30d7c..7be0b2ed 100644 --- a/axum/with-state/Cargo.toml +++ b/axum/with-state/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-axum = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.26.0" diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index ad972835..c557a180 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] async-trait = "0.1.56" axum = "0.7.3" -serde = { version = "1.0.148", default-features = false, features = ["derive"] } -shuttle-service = "0.39.0" -shuttle-axum = "0.39.0" -shuttle-runtime = "0.39.0" +serde = { version = "1", features = ["derive"] } +shuttle-service = "0.40.0" +shuttle-axum = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.28.2" diff --git a/custom-resource/pdo/src/lib.rs b/custom-resource/pdo/src/lib.rs index def29563..13b07c78 100644 --- a/custom-resource/pdo/src/lib.rs +++ b/custom-resource/pdo/src/lib.rs @@ -1,43 +1,45 @@ use async_trait::async_trait; -use serde::Serialize; -use shuttle_service::{resource::Type, Error, Factory, IntoResource, ResourceBuilder}; +use serde::{Serialize, Deserialize}; +use shuttle_service::{Error, IntoResource, ResourceFactory, ResourceInputBuilder}; -#[derive(Default, Serialize)] +#[derive(Default)] pub struct Builder { - name: String, -} - -pub struct Pdo { - pub name: String, + field: String, } impl Builder { - /// Name to give resource - pub fn name(mut self, name: &str) -> Self { - self.name = name.to_string(); + // Make a setter method for each field in the builder + pub fn field(mut self, field: &str) -> Self { + self.field = field.to_string(); self } } +#[derive(Serialize, Deserialize)] +pub struct InputType { + name: String, +} + #[async_trait] -impl ResourceBuilder for Builder { - const TYPE: Type = Type::Custom; - type Config = Self; - type Output = String; +impl ResourceInputBuilder for Builder { + // Read the trait docs for explanations of these types + type Input = InputType; + type Output = InputType; - fn config(&self) -> &Self::Config { - self + async fn build(self, _factory: &ResourceFactory) -> Result { + // factory can be used to get metadata from Shuttle + Ok(InputType { name: self.field }) } +} - async fn output(self, _factory: &mut dyn Factory) -> Result { - // factory can be used to get resources from Shuttle - Ok(self.name) - } +pub struct Pdo { + pub name: String, } #[async_trait] -impl IntoResource for String { +impl IntoResource for InputType { async fn into_resource(self) -> Result { - Ok(Pdo { name: self }) + // connection or setup logic can be handled here + Ok(Pdo { name: self.name }) } } diff --git a/custom-resource/pdo/src/main.rs b/custom-resource/pdo/src/main.rs index a74326f3..14535844 100644 --- a/custom-resource/pdo/src/main.rs +++ b/custom-resource/pdo/src/main.rs @@ -7,7 +7,7 @@ async fn hello_world(State(pdo): State>) -> String { } #[shuttle_runtime::main] -async fn axum(#[Builder(name = "John")] pdo: Pdo) -> shuttle_axum::ShuttleAxum { +async fn axum(#[Builder(field = "value")] pdo: Pdo) -> shuttle_axum::ShuttleAxum { let state = Arc::new(pdo); let router = Router::new().route("/", get(hello_world)).with_state(state); diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 24ba9a0f..add427c7 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.39.0" +shuttle-runtime = "0.40.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index 31fdef41..2bb3c16b 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -10,7 +10,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-persist = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index bb9e4b52..a651b676 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,10 +16,10 @@ lettre = "0.11.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.39.0" -shuttle-runtime = "0.39.0" -shuttle-secrets = "0.39.0" -shuttle-shared-db = { version = "0.39.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.40.0" +shuttle-runtime = "0.40.0" +shuttle-secrets = "0.40.0" +shuttle-shared-db = { version = "0.40.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.1", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml index 0ede439c..6a5e8d03 100644 --- a/next/hello-world/Cargo.toml +++ b/next/hello-world/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" crate-type = [ "cdylib" ] [dependencies] -shuttle-next = "0.39.0" +shuttle-next = "0.40.0" tracing = "0.1.37" futures = "0.3.25" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 61a383c4..ec082b2c 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,7 +15,7 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = "0.39.0" -shuttle-runtime = "0.39.0" -shuttle-secrets = "0.39.0" +shuttle-axum = "0.40.0" +shuttle-runtime = "0.40.0" +shuttle-secrets = "0.40.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 679647bc..ae68b5a0 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "2.0.0" -shuttle-poem = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-poem = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index b4ab6781..88c48e68 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "2.0.0" -shuttle-poem = "0.39.0" -shuttle-shared-db = { version = "0.39.0", features = ["mongodb"] } -shuttle-runtime = "0.39.0" +shuttle-poem = "0.40.0" +shuttle-shared-db = { version = "0.40.0", features = ["mongodb"] } +shuttle-runtime = "0.40.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml index 7da28f70..2ef71fd3 100644 --- a/poem/postgres/Cargo.toml +++ b/poem/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] poem = "2.0.0" serde = "1.0.148" -shuttle-poem = "0.39.0" -shuttle-runtime = "0.39.0" -shuttle-shared-db = { version = "0.39.0", features = ["postgres", "sqlx"] } +shuttle-poem = "0.40.0" +shuttle-runtime = "0.40.0" +shuttle-shared-db = { version = "0.40.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 7d421a40..e0cf95dd 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,9 +7,9 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.6.1" -shuttle-runtime = "0.39.0" -shuttle-secrets = "0.39.0" +shuttle-runtime = "0.40.0" +shuttle-secrets = "0.40.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity -shuttle-serenity = "0.39.0" +shuttle-serenity = "0.40.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index edcc0e78..12c65017 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-rocket = "0.40.0" +shuttle-runtime = "0.40.0" rocket_dyn_templates = { version = "0.1.0-rc.4", features = ["handlebars"] } tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 95919e5b..e6f64d4b 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-rocket = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 0180a501..52a4bc45 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-rocket = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.26.0" diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index e0fdbd7e..b191676f 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -4,10 +4,10 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.39.0" -shuttle-opendal = "0.39.0" +shuttle-runtime = "0.40.0" +shuttle-opendal = "0.40.0" tokio = "1.26.0" -shuttle-rocket = "0.39.0" +shuttle-rocket = "0.40.0" opendal = "0.45.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index b43d6125..9b09d962 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.39.0" -shuttle-rocket = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-persist = "0.40.0" +shuttle-rocket = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 96e9b3c6..af477488 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.39.0" -shuttle-runtime = "0.39.0" -shuttle-shared-db = { version = "0.39.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.40.0" +shuttle-runtime = "0.40.0" +shuttle-shared-db = { version = "0.40.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 723826d1..09a8e2a5 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.39.0" -shuttle-runtime = "0.39.0" -shuttle-secrets = "0.39.0" +shuttle-rocket = "0.40.0" +shuttle-runtime = "0.40.0" +shuttle-secrets = "0.40.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index b340ecba..ec3c05aa 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-rocket = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index a9542d49..e4cb05eb 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" nanoid = "0.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.39.0" -shuttle-runtime = "0.39.0" -shuttle-shared-db = { version = "0.39.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.40.0" +shuttle-runtime = "0.40.0" +shuttle-shared-db = { version = "0.40.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index d3803d9a..6a977126 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-rocket = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 1f4320c0..a344a182 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] salvo = "0.63.0" -shuttle-salvo = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-salvo = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml index 37af783b..51712444 100644 --- a/salvo/image-rescaler/Cargo.toml +++ b/salvo/image-rescaler/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] image = "0.24.8" salvo = "0.63.0" -shuttle-salvo = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-salvo = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 2f909336..2113f959 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.39.0" -shuttle-secrets = "0.39.0" -shuttle-serenity = "0.39.0" +shuttle-runtime = "0.40.0" +shuttle-secrets = "0.40.0" +shuttle-serenity = "0.40.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index f04fb0d1..651484ef 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.39.0" -shuttle-secrets = "0.39.0" -shuttle-serenity = "0.39.0" -shuttle-shared-db = { version = "0.39.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.40.0" +shuttle-secrets = "0.40.0" +shuttle-serenity = "0.40.0" +shuttle-shared-db = { version = "0.40.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 49cba2a6..3a79ab46 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-thruster = "0.40.0" +shuttle-runtime = "0.40.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml index 290d0d10..2d79d170 100644 --- a/thruster/postgres/Cargo.toml +++ b/thruster/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" hyper = "0.14.23" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.39.0", features = ["postgres", "sqlx"] } -shuttle-runtime = "0.39.0" -shuttle-thruster = "0.39.0" +shuttle-aws-rds = { version = "0.40.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.40.0" +shuttle-thruster = "0.40.0" sqlx = "0.7.1" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 1753f8a5..28437504 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.39.0" -shuttle-runtime = "0.39.0" +shuttle-tide = "0.40.0" +shuttle-runtime = "0.40.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml index 4b01e3a3..9b3f9bf8 100644 --- a/tide/postgres/Cargo.toml +++ b/tide/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.39.0", features = ["postgres", "sqlx"] } -shuttle-runtime = "0.39.0" -shuttle-tide = "0.39.0" +shuttle-aws-rds = { version = "0.40.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.40.0" +shuttle-tide = "0.40.0" sqlx = "0.7.1" tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 2380b913..d3806c88 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.39.0" -shuttle-tower = "0.39.0" +shuttle-runtime = "0.40.0" +shuttle-tower = "0.40.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 03143e72..f54d60df 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.39.0" +shuttle-actix-web = "0.40.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.39.0", default-features = false } +shuttle-runtime = { version = "0.40.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = "0.3.17" diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 18ef66a5..a050d916 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.39.0" -shuttle-warp = "0.39.0" +shuttle-runtime = "0.40.0" +shuttle-warp = "0.40.0" tokio = "1.26.0" warp = "0.3.3" From a0791d797ed8fdefc953adb6fe9e0fd5d294aa16 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Tue, 5 Mar 2024 13:29:58 +0100 Subject: [PATCH 142/239] feat: template definition system, remove superflous templates (#148) * chore: reduce duplicated examples * nit * wip: templates format and scripts * versions * feat: template checking works with workspaces * remove simple/duplicated templates * add axum templates * fix duplicate template check * ci: add template check * remove next * add more templates * move all templates into new format * fixes * nit * nit: docs * use shuttle-common model * fix: pdo and tracing sub * ci: remove next/wasm support * nit --- .github/workflows/ci.yml | 24 +- .gitpod.yml | 4 - README.md | 96 +---- _scripts/check-templates.rs | 83 ++++ axum/static-next-server/.gitignore | 4 - axum/static-next-server/Cargo.toml | 12 - axum/static-next-server/README.md | 9 - axum/static-next-server/Shuttle.toml | 3 - axum/static-next-server/src/main.rs | 12 - axum/with-state/Cargo.toml | 10 - axum/with-state/src/main.rs | 23 -- ci.sh | 17 +- custom-resource/pdo/src/lib.rs | 2 +- next/hello-world/.target | 1 - next/hello-world/Cargo.toml | 12 - next/hello-world/src/lib.rs | 33 -- poem/postgres/Cargo.toml | 13 - poem/postgres/Shuttle.toml | 1 - poem/postgres/schema.sql | 6 - poem/postgres/src/main.rs | 59 --- rocket/dyn-templates/Cargo.toml | 2 +- templates.toml | 386 +++++++++++++++++++ thruster/postgres/Cargo.toml | 15 - thruster/postgres/Shuttle.toml | 1 - thruster/postgres/schema.sql | 6 - thruster/postgres/src/main.rs | 114 ------ tide/postgres/Cargo.toml | 13 - tide/postgres/Shuttle.toml | 1 - tide/postgres/schema.sql | 6 - tide/postgres/src/main.rs | 57 --- tracing/custom-tracing-subscriber/Cargo.toml | 2 +- 31 files changed, 493 insertions(+), 534 deletions(-) delete mode 100644 .gitpod.yml create mode 100644 _scripts/check-templates.rs delete mode 100644 axum/static-next-server/.gitignore delete mode 100644 axum/static-next-server/Cargo.toml delete mode 100644 axum/static-next-server/README.md delete mode 100644 axum/static-next-server/Shuttle.toml delete mode 100644 axum/static-next-server/src/main.rs delete mode 100644 axum/with-state/Cargo.toml delete mode 100644 axum/with-state/src/main.rs delete mode 100644 next/hello-world/.target delete mode 100644 next/hello-world/Cargo.toml delete mode 100644 next/hello-world/src/lib.rs delete mode 100644 poem/postgres/Cargo.toml delete mode 100644 poem/postgres/Shuttle.toml delete mode 100644 poem/postgres/schema.sql delete mode 100644 poem/postgres/src/main.rs create mode 100644 templates.toml delete mode 100644 thruster/postgres/Cargo.toml delete mode 100644 thruster/postgres/Shuttle.toml delete mode 100644 thruster/postgres/schema.sql delete mode 100644 thruster/postgres/src/main.rs delete mode 100644 tide/postgres/Cargo.toml delete mode 100644 tide/postgres/Shuttle.toml delete mode 100644 tide/postgres/schema.sql delete mode 100644 tide/postgres/src/main.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 42511e53..a4b4292d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,18 +11,29 @@ env: CARGO_TERM_COLOR: always jobs: - fmt-clippy-a-p: + check-templates: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Install wasm32-wasi target - run: rustup target add wasm32-wasi + - uses: taiki-e/install-action@v2 + with: + tool: cargo-binstall + + - run: cargo binstall -y rust-script@0.34.0 + + - run: rust-script _scripts/check-templates.rs + + fmt-clippy-a-p: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 - name: Install sccache run: | - SCCACHE_VERSION='v0.5.4' + SCCACHE_VERSION='v0.7.7' curl -L https://github.com/mozilla/sccache/releases/download/$SCCACHE_VERSION/sccache-$SCCACHE_VERSION-x86_64-unknown-linux-musl.tar.gz \ | tar -xOz sccache-$SCCACHE_VERSION-x86_64-unknown-linux-musl/sccache \ > /home/runner/.cargo/bin/sccache \ @@ -44,12 +55,9 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install wasm32-wasi target - run: rustup target add wasm32-wasi - - name: Install sccache run: | - SCCACHE_VERSION='v0.5.4' + SCCACHE_VERSION='v0.7.7' curl -L https://github.com/mozilla/sccache/releases/download/$SCCACHE_VERSION/sccache-$SCCACHE_VERSION-x86_64-unknown-linux-musl.tar.gz \ | tar -xOz sccache-$SCCACHE_VERSION-x86_64-unknown-linux-musl/sccache \ > /home/runner/.cargo/bin/sccache \ diff --git a/.gitpod.yml b/.gitpod.yml deleted file mode 100644 index 3330f266..00000000 --- a/.gitpod.yml +++ /dev/null @@ -1,4 +0,0 @@ -# List the start up tasks. Learn more https://www.gitpod.io/docs/config-start-tasks/ -tasks: - - before: cargo install cargo-shuttle - command: cargo shuttle login diff --git a/README.md b/README.md index e5eb4a67..a1e9de46 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,12 @@ # Shuttle Examples -This is a collection of some example apps that show what you can do with shuttle. +This is a collection of some example apps that show what you can deploy on Shuttle. -The examples in this repository, listed below, consists of *"Hello, world!"* examples of all officially supported web frameworks and how to combine them with Shuttle resources, but also fullstack templates and more. - -There are also unofficial examples that are created and maintained by community members. -Contributions to this list are welcome. -Check out the list at the [bottom of this page](#community-examples). +The examples in this repository, consists of *"Hello, world!"* examples of all officially supported web frameworks and how to combine them with Shuttle resources, but also fullstack templates and more. ## How to clone, run and deploy an example -To clone an example, use the init command of the [`cargo-shuttle`](https://docs.shuttle.rs/introduction/installation) binary and specify the git URL and optional subfolder: +To clone an example, use the `init` command of the [`cargo-shuttle`](https://docs.shuttle.rs/introduction/installation) binary and specify the git URL and optional subfolder: ```bash cargo shuttle init --from https://github.com/shuttle-hq/shuttle-examples --subfolder axum/hello-world @@ -42,89 +38,3 @@ cargo shuttle project start # Deploy to Shuttle cargo shuttle deploy ``` - -## Official Examples - -This is a list of all examples maintained in this repository. - -**Framework** | **Name & Link** | **Description** | **Command** ---------------|-----------------|-----------------|------------- -Actix Web | [hello-world](./actix-web/hello-world/) | Hello World | `cargo shuttle init --template actix-web` -Actix Web | [postgres](./actix-web/postgres/) | TODO app with a Postgres DB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/postgres` -Actix Web | [static-files](./actix-web/static-files/) | Hello World page that serves static HTML and JS files | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/static-files` -Actix Web | [clerk](./actix-web/clerk/) | A React + Tailwind app that uses Clerk as an auth provider | `cargo shuttle init cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/clerk` -Actix Web | [websocket-actorless](./actix-web/websocket-actorless/) | Websocket app that checks the status of Shuttle's API | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/websocket-actorless` -Actix Web | [cookie-authentication](./actix-web/cookie-authentication/) | Use JWT to authenticate API endpoints | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/cookie-authentication` -Axum | [hello-world](./axum/hello-world/) | Hello World | `cargo shuttle init --template axum` -Axum | [htmx-crud](./axum/htmx-crud/) | htmx CRUD app | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/htmx-crud` -Axum | [metadata](./axum/metadata/) | Simple app that prints the service information such as Shuttle service name | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/metadata` -Axum | [qdrant](./axum/qdrant/) | Barebones example of the shuttle-qdrant plugin | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/qdrant` -Axum | [static-files](./axum/static-files/) | Hello World page that serves static HTML and JS files | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/static-files` -Axum | [static-next-server](./axum/static-next-server/) | SPA server for serving a apps from frameworks such as Next.js | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/static-next-server` -Axum | [websocket](./axum/websocket/) | Websocket app that checks the status of Shuttle's API | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/websocket` -Axum | [with-state](./axum/with-state/) | Hello World with example of how to utilize State in Axum | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/with-state` -Axum | [jwt-authentication](./axum/jwt-authentication/) | Use JWT to authenticate API endpoints | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder axum/jwt-authentication` -Axum & Next.js | [saas](./fullstack-templates/saas/) | Competent opinionated fullstack web app with pre-made routes and assets | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder fullstack-templates/saas` -Loco | [hello-world](./loco/hello-world/) | Hello World | `cargo shuttle init --template loco` -Poem | [hello-world](./poem/hello-world/) | Hello World | `cargo shuttle init --template poem` -Poem | [mongodb](./poem/mongodb/) | TODO app with MongoDB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder poem/mongodb` -Poem | [postgres](./poem/postgres/) | TODO app with a Postgres DB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder poem/postgres` -Poise | [hello-world](./poise/hello-world/) | Hello World Discord bot | `cargo shuttle init --template poise` -Rocket | [jwt-authentication](./rocket/jwt-authentication/) | Use JWT to authenticate API endpoints | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/jwt-authentication` -Rocket | [dyn-templates](./rocket/dyn-templates/) | Handlebars dynamic templates | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/dyn-templates` -Rocket | [hello-world](./rocket/hello-world/) | Hello World | `cargo shuttle init --template rocket` -Rocket | [persist](./rocket/persist/) | Store weather data with Shuttle Persist | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/persist` -Rocket | [postgres](./rocket/postgres/) | TODO app with a Postgres DB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/postgres` -Rocket | [secrets](./rocket/secrets/) | Extract secrets from your Secrets.toml file | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/secrets` -Rocket | [static-files](./rocket/static-files/) | Hello World page that serves static HTML and JS files | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/static-files` -Rocket | [url-shortener](./rocket/url-shortener/) | URL shortener with Postgres storage | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/url-shortener` -Rocket | [workspace](./rocket/workspace/) | A cargo workspace where one crate is a Shuttle service | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/workspace` -Rocket | [opendal-memory](./rocket/opendal-memory/) | app with an OpenDAL memory storage | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder rocket/opendal-memory` -Salvo | [hello-world](./salvo/hello-world/) | Hello World | `cargo shuttle init --template salvo` -Salvo | [image-rescaler](./salvo/image-rescaler/) | Hello World | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder salvo/image-rescaler` -Serenity | [hello-world](./serenity/hello-world/) | Hello World Discord bot | `cargo shuttle init --template serenity` -Thruster | [hello-world](./thruster/hello-world/) | Hello World | `cargo shuttle init --template thruster` -Thruster | [postgres](./thruster/postgres/) | TODO app with a Postgres DB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder thruster/postgres` -Tide | [hello-world](./tide/hello-world/) | Hello World | `cargo shuttle init --template tide` -Tide | [postgres](./tide/postgres/) | TODO app with a Postgres DB | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder tide/postgres` -Tower | [hello-world](./tower/hello-world/) | Hello World | `cargo shuttle init --template tower` -Tracing | [custom-tracing-subscriber](./tracing/custom-tracing-subscriber/) | Hello world with a custom tracing setup | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder tracing/custom-tracing-subscriber` -Warp | [hello-world](./warp/hello-world/) | Hello World | `cargo shuttle init --template warp` -*Custom Service* | [none](./custom-service/none/) | Empty service - A barebones implementation of Shuttle Service trait that does nothing | `cargo shuttle init --template none` -*Custom Service* | [shuttle-cron](./shuttle-cron/) | A custom service that runs a cron job server using Apalis | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder shuttle-cron` -*Custom Service* | [request-scheduler](./custom-service/request-scheduler/) | A custom *Request Scheduler* service | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder custom-service/request-scheduler` -*Custom Resource* | [pdo](./custom-resource/pdo/) | Custom Shuttle resource that holds a Plain Data Object (PDO), shown in the context of an Axum app | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder custom-resource/pdo` -*Other* | [standalone-binary](./other/standalone-binary/) | How to split a project to allow it to run both with Shuttle and standalone | `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder other/standalone-binary` - -## Community Examples - -This is a collection of unofficial examples that community members have submitted. -Quality and maintenance is not guaranteed. -You can submit a Pull Request to add your example to the list. - - - -**Framework** | **Name & Link** | **Description** | **Command** ---------------|-----------------|-------------|---------------- -Actix Web/Any | [GitHub Login (OAuth)](https://github.com/robjtede/actix-examples-oauth-github) | Sample app demonstrating GitHub OAuth login using Actix Web | `cargo shuttle init --from robjtede/actix-examples-oauth-github` -Axum/Any | [Fullstack Rust](https://github.com/TylerBloom/shuttle-fullstack-rust-example) | A basic project template for fullstack Rust projects | `cargo shuttle init --from TylerBloom/shuttle-fullstack-rust-example` -Axum/Yew | [Web App with Yew](https://github.com/sentinel1909/shuttle-template-yew) | A basic project template for a web app using the Yew framework | `cargo shuttle init --from sentinel1909/shuttle-template-yew` | -Axum/Bevy | [Shuttle with Bevy](https://github.com/joshua-mo-143/shuttle-bevy-ex) | A basic project template for a compiled Bevy WASM "Hello World" webpage | `cargo shuttle init --from joshua-mo-143/shuttle-bevy-ex` | -Actix Web | [Web API with Actix Web](https://github.com/sentinel1909/shuttle-template-actix) | A template for starting an API with Actix Web | `cargo shuttle init --from sentinel1909/shuttle-template-actix` -Rocket/Yew | [Web API with Rocket and Sled](https://github.com/wiseaidev/rocket-yew-starter-pack) | A Full Stack CRUD template for starting an API with [Rocket](https://github.com/rwf2/Rocket), [Sled](https://github.com/spacejam/sled) and [Yew](https://github.com/yewstack/yew) | `cargo shuttle init --from wiseaidev/rocket-yew-starter-pack` diff --git a/_scripts/check-templates.rs b/_scripts/check-templates.rs new file mode 100644 index 00000000..7e2a5383 --- /dev/null +++ b/_scripts/check-templates.rs @@ -0,0 +1,83 @@ +//! Usage: rust-script _scripts/check-templates.rs +//! +//! ```cargo +//! [dependencies] +//! shuttle-common = "*" # always use latest version +//! toml = "0.8" +//! ignore = "0.4" +//! ``` + +use shuttle_common::templates::TemplatesSchema; + +fn main() { + let s = std::fs::read_to_string("templates.toml").expect("to find file"); + let toml: TemplatesSchema = toml::from_str(&s).expect("to parse toml file"); + + let (tx, rx) = std::sync::mpsc::channel::(); + + let t = std::thread::spawn(move || rx.into_iter().collect::>()); + + let walker = ignore::WalkBuilder::new(".").build_parallel(); + walker.run(|| { + let tx = tx.clone(); + Box::new(move |result| { + use ignore::WalkState::*; + // join directory with filename so that this directory can be skipped in the case of a workspace + let path = result.unwrap().into_path().join("Cargo.toml"); + if !path.exists() { + return Continue; + } + + let s = format!("{}", path.display()); + let s = s + .trim_start_matches("./") + .trim_end_matches("/Cargo.toml") + .to_owned(); + tx.send(s).unwrap(); + + if std::fs::read_to_string(&path) + .unwrap() + .contains("[workspace]") + { + // don't walk into subdirectories of workspaces + return Skip; + } + + Continue + }) + }); + drop(tx); + let mut manifests = t.join().unwrap(); + + let mut set = std::collections::BTreeSet::<_>::new(); + for (name, t) in toml.templates { + if t.community.is_some_and(|c| c) { + continue; + } + + let path = t.path.unwrap_or_default(); + + if !set.insert(path.clone()) { + eprintln!("Path '{}' referenced in two places", path); + std::process::exit(1); + } + + if !manifests.remove(&path) { + eprintln!( + "Template {} referenced non-existent manifest file at {}", + name, path + ); + std::process::exit(1); + } + } + + if !manifests.is_empty() { + println!("Missing template definitions:"); + for s in manifests { + println!("{s}"); + } + std::process::exit(1); + } + + println!("Template definitions verified") +} diff --git a/axum/static-next-server/.gitignore b/axum/static-next-server/.gitignore deleted file mode 100644 index 0580e83d..00000000 --- a/axum/static-next-server/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Generated by Cargo -# will have compiled files and executables -**/target/ -static/ diff --git a/axum/static-next-server/Cargo.toml b/axum/static-next-server/Cargo.toml deleted file mode 100644 index 1ce5c054..00000000 --- a/axum/static-next-server/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "static-next-server" -version = "0.1.0" -edition = "2021" -publish = false - -[dependencies] -axum = "0.7.3" -shuttle-axum = "0.40.0" -shuttle-runtime = "0.40.0" -tokio = "1.26.0" -tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/static-next-server/README.md b/axum/static-next-server/README.md deleted file mode 100644 index c2f21c83..00000000 --- a/axum/static-next-server/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Serving a NextJS project with Axum - -This example is a template for an [axum](https://github.com/tokio-rs/axum) server that serves a NextJS single-page application as static assets, deployed with shuttle. For more information on how to achieve this, check out this article by one of our contributors: https://joshmo.hashnode.dev/deploying-a-nextjs-front-end-with-a-rust-api-in-one-go. - -## Note - -This project misses the `static` NextJS bundle because it's common to not commit it to GitHub. This is done through a `.gitignore`, but Shuttle uses the assets list in `Shuttle.toml` file which waves the `.gitignore` rule. That's because otherwise Shuttle wouldn't package the `static` directory to be able to deploy it, because of the `.gitignore` filtering. - -As a result, building this project or trying to run it locally will fail because of the missing `static` folder. diff --git a/axum/static-next-server/Shuttle.toml b/axum/static-next-server/Shuttle.toml deleted file mode 100644 index 849387a8..00000000 --- a/axum/static-next-server/Shuttle.toml +++ /dev/null @@ -1,3 +0,0 @@ -assets = [ - "static/*", -] diff --git a/axum/static-next-server/src/main.rs b/axum/static-next-server/src/main.rs deleted file mode 100644 index c18a384d..00000000 --- a/axum/static-next-server/src/main.rs +++ /dev/null @@ -1,12 +0,0 @@ -use axum::Router; -use tower_http::services::{ServeDir, ServeFile}; - -#[shuttle_runtime::main] -async fn axum() -> shuttle_axum::ShuttleAxum { - let router = Router::new().nest_service( - "/", - ServeDir::new("static").not_found_service(ServeFile::new("static/index.html")), - ); - - Ok(router.into()) -} diff --git a/axum/with-state/Cargo.toml b/axum/with-state/Cargo.toml deleted file mode 100644 index 7be0b2ed..00000000 --- a/axum/with-state/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "with-state" -version = "0.1.0" -edition = "2021" - -[dependencies] -axum = "0.7.3" -shuttle-axum = "0.40.0" -shuttle-runtime = "0.40.0" -tokio = "1.26.0" diff --git a/axum/with-state/src/main.rs b/axum/with-state/src/main.rs deleted file mode 100644 index 58b284ff..00000000 --- a/axum/with-state/src/main.rs +++ /dev/null @@ -1,23 +0,0 @@ -use std::sync::Arc; - -use axum::{extract::State, response::IntoResponse, routing::get, Router}; - -async fn hello_world(State(state): State>) -> impl IntoResponse { - state.msg -} - -#[derive(Clone)] -struct AppState { - msg: &'static str, -} - -#[shuttle_runtime::main] -async fn axum() -> shuttle_axum::ShuttleAxum { - let state = Arc::new(AppState { - msg: "Hello, world!", - }); - - let router = Router::new().route("/", get(hello_world)).with_state(state); - - Ok(router.into()) -} diff --git a/ci.sh b/ci.sh index 469cc1f9..dac2e029 100755 --- a/ci.sh +++ b/ci.sh @@ -10,20 +10,7 @@ DIRS=$(find . -name Cargo.toml -exec dirname {} \; | sort | awk -v from="$FROM" # Loop through each directory and run cargo fmt and cargo clippy, exit on failure for dir in $DIRS; do - if [ -f "$dir/.disable_ci" ]; then - echo "Skipping $dir" - continue - fi - echo "Checking $dir" - - if [ -f "$dir/.target" ]; then - target=$(<$dir/.target) - - cargo fmt --all --manifest-path "$dir/Cargo.toml" -- --check - cargo clippy --no-deps --target $target --manifest-path "$dir/Cargo.toml" -- -D warnings - else - cargo fmt --all --manifest-path "$dir/Cargo.toml" -- --check - cargo clippy --no-deps --manifest-path "$dir/Cargo.toml" -- -D warnings - fi + cargo fmt --all --manifest-path "$dir/Cargo.toml" -- --check + cargo clippy --no-deps --manifest-path "$dir/Cargo.toml" -- -D warnings done diff --git a/custom-resource/pdo/src/lib.rs b/custom-resource/pdo/src/lib.rs index 13b07c78..a75d191f 100644 --- a/custom-resource/pdo/src/lib.rs +++ b/custom-resource/pdo/src/lib.rs @@ -1,5 +1,5 @@ use async_trait::async_trait; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use shuttle_service::{Error, IntoResource, ResourceFactory, ResourceInputBuilder}; #[derive(Default)] diff --git a/next/hello-world/.target b/next/hello-world/.target deleted file mode 100644 index caff62a7..00000000 --- a/next/hello-world/.target +++ /dev/null @@ -1 +0,0 @@ -wasm32-wasi \ No newline at end of file diff --git a/next/hello-world/Cargo.toml b/next/hello-world/Cargo.toml deleted file mode 100644 index 6a5e8d03..00000000 --- a/next/hello-world/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "hello-world" -version = "0.1.0" -edition = "2021" - -[lib] -crate-type = [ "cdylib" ] - -[dependencies] -shuttle-next = "0.40.0" -tracing = "0.1.37" -futures = "0.3.25" diff --git a/next/hello-world/src/lib.rs b/next/hello-world/src/lib.rs deleted file mode 100644 index a4ad78a2..00000000 --- a/next/hello-world/src/lib.rs +++ /dev/null @@ -1,33 +0,0 @@ -shuttle_next::app! { - use futures::TryStreamExt; - use tracing::debug; - use shuttle_next::body::StreamBody; - use shuttle_next::extract::BodyStream; - use shuttle_next::response::{Response, IntoResponse}; - - #[shuttle_next::endpoint(method = get, route = "/")] - async fn hello() -> &'static str { - "Hello, World!" - } - - // We can also use tracing/log macros directly: - #[shuttle_next::endpoint(method = get, route = "/goodbye")] - async fn goodbye() -> &'static str { - debug!("goodbye endpoint called"); - "Goodbye, World!" - } - - // We can also extract the http body in our handlers. - // The endpoint below takes the body from the request using the axum `BodyStream` - // extractor, lazily maps its bytes to uppercase and streams it back in our response: - #[shuttle_next::endpoint(method = post, route = "/uppercase")] - async fn uppercase(body: BodyStream) -> impl IntoResponse { - let chunk_stream = body.map_ok(|chunk| { - chunk - .iter() - .map(|byte| byte.to_ascii_uppercase()) - .collect::>() - }); - Response::new(StreamBody::new(chunk_stream)) - } -} diff --git a/poem/postgres/Cargo.toml b/poem/postgres/Cargo.toml deleted file mode 100644 index 2ef71fd3..00000000 --- a/poem/postgres/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "postgres" -version = "0.1.0" -edition = "2021" - -[dependencies] -poem = "2.0.0" -serde = "1.0.148" -shuttle-poem = "0.40.0" -shuttle-runtime = "0.40.0" -shuttle-shared-db = { version = "0.40.0", features = ["postgres", "sqlx"] } -sqlx = "0.7.1" -tokio = "1.26.0" diff --git a/poem/postgres/Shuttle.toml b/poem/postgres/Shuttle.toml deleted file mode 100644 index 33ccd078..00000000 --- a/poem/postgres/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "postgres-poem-app" diff --git a/poem/postgres/schema.sql b/poem/postgres/schema.sql deleted file mode 100644 index 460e7c23..00000000 --- a/poem/postgres/schema.sql +++ /dev/null @@ -1,6 +0,0 @@ -DROP TABLE IF EXISTS todos; - -CREATE TABLE todos ( - id serial PRIMARY KEY, - note TEXT NOT NULL -); diff --git a/poem/postgres/src/main.rs b/poem/postgres/src/main.rs deleted file mode 100644 index ccd3b446..00000000 --- a/poem/postgres/src/main.rs +++ /dev/null @@ -1,59 +0,0 @@ -use poem::{ - error::BadRequest, - get, handler, - middleware::AddData, - post, - web::{Data, Json, Path}, - EndpointExt, Result, Route, -}; -use serde::{Deserialize, Serialize}; -use shuttle_poem::ShuttlePoem; -use shuttle_runtime::CustomError; -use sqlx::{Executor, FromRow, PgPool}; - -#[handler] -async fn retrieve(Path(id): Path, state: Data<&PgPool>) -> Result> { - let todo = sqlx::query_as("SELECT * FROM todos WHERE id = $1") - .bind(id) - .fetch_one(state.0) - .await - .map_err(BadRequest)?; - - Ok(Json(todo)) -} - -#[handler] -async fn add(Json(data): Json, state: Data<&PgPool>) -> Result> { - let todo = sqlx::query_as("INSERT INTO todos(note) VALUES ($1) RETURNING id, note") - .bind(&data.note) - .fetch_one(state.0) - .await - .map_err(BadRequest)?; - - Ok(Json(todo)) -} - -#[shuttle_runtime::main] -async fn poem(#[shuttle_shared_db::Postgres] pool: PgPool) -> ShuttlePoem { - pool.execute(include_str!("../schema.sql")) - .await - .map_err(CustomError::new)?; - - let app = Route::new() - .at("/todo", post(add)) - .at("/todo/:id", get(retrieve)) - .with(AddData::new(pool)); - - Ok(app.into()) -} - -#[derive(Deserialize)] -struct TodoNew { - pub note: String, -} - -#[derive(Serialize, FromRow)] -struct Todo { - pub id: i32, - pub note: String, -} diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 12c65017..ab3ce9d4 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] rocket = "0.5.0" +rocket_dyn_templates = { version = "0.1.0", features = ["handlebars"] } shuttle-rocket = "0.40.0" shuttle-runtime = "0.40.0" -rocket_dyn_templates = { version = "0.1.0-rc.4", features = ["handlebars"] } tokio = "1.26.0" diff --git a/templates.toml b/templates.toml new file mode 100644 index 00000000..4493ca4f --- /dev/null +++ b/templates.toml @@ -0,0 +1,386 @@ +# Shuttle Template Definitions +# +# Use `rust-script _scripts/check-templates.rs` to validate this list + +## OFFICIAL STARTERS ## + +[templates.actix-web-hello-world] +title = "Actix Web Hello World" +path = "actix-web/hello-world" +type = "starter" +use_cases = ["Web app"] +tags = ["actix-web"] +template = "actix-web" + +[templates.axum-hello-world] +title = "Axum Hello World" +path = "axum/hello-world" +type = "starter" +use_cases = ["Web app"] +tags = ["axum"] +template = "axum" + +[templates.loco-hello-world] +title = "Loco Hello World" +path = "loco/hello-world" +type = "starter" +use_cases = ["Web app"] +tags = ["loco"] +template = "loco" + +[templates.poem-hello-world] +title = "Poem Hello World" +path = "poem/hello-world" +type = "starter" +use_cases = ["Web app"] +tags = ["poem"] +template = "poem" + +[templates.poise-hello-world] +title = "Poise Hello World" +path = "poise/hello-world" +type = "starter" +use_cases = ["Discord bot"] +tags = ["poise", "serenity"] +template = "poise" + +[templates.rocket-hello-world] +title = "Rocket Hello World" +path = "rocket/hello-world" +type = "starter" +use_cases = ["Web app"] +tags = ["rocket"] +template = "rocket" + +[templates.salvo-hello-world] +title = "Salvo Hello World" +path = "salvo/hello-world" +type = "starter" +use_cases = ["Web app"] +tags = ["salvo"] +template = "salvo" + +[templates.serenity-hello-world] +title = "Serenity Hello World" +path = "serenity/hello-world" +type = "starter" +use_cases = ["Discord bot"] +tags = ["serenity"] +template = "serenity" + +[templates.thruster-hello-world] +title = "Thruster Hello World" +path = "thruster/hello-world" +type = "starter" +use_cases = ["Web app"] +tags = ["thruster"] +template = "thruster" + +[templates.tide-hello-world] +title = "Tide Hello World" +path = "tide/hello-world" +type = "starter" +use_cases = ["Web app"] +tags = ["tide"] +template = "tide" + +[templates.tower-hello-world] +title = "Tower Hello World" +path = "tower/hello-world" +type = "starter" +use_cases = ["Web app"] +tags = ["tower"] +template = "tower" + +[templates.warp-hello-world] +title = "Warp Hello World" +path = "warp/hello-world" +type = "starter" +use_cases = ["Web app"] +tags = ["warp"] +template = "warp" + +[templates.none] +title = "None" +description = "Empty service - A barebones implementation of Shuttle Service trait that does nothing" +path = "custom-service/none" +type = "starter" +use_cases = [] +tags = ["diy"] +template = "none" + + +## OFFICIAL TEMPLATES ## + + +[templates.actix-web-postgres] +title = "Actix Web Postgres" +description = "Todo list with a Postgres database" +path = "actix-web/postgres" +use_cases = ["Web app", "Storage"] +tags = ["actix-web", "database", "postgres"] + +[templates.actix-web-clerk-react] +title = "Clerk authentication" +description = "Fullstack Rust+React with auth provider logic" +path = "actix-web/clerk" +use_cases = ["Web app", "Authentication"] +tags = ["actix-web", "clerk", "react", "typescript", "tailwind"] + +[templates.actix-cookie-authentication] +title = "Cookie Authentication" +description = "Use JWT to authenticate API endpoints" +path = "actix-web/cookie-authentication" +use_cases = ["Web app", "Authentication"] +tags = ["actix-web", "jwt"] + +[templates.actix-websocket-actorless] +title = "Actix Web Actorless Websockets" +description = "Health monitoring service using websockets" +path = "actix-web/websocket-actorless" +use_cases = ["Web app", "Monitoring"] +tags = ["actix-web", "websocket"] + +[templates.actix-static-files] +title = "Actix Web static file server" +description = "Hello World page that serves static HTML and JS files" +path = "actix-web/static-files" +use_cases = ["Web app"] +tags = ["actix-web"] + +[templates.axum-htmx-crud] +title = "Axum + HTMX" +description = "Simple CRUD app using HTMX and Askama" +path = "axum/htmx-crud" +use_cases = ["Web app", "Storage"] +tags = ["axum", "htmx", "database", "postgres"] + +[templates.axum-jwt-authentication] +title = "JWT authentication" +description = "Use JWT to authenticate API endpoints" +path = "axum/jwt-authentication" +use_cases = ["Web app", "Authentication"] +tags = ["axum", "jwt"] + +[templates.axum-metadata] +title = "Shuttle Metadata" +description = "Basic usage of Shuttle metadata" +path = "axum/metadata" +use_cases = [] +tags = ["axum"] + +[templates.axum-postgres] +title = "Axum Postgres" +description = "Todo list with a Postgres database" +path = "axum/postgres" +use_cases = ["Web app", "Storage"] +tags = ["axum", "database", "postgres"] + +[templates.axum-qdrant] +title = "Qdrant" +description = "Connecting to Qdrant cloud with shuttle-qdrant" +path = "axum/qdrant" +use_cases = ["Web app", "Storage", "AI"] +tags = ["axum", "database", "qdrant"] + +[templates.axum-static-files] +title = "File server" +description = "Hello World static file server with tower-http" +path = "axum/static-files" +use_cases = ["Web app"] +tags = ["axum"] + +[templates.axum-turso] +title = "Turso" +description = "Connect to a Turso DB with shuttle-turso" +path = "axum/turso" +use_cases = ["Web app", "Storage"] +tags = ["axum", "database", "libsql", "sqlite"] + +[templates.axum-websocket] +title = "Axum Websockets" +description = "Health monitoring service using websockets" +path = "axum/websocket" +use_cases = ["Web app", "Monitoring"] +tags = ["axum", "websocket"] + +[templates.custom-resource-pdo] +title = "Custom Resource" +description = "A custom resource for the Shuttle main macro" +path = "custom-resource/pdo" +use_cases = [] +tags = ["diy"] + +[templates.request-scheduler] +title = "Request Scheduler" +description = "Schedule requests with a cron schedule" +path = "custom-service/request-scheduler" +use_cases = ["Web app", "Cron jobs", "Storage"] +tags = ["axum"] + +[templates.axum-next-fullstack-saas] +title = "Fullstack SaaS" +description = "Opinionated fullstack web app with pre-made routes and assets" +path = "fullstack-templates/saas" +use_cases = ["Web app", "Authentication", "Storage", "Monetization"] +tags = ["axum", "next.js", "database", "postgres", "typescript", "tailwind"] + +[templates.standalone-binary] +title = "Standalone binary" +description = "How to split a project to allow it to run both with Shuttle and standalone" +path = "other/standalone-binary" +use_cases = [] +tags = ["diy", "axum"] + +[templates.poem-mongodb] +title = "Poem MongoDB" +description = "Todo list with a MongoDB database" +path = "poem/mongodb" +use_cases = ["Web app", "Storage"] +tags = ["poem", "database", "mongodb"] + +[templates.rocket-dyn-templates] +title = "Rocket Handlebars dynamic templates" +description = "HTML templating with Handlebars" +path = "rocket/dyn-templates" +use_cases = ["Web app"] +tags = ["rocket", "handlebars"] + +[templates.rocket-jwt-authentication] +title = "JWT authentication" +description = "Use JWT to authenticate API endpoints" +path = "rocket/jwt-authentication" +use_cases = ["Web app", "Authentication"] +tags = ["rocket", "jwt"] + +[templates.rocket-opendal-memory] +title = "OpenDAL in-memory store" +description = "A hashmap key-value store using OpenDAL" +path = "rocket/opendal-memory" +use_cases = ["Web app", "Storage"] +tags = ["rocket", "opendal"] + +[templates.rocket-persist] +title = "Rocket shuttle-persist" +description = "A hashmap key-value store using OpenDAL" +path = "rocket/persist" +use_cases = ["Web app", "Storage"] +tags = ["rocket", "opendal"] + +[templates.rocket-postgres] +title = "Rocket Postgres" +description = "Todo list with a Postgres database" +path = "rocket/postgres" +use_cases = ["Web app", "Storage"] +tags = ["rocket", "database", "postgres"] + +[templates.rocket-secrets] +title = "Shuttle Secrets" +description = "Rocket app showing how to use Shuttle Secrets" +path = "rocket/secrets" +use_cases = ["Web app"] +tags = ["rocket"] + +[templates.rocket-static-files] +title = "Rocket static file server" +description = "Hello World page that serves static HTML files" +path = "rocket/static-files" +use_cases = ["Web app"] +tags = ["rocket"] + +[templates.rocket-url-shortener] +title = "URL shortener" +description = "Save long URLs behind a short one, with Postgres storage" +path = "rocket/url-shortener" +use_cases = ["Web app", "Storage"] +tags = ["rocket", "database", "postgres"] + +[templates.workspace] +title = "Workspace" +description = "How to use a Shuttle app in a Cargo workspace" +path = "rocket/workspace" +use_cases = [] +tags = [] + +[templates.salvo-image-rescaler] +title = "Image Rescaler" +description = "Use the image library to rescale the Shuttle logo" +path = "salvo/image-rescaler" +use_cases = ["Web app", "Image processing"] +tags = ["salvo", "image"] + +[templates.serenity-postgres] +title = "Serenity Postgres" +description = "Todo list bot with a Postgres database" +path = "serenity/postgres" +use_cases = ["Discord bot", "Storage"] +tags = ["serenity", "database", "postgres"] + +[templates.shuttle-cron] +title = "Shutte custom Cron service" +description = "Schedule tasks with a cron schedule" +path = "shuttle-cron" +use_cases = ["Cron jobs", "Storage"] +tags = ["axum", "apalis", "database", "postgres"] + +[templates.custom-tracing-subscriber] +title = "Custom Tracing Subscriber" +description = "How to use a custom tracing-subscriber on Shuttle" +path = "tracing/custom-tracing-subscriber" +use_cases = ["Web App", "Logging"] +tags = ["actix-web", "tracing"] + + +## COMMUNITY TEMPLATES ## + + +# --- HOW TO ADD TO THE LIST --- +# 1. Your example should be in a public repository. +# 2. If it has a license, it should allow users to copy and modify the code. +# 3. Follow the pattern and add it to the list below +# - Try to keep the description below 120 characters long + +[templates.actix-github-oauth] +title = "GitHub Login (OAuth)" +description = "Sample app demonstrating GitHub OAuth login using Actix Web" +use_cases = ["Web App", "Authentication"] +tags = ["actix-web", "oauth"] +community = true +author = "robjtede" +repo = "https://github.com/robjtede/actix-examples-oauth-github" + +[templates.fullstack-rust] +title = "Fullstack Rust" +description = "A template for fullstack Rust projects" +use_cases = ["Web App"] +tags = ["axum", "yew"] +community = true +author = "TylerBloom" +repo = "https://github.com/TylerBloom/shuttle-fullstack-rust-example" + +[templates.axum-web-app-yew] +title = "Web App with Yew" +description = "A template for a web app using the Yew framework" +use_cases = ["Web App"] +tags = ["axum", "yew"] +community = true +author = "sentinel1909" +repo = "https://github.com/sentinel1909/shuttle-template-yew" + +[templates.actix-web-api] +title = "Web API with Actix Web" +description = "A template for starting an API with Actix Web" +use_cases = ["Web App"] +tags = ["actix-web"] +community = true +author = "sentinel1909" +repo = "https://github.com/sentinel1909/shuttle-template-actix" + +[templates.rocket-yew-sled] +title = "Web API with Rocket and Sled" +description = "A Full Stack CRUD template for starting an API with Rocket, Sled, and Yew" +use_cases = ["Web App"] +tags = ["rocket", "yew"] +community = true +author = "wiseaidev" +repo = "https://github.com/wiseaidev/rocket-yew-starter-pack" diff --git a/thruster/postgres/Cargo.toml b/thruster/postgres/Cargo.toml deleted file mode 100644 index 2d79d170..00000000 --- a/thruster/postgres/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "postgres" -version = "0.1.0" -edition = "2021" - -[dependencies] -hyper = "0.14.23" -serde = { version = "1.0.148", features = ["derive"] } -serde_json = "1.0.89" -shuttle-aws-rds = { version = "0.40.0", features = ["postgres", "sqlx"] } -shuttle-runtime = "0.40.0" -shuttle-thruster = "0.40.0" -sqlx = "0.7.1" -thruster = { version = "1.3.0", features = ["hyper_server"] } -tokio = "1.26.0" diff --git a/thruster/postgres/Shuttle.toml b/thruster/postgres/Shuttle.toml deleted file mode 100644 index 1920c384..00000000 --- a/thruster/postgres/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "postgres-thruster-app" diff --git a/thruster/postgres/schema.sql b/thruster/postgres/schema.sql deleted file mode 100644 index 460e7c23..00000000 --- a/thruster/postgres/schema.sql +++ /dev/null @@ -1,6 +0,0 @@ -DROP TABLE IF EXISTS todos; - -CREATE TABLE todos ( - id serial PRIMARY KEY, - note TEXT NOT NULL -); diff --git a/thruster/postgres/src/main.rs b/thruster/postgres/src/main.rs deleted file mode 100644 index dc553102..00000000 --- a/thruster/postgres/src/main.rs +++ /dev/null @@ -1,114 +0,0 @@ -use serde::{Deserialize, Serialize}; -use shuttle_runtime::CustomError; -use sqlx::{Executor, FromRow, PgPool}; -use thruster::{ - context::{ - context_ext::ContextExt, hyper_request::HyperRequest, - typed_hyper_context::TypedHyperContext, - }, - errors::{ErrorSet, ThrusterError}, - m, middleware_fn, App, Context, HyperServer, MiddlewareNext, MiddlewareResult, ThrusterServer, -}; - -type Ctx = TypedHyperContext; - -#[derive(Deserialize)] -struct TodoNew { - pub note: String, -} - -#[derive(Serialize, FromRow)] -struct Todo { - pub id: i32, - pub note: String, -} - -struct ServerConfig { - pool: PgPool, -} - -#[derive(Clone)] -struct RequestConfig { - pool: PgPool, -} - -fn generate_context(request: HyperRequest, state: &ServerConfig, _path: &str) -> Ctx { - Ctx::new( - request, - RequestConfig { - pool: state.pool.clone(), - }, - ) -} - -#[middleware_fn] -async fn retrieve(mut context: Ctx, _next: MiddlewareNext) -> MiddlewareResult { - let id: i32 = context - .params() - .get("id") - .ok_or_else(|| { - ThrusterError::parsing_error( - Ctx::new_without_request(context.extra.clone()), - "id is required", - ) - })? - .param - .parse() - .map_err(|_e| { - ThrusterError::parsing_error( - Ctx::new_without_request(context.extra.clone()), - "id must be a number", - ) - })?; - - let todo: Todo = sqlx::query_as("SELECT * FROM todos WHERE id = $1") - .bind(id) - .fetch_one(&context.extra.pool) - .await - .map_err(|_e| { - ThrusterError::not_found_error(Ctx::new_without_request(context.extra.clone())) - })?; - - context.set_body(serde_json::to_vec(&todo).unwrap()); - - Ok(context) -} - -#[middleware_fn] -async fn add(mut context: Ctx, _next: MiddlewareNext) -> MiddlewareResult { - let extra = context.extra.clone(); - - let todo_req = context - .get_json::() - .await - .map_err(|_e| ThrusterError::generic_error(Ctx::new_without_request(extra)))?; - - let todo: Todo = sqlx::query_as("INSERT INTO todos(note) VALUES ($1) RETURNING id, note") - .bind(&todo_req.note) - .fetch_one(&context.extra.pool) - .await - .map_err(|_e| { - ThrusterError::generic_error(Ctx::new_without_request(context.extra.clone())) - })?; - - context.set_body(serde_json::to_vec(&todo).unwrap()); - - Ok(context) -} - -#[shuttle_runtime::main] -async fn thruster( - #[shuttle_aws_rds::Postgres] pool: PgPool, -) -> shuttle_thruster::ShuttleThruster> { - pool.execute(include_str!("../schema.sql")) - .await - .map_err(CustomError::new)?; - - let server = HyperServer::new( - App::::create(generate_context, ServerConfig { pool }) - .post("/todos", m![add]) - .get("/todos/:id", m![retrieve]), - ); - - Ok(server.into()) -} diff --git a/tide/postgres/Cargo.toml b/tide/postgres/Cargo.toml deleted file mode 100644 index 9b3f9bf8..00000000 --- a/tide/postgres/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "postgres" -version = "0.1.0" -edition = "2021" - -[dependencies] -serde = { version = "1.0.148", features = ["derive"] } -shuttle-aws-rds = { version = "0.40.0", features = ["postgres", "sqlx"] } -shuttle-runtime = "0.40.0" -shuttle-tide = "0.40.0" -sqlx = "0.7.1" -tokio = "1.26.0" -tide = "0.16.0" diff --git a/tide/postgres/Shuttle.toml b/tide/postgres/Shuttle.toml deleted file mode 100644 index 4ffbeb3e..00000000 --- a/tide/postgres/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "postgres-tide-app" diff --git a/tide/postgres/schema.sql b/tide/postgres/schema.sql deleted file mode 100644 index 460e7c23..00000000 --- a/tide/postgres/schema.sql +++ /dev/null @@ -1,6 +0,0 @@ -DROP TABLE IF EXISTS todos; - -CREATE TABLE todos ( - id serial PRIMARY KEY, - note TEXT NOT NULL -); diff --git a/tide/postgres/src/main.rs b/tide/postgres/src/main.rs deleted file mode 100644 index 1513d849..00000000 --- a/tide/postgres/src/main.rs +++ /dev/null @@ -1,57 +0,0 @@ -use serde::{Deserialize, Serialize}; -use shuttle_runtime::CustomError; -use shuttle_tide::ShuttleTide; -use sqlx::{Executor, FromRow, PgPool}; -use tide::{Body, Request}; - -async fn retrieve(req: Request) -> tide::Result { - let id: i32 = req.param("id")?.parse()?; - let todo: Todo = sqlx::query_as("SELECT * FROM todos WHERE id = $1") - .bind(id) - .fetch_one(&req.state().pool) - .await?; - - Body::from_json(&todo).map(Into::into) -} - -async fn add(mut req: Request) -> tide::Result { - let data: TodoNew = req.body_json().await?; - let todo: Todo = sqlx::query_as("INSERT INTO todos(note) VALUES ($1) RETURNING id, note") - .bind(&data.note) - .fetch_one(&req.state().pool) - .await?; - - Body::from_json(&todo).map(Into::into) -} - -#[derive(Clone)] -struct MyState { - pool: PgPool, -} - -#[shuttle_runtime::main] -async fn tide(#[shuttle_aws_rds::Postgres] pool: PgPool) -> ShuttleTide { - pool.execute(include_str!("../schema.sql")) - .await - .map_err(CustomError::new)?; - - let state = MyState { pool }; - let mut app = tide::with_state(state); - - app.with(tide::log::LogMiddleware::new()); - app.at("/todo").post(add); - app.at("/todo/:id").get(retrieve); - - Ok(app.into()) -} - -#[derive(Deserialize)] -struct TodoNew { - pub note: String, -} - -#[derive(Serialize, FromRow)] -struct Todo { - pub id: i32, - pub note: String, -} diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index f54d60df..1c2095d3 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -10,4 +10,4 @@ shuttle-actix-web = "0.40.0" shuttle-runtime = { version = "0.40.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" -tracing-subscriber = "0.3.17" +tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } From 12ce8a7b5aa60267397a0653c5fc39eda7edf0e8 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Thu, 7 Mar 2024 12:11:10 +0100 Subject: [PATCH 143/239] chore: v0.41.0 (#151) --- actix-web/clerk/backend/Cargo.toml | 6 +++--- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/htmx-crud/Cargo.toml | 6 +++--- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 6 +++--- axum/postgres/Cargo.toml | 6 +++--- axum/qdrant/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 8 ++++---- other/standalone-binary/Cargo.toml | 6 +++--- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 6 +++--- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/opendal-memory/Cargo.toml | 6 +++--- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 6 +++--- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- salvo/image-rescaler/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 6 +++--- serenity/postgres/Cargo.toml | 8 ++++---- thruster/hello-world/Cargo.toml | 4 ++-- tide/hello-world/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 42 files changed, 104 insertions(+), 104 deletions(-) diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml index 95dd4397..689d182c 100644 --- a/actix-web/clerk/backend/Cargo.toml +++ b/actix-web/clerk/backend/Cargo.toml @@ -10,6 +10,6 @@ clerk-rs = "0.2.3" openssl-sys = { version = "0.9.9", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.40.0" -shuttle-runtime = "0.40.0" -shuttle-secrets = "0.40.0" +shuttle-actix-web = "0.41.0" +shuttle-runtime = "0.41.0" +shuttle-secrets = "0.41.0" diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index 7dd86b57..b807562b 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.6.0" actix-session = { version = "0.8.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-actix-web = "0.41.0" +shuttle-runtime = "0.41.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 4a58a27b..941203d1 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-actix-web = "0.41.0" +shuttle-runtime = "0.41.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 25004d9f..dca8b58c 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-actix-web = "0.41.0" +shuttle-runtime = "0.41.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.40.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.41.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index eab9325f..a2063e9f 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-actix-web = "0.41.0" +shuttle-runtime = "0.41.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index ada84ef6..a3b96552 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-actix-web = "0.41.0" +shuttle-runtime = "0.41.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index c450568a..db4aacf9 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-axum = "0.41.0" +shuttle-runtime = "0.41.0" tokio = "1.28.2" tracing = "0.1.40" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index 1f46fb25..6b7acb76 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -9,9 +9,9 @@ askama_axum = "0.4.0" axum = "0.7.4" serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.40.0" -shuttle-runtime = "0.40.0" -shuttle-shared-db = { version = "0.40.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.41.0" +shuttle-runtime = "0.41.0" +shuttle-shared-db = { version = "0.41.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.2", features = ["runtime-tokio-rustls", "postgres"] } tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index d304836e..6d55a4c9 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-axum = "0.41.0" +shuttle-runtime = "0.41.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index 130e9ac3..7aa01c64 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.40.0" -shuttle-runtime = "0.40.0" -shuttle-metadata = "0.40.0" +shuttle-axum = "0.41.0" +shuttle-runtime = "0.41.0" +shuttle-metadata = "0.41.0" tokio = "1.28.2" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 10ac15b3..163b99ee 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.40.0" -shuttle-runtime = "0.40.0" -shuttle-shared-db = { version = "0.40.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.41.0" +shuttle-runtime = "0.41.0" +shuttle-shared-db = { version = "0.41.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index dd0bef76..71d57877 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.7.0" -shuttle-axum = "0.40.0" -shuttle-qdrant = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-axum = "0.41.0" +shuttle-qdrant = "0.41.0" +shuttle-runtime = "0.41.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index c3778e5e..34e95b95 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-axum = "0.41.0" +shuttle-runtime = "0.41.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 1d8afcb0..52c9e6c5 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.40.0" -shuttle-runtime = "0.40.0" -shuttle-turso = "0.40.0" +shuttle-axum = "0.41.0" +shuttle-runtime = "0.41.0" +shuttle-turso = "0.41.0" libsql = "0.2.0" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 56edc816..c7660ff1 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-axum = "0.41.0" +shuttle-runtime = "0.41.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index c557a180..8b45cc07 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1", features = ["derive"] } -shuttle-service = "0.40.0" -shuttle-axum = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-service = "0.41.0" +shuttle-axum = "0.41.0" +shuttle-runtime = "0.41.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index add427c7..64c4bf52 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.40.0" +shuttle-runtime = "0.41.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index 2bb3c16b..47d23cff 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -10,7 +10,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-persist = "0.41.0" +shuttle-runtime = "0.41.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index a651b676..18f9de85 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,10 +16,10 @@ lettre = "0.11.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.40.0" -shuttle-runtime = "0.40.0" -shuttle-secrets = "0.40.0" -shuttle-shared-db = { version = "0.40.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.41.0" +shuttle-runtime = "0.41.0" +shuttle-secrets = "0.41.0" +shuttle-shared-db = { version = "0.41.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.1", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index ec082b2c..94665841 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,7 +15,7 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = "0.40.0" -shuttle-runtime = "0.40.0" -shuttle-secrets = "0.40.0" +shuttle-axum = "0.41.0" +shuttle-runtime = "0.41.0" +shuttle-secrets = "0.41.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index ae68b5a0..6cef211d 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "2.0.0" -shuttle-poem = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-poem = "0.41.0" +shuttle-runtime = "0.41.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 88c48e68..f295a87b 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "2.0.0" -shuttle-poem = "0.40.0" -shuttle-shared-db = { version = "0.40.0", features = ["mongodb"] } -shuttle-runtime = "0.40.0" +shuttle-poem = "0.41.0" +shuttle-shared-db = { version = "0.41.0", features = ["mongodb"] } +shuttle-runtime = "0.41.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index e0cf95dd..03024cb5 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,9 +7,9 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.6.1" -shuttle-runtime = "0.40.0" -shuttle-secrets = "0.40.0" +shuttle-runtime = "0.41.0" +shuttle-secrets = "0.41.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity -shuttle-serenity = "0.40.0" +shuttle-serenity = "0.41.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index ab3ce9d4..48e543d1 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" rocket_dyn_templates = { version = "0.1.0", features = ["handlebars"] } -shuttle-rocket = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-rocket = "0.41.0" +shuttle-runtime = "0.41.0" tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index e6f64d4b..ccdc2b35 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-rocket = "0.41.0" +shuttle-runtime = "0.41.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 52a4bc45..036ae586 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-rocket = "0.41.0" +shuttle-runtime = "0.41.0" tokio = "1.26.0" diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index b191676f..84e1570d 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -4,10 +4,10 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.40.0" -shuttle-opendal = "0.40.0" +shuttle-runtime = "0.41.0" +shuttle-opendal = "0.41.0" tokio = "1.26.0" -shuttle-rocket = "0.40.0" +shuttle-rocket = "0.41.0" opendal = "0.45.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 9b09d962..f3d7a475 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.40.0" -shuttle-rocket = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-persist = "0.41.0" +shuttle-rocket = "0.41.0" +shuttle-runtime = "0.41.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index af477488..b9bbc4ef 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.40.0" -shuttle-runtime = "0.40.0" -shuttle-shared-db = { version = "0.40.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.41.0" +shuttle-runtime = "0.41.0" +shuttle-shared-db = { version = "0.41.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 09a8e2a5..86126335 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.40.0" -shuttle-runtime = "0.40.0" -shuttle-secrets = "0.40.0" +shuttle-rocket = "0.41.0" +shuttle-runtime = "0.41.0" +shuttle-secrets = "0.41.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index ec3c05aa..be72fd8c 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-rocket = "0.41.0" +shuttle-runtime = "0.41.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index e4cb05eb..6d512ee8 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" nanoid = "0.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.40.0" -shuttle-runtime = "0.40.0" -shuttle-shared-db = { version = "0.40.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.41.0" +shuttle-runtime = "0.41.0" +shuttle-shared-db = { version = "0.41.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 6a977126..30a1a3fb 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-rocket = "0.41.0" +shuttle-runtime = "0.41.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index a344a182..35ab9fc8 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] salvo = "0.63.0" -shuttle-salvo = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-salvo = "0.41.0" +shuttle-runtime = "0.41.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml index 51712444..95f76f4d 100644 --- a/salvo/image-rescaler/Cargo.toml +++ b/salvo/image-rescaler/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] image = "0.24.8" salvo = "0.63.0" -shuttle-salvo = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-salvo = "0.41.0" +shuttle-runtime = "0.41.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 2113f959..7a12eba0 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.40.0" -shuttle-secrets = "0.40.0" -shuttle-serenity = "0.40.0" +shuttle-runtime = "0.41.0" +shuttle-secrets = "0.41.0" +shuttle-serenity = "0.41.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 651484ef..ab5f31df 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.40.0" -shuttle-secrets = "0.40.0" -shuttle-serenity = "0.40.0" -shuttle-shared-db = { version = "0.40.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.41.0" +shuttle-secrets = "0.41.0" +shuttle-serenity = "0.41.0" +shuttle-shared-db = { version = "0.41.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 3a79ab46..a7a8ebcc 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-thruster = "0.41.0" +shuttle-runtime = "0.41.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 28437504..332e2c8a 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.40.0" -shuttle-runtime = "0.40.0" +shuttle-tide = "0.41.0" +shuttle-runtime = "0.41.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index d3806c88..b74c77cc 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.40.0" -shuttle-tower = "0.40.0" +shuttle-runtime = "0.41.0" +shuttle-tower = "0.41.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 1c2095d3..9ce74715 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.40.0" +shuttle-actix-web = "0.41.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.40.0", default-features = false } +shuttle-runtime = { version = "0.41.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index a050d916..ddb9eccb 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.40.0" -shuttle-warp = "0.40.0" +shuttle-runtime = "0.41.0" +shuttle-warp = "0.41.0" tokio = "1.26.0" warp = "0.3.3" From 37adada8e7cc51d6e4fe484bc2779835a73d6d99 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Thu, 7 Mar 2024 12:13:38 +0100 Subject: [PATCH 144/239] feat: update templates to latest schema (#150) * feat: update templates to latest schema * nit --- _scripts/check-templates.rs | 31 +++-- axum/hello-world/Cargo.toml | 3 +- templates.toml | 224 ++++++++++++++++++------------------ 3 files changed, 137 insertions(+), 121 deletions(-) diff --git a/_scripts/check-templates.rs b/_scripts/check-templates.rs index 7e2a5383..c3a73769 100644 --- a/_scripts/check-templates.rs +++ b/_scripts/check-templates.rs @@ -11,18 +11,20 @@ use shuttle_common::templates::TemplatesSchema; fn main() { let s = std::fs::read_to_string("templates.toml").expect("to find file"); - let toml: TemplatesSchema = toml::from_str(&s).expect("to parse toml file"); + let schema: TemplatesSchema = toml::from_str(&s).expect("to parse toml file"); let (tx, rx) = std::sync::mpsc::channel::(); - let t = std::thread::spawn(move || rx.into_iter().collect::>()); + let thread = + std::thread::spawn(move || rx.into_iter().collect::>()); let walker = ignore::WalkBuilder::new(".").build_parallel(); walker.run(|| { let tx = tx.clone(); Box::new(move |result| { use ignore::WalkState::*; - // join directory with filename so that this directory can be skipped in the case of a workspace + // Join directory with filename so that this directory can + // be skipped in the case of a workspace manifest. let path = result.unwrap().into_path().join("Cargo.toml"); if !path.exists() { return Continue; @@ -47,12 +49,25 @@ fn main() { }) }); drop(tx); - let mut manifests = t.join().unwrap(); + let mut manifests = thread.join().unwrap(); let mut set = std::collections::BTreeSet::<_>::new(); - for (name, t) in toml.templates { - if t.community.is_some_and(|c| c) { - continue; + // don't validate community templates + for (name, t) in schema + .starters + .into_iter() + .chain(schema.templates.into_iter()) + .chain(schema.examples.into_iter()) + .chain(schema.tutorials.into_iter()) + { + const MAX_LENGTH: usize = 100; + let len = t.title.chars().count() + t.description.chars().count(); + if len > MAX_LENGTH { + eprintln!( + "The title + description of '{}' is too long (length {}; max {})", + name, len, MAX_LENGTH + ); + std::process::exit(1); } let path = t.path.unwrap_or_default(); @@ -79,5 +94,5 @@ fn main() { std::process::exit(1); } - println!("Template definitions verified") + println!("Template definitions verified ✅") } diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index db4aacf9..066715ac 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -4,8 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = "0.7.3" +axum = "0.7.4" shuttle-axum = "0.41.0" shuttle-runtime = "0.41.0" tokio = "1.28.2" -tracing = "0.1.40" diff --git a/templates.toml b/templates.toml index 4493ca4f..b398fa7e 100644 --- a/templates.toml +++ b/templates.toml @@ -1,110 +1,112 @@ # Shuttle Template Definitions # -# Use `rust-script _scripts/check-templates.rs` to validate this list +# The schema is defined in `shuttle_common::templates`. +# Use `rust-script _scripts/check-templates.rs` to validate this list. +version = 1 + ## OFFICIAL STARTERS ## -[templates.actix-web-hello-world] -title = "Actix Web Hello World" +[starters.actix-web-hello-world] +title = "Actix Web" +description = "Powerful and fast web framework" path = "actix-web/hello-world" -type = "starter" use_cases = ["Web app"] tags = ["actix-web"] template = "actix-web" -[templates.axum-hello-world] -title = "Axum Hello World" +[starters.axum-hello-world] +title = "Axum" +description = "Modular web framework from the Tokio ecosystem" path = "axum/hello-world" -type = "starter" use_cases = ["Web app"] tags = ["axum"] template = "axum" -[templates.loco-hello-world] -title = "Loco Hello World" +[starters.loco-hello-world] +title = "Loco" +description = "Batteries included web framework based on Axum" path = "loco/hello-world" -type = "starter" use_cases = ["Web app"] tags = ["loco"] template = "loco" -[templates.poem-hello-world] -title = "Poem Hello World" +[starters.poem-hello-world] +title = "Poem" +description = "Full-featured and easy-to-use web framework" path = "poem/hello-world" -type = "starter" use_cases = ["Web app"] tags = ["poem"] template = "poem" -[templates.poise-hello-world] -title = "Poise Hello World" +[starters.poise-hello-world] +title = "Poise" +description = "Discord Bot framework with good slash command support" path = "poise/hello-world" -type = "starter" use_cases = ["Discord bot"] tags = ["poise", "serenity"] template = "poise" -[templates.rocket-hello-world] -title = "Rocket Hello World" +[starters.rocket-hello-world] +title = "Rocket" +description = "Simple and easy-to-use web framework" path = "rocket/hello-world" -type = "starter" use_cases = ["Web app"] tags = ["rocket"] template = "rocket" -[templates.salvo-hello-world] -title = "Salvo Hello World" +[starters.salvo-hello-world] +title = "Salvo" +description = "Full-featured and easy-to-use web framework" path = "salvo/hello-world" -type = "starter" use_cases = ["Web app"] tags = ["salvo"] template = "salvo" -[templates.serenity-hello-world] -title = "Serenity Hello World" +[starters.serenity-hello-world] +title = "Serenity" +description = "Discord Bot framework" path = "serenity/hello-world" -type = "starter" use_cases = ["Discord bot"] tags = ["serenity"] template = "serenity" -[templates.thruster-hello-world] -title = "Thruster Hello World" +[starters.thruster-hello-world] +title = "Thruster" +description = "Web framework" path = "thruster/hello-world" -type = "starter" use_cases = ["Web app"] tags = ["thruster"] template = "thruster" -[templates.tide-hello-world] -title = "Tide Hello World" +[starters.tide-hello-world] +title = "Tide" +description = "Web framework" path = "tide/hello-world" -type = "starter" use_cases = ["Web app"] tags = ["tide"] template = "tide" -[templates.tower-hello-world] -title = "Tower Hello World" +[starters.tower-hello-world] +title = "Tower" +description = "Modular service library" path = "tower/hello-world" -type = "starter" use_cases = ["Web app"] tags = ["tower"] template = "tower" -[templates.warp-hello-world] -title = "Warp Hello World" +[starters.warp-hello-world] +title = "Warp" +description = "Web framework" path = "warp/hello-world" -type = "starter" use_cases = ["Web app"] tags = ["warp"] template = "warp" -[templates.none] -title = "None" -description = "Empty service - A barebones implementation of Shuttle Service trait that does nothing" +[starters.no-framework] +title = "No framework" +description = "An empty implementation of the Shuttle Service trait" path = "custom-service/none" -type = "starter" use_cases = [] tags = ["diy"] template = "none" @@ -112,9 +114,8 @@ template = "none" ## OFFICIAL TEMPLATES ## - [templates.actix-web-postgres] -title = "Actix Web Postgres" +title = "Postgres" description = "Todo list with a Postgres database" path = "actix-web/postgres" use_cases = ["Web app", "Storage"] @@ -135,21 +136,21 @@ use_cases = ["Web app", "Authentication"] tags = ["actix-web", "jwt"] [templates.actix-websocket-actorless] -title = "Actix Web Actorless Websockets" +title = "Websockets Actorless" description = "Health monitoring service using websockets" path = "actix-web/websocket-actorless" use_cases = ["Web app", "Monitoring"] tags = ["actix-web", "websocket"] [templates.actix-static-files] -title = "Actix Web static file server" +title = "File server" description = "Hello World page that serves static HTML and JS files" path = "actix-web/static-files" use_cases = ["Web app"] tags = ["actix-web"] [templates.axum-htmx-crud] -title = "Axum + HTMX" +title = "HTMX" description = "Simple CRUD app using HTMX and Askama" path = "axum/htmx-crud" use_cases = ["Web app", "Storage"] @@ -162,15 +163,8 @@ path = "axum/jwt-authentication" use_cases = ["Web app", "Authentication"] tags = ["axum", "jwt"] -[templates.axum-metadata] -title = "Shuttle Metadata" -description = "Basic usage of Shuttle metadata" -path = "axum/metadata" -use_cases = [] -tags = ["axum"] - [templates.axum-postgres] -title = "Axum Postgres" +title = "Postgres" description = "Todo list with a Postgres database" path = "axum/postgres" use_cases = ["Web app", "Storage"] @@ -198,19 +192,12 @@ use_cases = ["Web app", "Storage"] tags = ["axum", "database", "libsql", "sqlite"] [templates.axum-websocket] -title = "Axum Websockets" +title = "Websockets" description = "Health monitoring service using websockets" path = "axum/websocket" use_cases = ["Web app", "Monitoring"] tags = ["axum", "websocket"] -[templates.custom-resource-pdo] -title = "Custom Resource" -description = "A custom resource for the Shuttle main macro" -path = "custom-resource/pdo" -use_cases = [] -tags = ["diy"] - [templates.request-scheduler] title = "Request Scheduler" description = "Schedule requests with a cron schedule" @@ -225,22 +212,15 @@ path = "fullstack-templates/saas" use_cases = ["Web app", "Authentication", "Storage", "Monetization"] tags = ["axum", "next.js", "database", "postgres", "typescript", "tailwind"] -[templates.standalone-binary] -title = "Standalone binary" -description = "How to split a project to allow it to run both with Shuttle and standalone" -path = "other/standalone-binary" -use_cases = [] -tags = ["diy", "axum"] - [templates.poem-mongodb] -title = "Poem MongoDB" +title = "MongoDB" description = "Todo list with a MongoDB database" path = "poem/mongodb" use_cases = ["Web app", "Storage"] tags = ["poem", "database", "mongodb"] [templates.rocket-dyn-templates] -title = "Rocket Handlebars dynamic templates" +title = "Handlebars dynamic templates" description = "HTML templating with Handlebars" path = "rocket/dyn-templates" use_cases = ["Web app"] @@ -255,34 +235,20 @@ tags = ["rocket", "jwt"] [templates.rocket-opendal-memory] title = "OpenDAL in-memory store" -description = "A hashmap key-value store using OpenDAL" +description = "A key-value store using OpenDAL" path = "rocket/opendal-memory" use_cases = ["Web app", "Storage"] tags = ["rocket", "opendal"] -[templates.rocket-persist] -title = "Rocket shuttle-persist" -description = "A hashmap key-value store using OpenDAL" -path = "rocket/persist" -use_cases = ["Web app", "Storage"] -tags = ["rocket", "opendal"] - [templates.rocket-postgres] -title = "Rocket Postgres" +title = "Postgres" description = "Todo list with a Postgres database" path = "rocket/postgres" use_cases = ["Web app", "Storage"] tags = ["rocket", "database", "postgres"] -[templates.rocket-secrets] -title = "Shuttle Secrets" -description = "Rocket app showing how to use Shuttle Secrets" -path = "rocket/secrets" -use_cases = ["Web app"] -tags = ["rocket"] - [templates.rocket-static-files] -title = "Rocket static file server" +title = "File server" description = "Hello World page that serves static HTML files" path = "rocket/static-files" use_cases = ["Web app"] @@ -295,13 +261,6 @@ path = "rocket/url-shortener" use_cases = ["Web app", "Storage"] tags = ["rocket", "database", "postgres"] -[templates.workspace] -title = "Workspace" -description = "How to use a Shuttle app in a Cargo workspace" -path = "rocket/workspace" -use_cases = [] -tags = [] - [templates.salvo-image-rescaler] title = "Image Rescaler" description = "Use the image library to rescale the Shuttle logo" @@ -310,15 +269,15 @@ use_cases = ["Web app", "Image processing"] tags = ["salvo", "image"] [templates.serenity-postgres] -title = "Serenity Postgres" -description = "Todo list bot with a Postgres database" +title = "Postgres" +description = "Todo list Discord bot with a Postgres database" path = "serenity/postgres" use_cases = ["Discord bot", "Storage"] tags = ["serenity", "database", "postgres"] [templates.shuttle-cron] title = "Shutte custom Cron service" -description = "Schedule tasks with a cron schedule" +description = "Schedule tasks on a cron schedule with apalis" path = "shuttle-cron" use_cases = ["Cron jobs", "Storage"] tags = ["axum", "apalis", "database", "postgres"] @@ -331,56 +290,99 @@ use_cases = ["Web App", "Logging"] tags = ["actix-web", "tracing"] -## COMMUNITY TEMPLATES ## +## EXAMPLES ## +[examples.metadata] +title = "Shuttle Metadata" +description = "Basic usage of shuttle-metadata" +path = "axum/metadata" +use_cases = [] +tags = ["axum"] + +[examples.persist] +title = "Shuttle Persist" +description = "Basic usage of shuttle-persist" +path = "rocket/persist" +use_cases = ["Web app", "Storage"] +tags = ["rocket"] + +[examples.secrets] +title = "Shuttle Secrets" +description = "Basic usage of shuttle-secrets" +path = "rocket/secrets" +use_cases = ["Web app"] +tags = ["rocket"] + +[examples.workspace] +title = "Workspace" +description = "How to use a Shuttle app in a Cargo workspace" +path = "rocket/workspace" +use_cases = [] +tags = [] + +[examples.custom-resource-pdo] +title = "Custom Resource" +description = "A custom PDO resource for the Shuttle main macro" +path = "custom-resource/pdo" +use_cases = [] +tags = ["diy"] + +[examples.standalone-binary] +title = "Standalone binary" +description = "How to run an app both with Shuttle and standalone" +path = "other/standalone-binary" +use_cases = [] +tags = ["diy", "axum"] + + +## TUTORIALS ## + +[tutorials] + + +## COMMUNITY TEMPLATES ## # --- HOW TO ADD TO THE LIST --- # 1. Your example should be in a public repository. # 2. If it has a license, it should allow users to copy and modify the code. # 3. Follow the pattern and add it to the list below -# - Try to keep the description below 120 characters long -[templates.actix-github-oauth] +[community_templates.actix-github-oauth] title = "GitHub Login (OAuth)" description = "Sample app demonstrating GitHub OAuth login using Actix Web" use_cases = ["Web App", "Authentication"] tags = ["actix-web", "oauth"] -community = true author = "robjtede" repo = "https://github.com/robjtede/actix-examples-oauth-github" -[templates.fullstack-rust] +[community_templates.fullstack-rust-axum-yew] title = "Fullstack Rust" -description = "A template for fullstack Rust projects" +description = "A template for fullstack Rust projects with Yew" use_cases = ["Web App"] tags = ["axum", "yew"] -community = true author = "TylerBloom" repo = "https://github.com/TylerBloom/shuttle-fullstack-rust-example" -[templates.axum-web-app-yew] +[community_templates.axum-web-app-yew] title = "Web App with Yew" description = "A template for a web app using the Yew framework" use_cases = ["Web App"] tags = ["axum", "yew"] -community = true author = "sentinel1909" repo = "https://github.com/sentinel1909/shuttle-template-yew" -[templates.actix-web-api] +[community_templates.actix-web-api] title = "Web API with Actix Web" description = "A template for starting an API with Actix Web" use_cases = ["Web App"] tags = ["actix-web"] -community = true author = "sentinel1909" repo = "https://github.com/sentinel1909/shuttle-template-actix" -[templates.rocket-yew-sled] +[community_templates.rocket-yew-sled] title = "Web API with Rocket and Sled" description = "A Full Stack CRUD template for starting an API with Rocket, Sled, and Yew" use_cases = ["Web App"] tags = ["rocket", "yew"] -community = true author = "wiseaidev" repo = "https://github.com/wiseaidev/rocket-yew-starter-pack" From 5ca168046d498c64a682913d3b3fea2f899d0f16 Mon Sep 17 00:00:00 2001 From: Aadi Desai <21363892+supleed2@users.noreply.github.com> Date: Thu, 7 Mar 2024 20:51:39 +0530 Subject: [PATCH 145/239] fix: replace deprecated fn call in example `rocket/jwt-authentication` (#152) `chrono::TimeDelta::minutes` to `chrono::TimeDelta::try_minutes`, with `.expect` --- rocket/jwt-authentication/src/claims.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rocket/jwt-authentication/src/claims.rs b/rocket/jwt-authentication/src/claims.rs index dde34121..0ddd281e 100644 --- a/rocket/jwt-authentication/src/claims.rs +++ b/rocket/jwt-authentication/src/claims.rs @@ -18,7 +18,8 @@ const SECRET: &str = "secret"; lazy_static! { /// Time before token expires (aka exp claim) - static ref TOKEN_EXPIRATION: Duration = Duration::minutes(5); + static ref TOKEN_EXPIRATION: Duration = Duration::try_minutes(5) + .expect("failed to create an expiration duration"); } // Used when decoding a token to `Claims` From 90bc7170847d999a5bb819230fa41e7c870a5cce Mon Sep 17 00:00:00 2001 From: Lonanche <39042008+Lonanche@users.noreply.github.com> Date: Mon, 11 Mar 2024 13:45:56 +0000 Subject: [PATCH 146/239] add serenity weather forecast bot example (#146) * add serenity weather forecast bot example * fix: formatting * bump versions * add to templates.toml --------- Co-authored-by: jonaro00 <54029719+jonaro00@users.noreply.github.com> --- serenity/weather-forecast/Cargo.toml | 15 +++ serenity/weather-forecast/README.md | 3 + serenity/weather-forecast/Secrets.toml | 3 + serenity/weather-forecast/src/main.rs | 131 +++++++++++++++++++++++ serenity/weather-forecast/src/weather.rs | 88 +++++++++++++++ templates.toml | 7 ++ 6 files changed, 247 insertions(+) create mode 100644 serenity/weather-forecast/Cargo.toml create mode 100644 serenity/weather-forecast/README.md create mode 100644 serenity/weather-forecast/Secrets.toml create mode 100644 serenity/weather-forecast/src/main.rs create mode 100644 serenity/weather-forecast/src/weather.rs diff --git a/serenity/weather-forecast/Cargo.toml b/serenity/weather-forecast/Cargo.toml new file mode 100644 index 00000000..8cb47309 --- /dev/null +++ b/serenity/weather-forecast/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "shuttle-docs-weather-bot" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.66" +reqwest = { version = "0.11.24", features = ["json"] } +serde = "1.0.197" +serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } +shuttle-runtime = "0.41.0" +shuttle-secrets = "0.41.0" +shuttle-serenity = "0.41.0" +tokio = "1.26.0" +tracing = "0.1.37" diff --git a/serenity/weather-forecast/README.md b/serenity/weather-forecast/README.md new file mode 100644 index 00000000..34b9de58 --- /dev/null +++ b/serenity/weather-forecast/README.md @@ -0,0 +1,3 @@ +# Serenity Weather Forecast Bot with Shuttle + +For a full tutorial on how to build and set up this bot, please refer to [Shuttle docs](https://docs.shuttle.rs/templates/tutorials/discord-weather-forecast) diff --git a/serenity/weather-forecast/Secrets.toml b/serenity/weather-forecast/Secrets.toml new file mode 100644 index 00000000..b1b9f929 --- /dev/null +++ b/serenity/weather-forecast/Secrets.toml @@ -0,0 +1,3 @@ +DISCORD_TOKEN = "the contents of my discord token" +DISCORD_GUILD_ID="123456789" +WEATHER_API_KEY="the contents of my weather api key" \ No newline at end of file diff --git a/serenity/weather-forecast/src/main.rs b/serenity/weather-forecast/src/main.rs new file mode 100644 index 00000000..36a483eb --- /dev/null +++ b/serenity/weather-forecast/src/main.rs @@ -0,0 +1,131 @@ +mod weather; + +use anyhow::Context as _; +use serenity::all::{GuildId, Interaction}; +use serenity::async_trait; +use serenity::builder::{ + CreateCommand, CreateCommandOption, CreateInteractionResponse, CreateInteractionResponseMessage, +}; +use serenity::model::gateway::Ready; +use serenity::prelude::*; +use shuttle_secrets::SecretStore; +use tracing::info; + +struct Bot { + weather_api_key: String, + client: reqwest::Client, + discord_guild_id: GuildId, +} + +#[async_trait] +impl EventHandler for Bot { + async fn ready(&self, ctx: Context, ready: Ready) { + info!("{} is connected!", ready.user.name); + + let commands = vec![ + CreateCommand::new("hello").description("Say hello"), + CreateCommand::new("weather") + .description("Display the weather") + .add_option( + CreateCommandOption::new( + serenity::all::CommandOptionType::String, + "place", + "City to lookup forecast", + ) + .required(true), + ), + ]; + + let commands = &self + .discord_guild_id + .set_commands(&ctx.http, commands) + .await + .unwrap(); + + info!("Registered commands: {:#?}", commands); + } + + async fn interaction_create(&self, ctx: Context, interaction: Interaction) { + if let Interaction::Command(command) = interaction { + let response_content = match command.data.name.as_str() { + "hello" => "hello".to_owned(), + "weather" => { + let argument = command + .data + .options + .iter() + .find(|opt| opt.name == "place") + .cloned(); + + let value = argument.unwrap().value; + let place = value.as_str().unwrap(); + + let result = + weather::get_forecast(place, &self.weather_api_key, &self.client).await; + + match result { + Ok((location, forecast)) => { + format!("Forecast: {} in {}", forecast.headline.overview, location) + } + Err(err) => { + format!("Err: {}", err) + } + } + } + command => unreachable!("Unknown command: {}", command), + }; + + let data = CreateInteractionResponseMessage::new().content(response_content); + let builder = CreateInteractionResponse::Message(data); + + if let Err(why) = command.create_response(&ctx.http, builder).await { + println!("Cannot respond to slash command: {why}"); + } + } + } +} + +#[shuttle_runtime::main] +async fn serenity( + #[shuttle_secrets::Secrets] secret_store: SecretStore, +) -> shuttle_serenity::ShuttleSerenity { + // Get the discord token set in `Secrets.toml` + let discord_token = secret_store + .get("DISCORD_TOKEN") + .context("'DISCORD_TOKEN' was not found")?; + + let weather_api_key = secret_store + .get("WEATHER_API_KEY") + .context("'WEATHER_API_KEY' was not found")?; + + let discord_guild_id = secret_store + .get("DISCORD_GUILD_ID") + .context("'DISCORD_GUILD_ID' was not found")?; + + let client = get_client( + &discord_token, + &weather_api_key, + discord_guild_id.parse().unwrap(), + ) + .await; + Ok(client.into()) +} + +pub async fn get_client( + discord_token: &str, + weather_api_key: &str, + discord_guild_id: u64, +) -> Client { + // Set gateway intents, which decides what events the bot will be notified about. + // Here we don't need any intents so empty + let intents = GatewayIntents::empty(); + + Client::builder(discord_token, intents) + .event_handler(Bot { + weather_api_key: weather_api_key.to_owned(), + client: reqwest::Client::new(), + discord_guild_id: GuildId::new(discord_guild_id), + }) + .await + .expect("Err creating client") +} diff --git a/serenity/weather-forecast/src/weather.rs b/serenity/weather-forecast/src/weather.rs new file mode 100644 index 00000000..21269f52 --- /dev/null +++ b/serenity/weather-forecast/src/weather.rs @@ -0,0 +1,88 @@ +use reqwest::Client; +use serde::Deserialize; +use std::fmt::Display; + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "PascalCase")] +pub struct Location { + key: String, + localized_name: String, + country: Country, +} + +impl Display for Location { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}, {}", self.localized_name, self.country.id) + } +} + +#[derive(Deserialize, Debug)] +pub struct Country { + #[serde(alias = "ID")] + pub id: String, +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "PascalCase")] +pub struct Forecast { + pub headline: Headline, +} + +#[derive(Deserialize, Debug)] +pub struct Headline { + #[serde(alias = "Text")] + pub overview: String, +} + +#[derive(Debug)] +pub struct CouldNotFindLocation { + place: String, +} + +impl Display for CouldNotFindLocation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Could not find location '{}'", self.place) + } +} + +impl std::error::Error for CouldNotFindLocation {} + +pub async fn get_forecast( + place: &str, + api_key: &str, + client: &Client, +) -> Result<(Location, Forecast), Box> { + // Endpoints we will use + const LOCATION_REQUEST: &str = "http://dataservice.accuweather.com/locations/v1/cities/search"; + const DAY_REQUEST: &str = "http://dataservice.accuweather.com/forecasts/v1/daily/1day/"; + + // The URL to call combined with our API_KEY and the place (via the q search parameter) + let url = format!("{}?apikey={}&q={}", LOCATION_REQUEST, api_key, place); + // Make the request we will call + let request = client.get(url).build().unwrap(); + // Execute the request and await a JSON result that will be converted to a + // vector of locations + let resp = client + .execute(request) + .await? + .json::>() + .await?; + + // Get the first location. If empty respond with the above declared + // `CouldNotFindLocation` error type + let first_location = resp + .into_iter() + .next() + .ok_or_else(|| CouldNotFindLocation { + place: place.to_owned(), + })?; + + // Now have the location combine the key/identifier with the URL + let url = format!("{}{}?apikey={}", DAY_REQUEST, first_location.key, api_key); + + let request = client.get(url).build().unwrap(); + let forecast = client.execute(request).await?.json::().await?; + + // Combine the location with the forecast + Ok((first_location, forecast)) +} diff --git a/templates.toml b/templates.toml index b398fa7e..4596e18d 100644 --- a/templates.toml +++ b/templates.toml @@ -275,6 +275,13 @@ path = "serenity/postgres" use_cases = ["Discord bot", "Storage"] tags = ["serenity", "database", "postgres"] +[templates.serenity-weather-forecast] +title = "Weather Bot" +description = "Weather forecast Discord bot using the Accuweather API" +path = "serenity/weather-forecast" +use_cases = ["Discord bot"] +tags = ["serenity"] + [templates.shuttle-cron] title = "Shutte custom Cron service" description = "Schedule tasks on a cron schedule with apalis" From 334172453ede115944d6df959f7575db66e91ad7 Mon Sep 17 00:00:00 2001 From: Joshua Mo <102877324+joshua-mo-143@users.noreply.github.com> Date: Mon, 11 Mar 2024 18:05:48 +0000 Subject: [PATCH 147/239] feat: bevy+axum hello world (#144) * feat: move bevy example to supported * chore: update dependencies * feat: move bevy example to supported chore: update dependencies * fix: wasm-bindgen version * fIx ThE gAmE * rename to bevy/hello-world * add to starters * fmt * ci: ignore workspace manifests * ci: libasound * ci * ci --------- Co-authored-by: jonaro00 <54029719+jonaro00@users.noreply.github.com> --- .github/workflows/ci.yml | 33 ++++------------ bevy/hello-world/.gitignore | 5 +++ bevy/hello-world/Cargo.toml | 3 ++ bevy/hello-world/Makefile | 5 +++ bevy/hello-world/README.md | 20 ++++++++++ bevy/hello-world/Shuttle.toml | 1 + bevy/hello-world/dist/Roboto-Black.ttf | Bin 0 -> 168060 bytes bevy/hello-world/dist/index.html | 31 +++++++++++++++ bevy/hello-world/game/Cargo.toml | 7 ++++ bevy/hello-world/game/src/main.rs | 50 +++++++++++++++++++++++++ bevy/hello-world/server/Cargo.toml | 11 ++++++ bevy/hello-world/server/src/main.rs | 11 ++++++ ci.sh | 2 + templates.toml | 7 ++++ 14 files changed, 161 insertions(+), 25 deletions(-) create mode 100644 bevy/hello-world/.gitignore create mode 100644 bevy/hello-world/Cargo.toml create mode 100644 bevy/hello-world/Makefile create mode 100644 bevy/hello-world/README.md create mode 100644 bevy/hello-world/Shuttle.toml create mode 100644 bevy/hello-world/dist/Roboto-Black.ttf create mode 100644 bevy/hello-world/dist/index.html create mode 100644 bevy/hello-world/game/Cargo.toml create mode 100644 bevy/hello-world/game/src/main.rs create mode 100644 bevy/hello-world/server/Cargo.toml create mode 100644 bevy/hello-world/server/src/main.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a4b4292d..d613fe21 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,31 +25,11 @@ jobs: - run: rust-script _scripts/check-templates.rs - fmt-clippy-a-p: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Install sccache - run: | - SCCACHE_VERSION='v0.7.7' - curl -L https://github.com/mozilla/sccache/releases/download/$SCCACHE_VERSION/sccache-$SCCACHE_VERSION-x86_64-unknown-linux-musl.tar.gz \ - | tar -xOz sccache-$SCCACHE_VERSION-x86_64-unknown-linux-musl/sccache \ - > /home/runner/.cargo/bin/sccache \ - && chmod +x /home/runner/.cargo/bin/sccache + fmt-clippy: + strategy: + matrix: + from-to: ["a q", "q zzz"] - - name: Check formatting and Clippy - shell: bash - run: ./ci.sh a q - env: - RUSTC_WRAPPER: /home/runner/.cargo/bin/sccache - CARGO_TARGET_DIR: /tmp/target - - - name: Show sccache stats - run: /home/runner/.cargo/bin/sccache --show-stats - - fmt-clippy-q-z: runs-on: ubuntu-latest steps: @@ -63,9 +43,12 @@ jobs: > /home/runner/.cargo/bin/sccache \ && chmod +x /home/runner/.cargo/bin/sccache + # bevy dependency + - run: sudo apt install -y libasound2-dev libudev-dev + - name: Check formatting and Clippy shell: bash - run: ./ci.sh q zzz + run: ./ci.sh ${{ matrix.from-to }} env: RUSTC_WRAPPER: /home/runner/.cargo/bin/sccache CARGO_TARGET_DIR: /tmp/target diff --git a/bevy/hello-world/.gitignore b/bevy/hello-world/.gitignore new file mode 100644 index 00000000..f5ed2c1c --- /dev/null +++ b/bevy/hello-world/.gitignore @@ -0,0 +1,5 @@ +target/ +Secrets*.toml +dist/* +!dist/index.html +!dist/Roboto-Black.ttf diff --git a/bevy/hello-world/Cargo.toml b/bevy/hello-world/Cargo.toml new file mode 100644 index 00000000..057ec7eb --- /dev/null +++ b/bevy/hello-world/Cargo.toml @@ -0,0 +1,3 @@ +[workspace] +resolver = "2" +members = ["game", "server"] diff --git a/bevy/hello-world/Makefile b/bevy/hello-world/Makefile new file mode 100644 index 00000000..3f921b4e --- /dev/null +++ b/bevy/hello-world/Makefile @@ -0,0 +1,5 @@ +build: + cargo build --package game --release --target wasm32-unknown-unknown && \ + wasm-bindgen --out-dir dist --target web target/wasm32-unknown-unknown/release/game.wasm +up: build + cargo shuttle run diff --git a/bevy/hello-world/README.md b/bevy/hello-world/README.md new file mode 100644 index 00000000..b2bbc7d5 --- /dev/null +++ b/bevy/hello-world/README.md @@ -0,0 +1,20 @@ +Example of how you can compile Bevy to WASM and run it on Shuttle. + +## Instructions + +Make sure you have `wasm-bindgen-cli` and the rustup `wasm32-unknown-unknown` compilation target added. If you don't, you can get them by running the following: +```bash +cargo install wasm-bindgen-cli +rustup target add wasm32-unknown-unknown +``` + +You can try the example out by simply running `cargo run`, or go straight to compilation if you want to get your game straight to the browser. + +In the Makefile, there is a command for compiling the game to WASM. +If you don't have `make` installed, you can run the command manually. + +```bash +make build +``` + +Go to the project workspace root or the `server` folder, run `cargo shuttle run`, then visit `http://localhost:8000/game`, you should see your Bevy program in action! diff --git a/bevy/hello-world/Shuttle.toml b/bevy/hello-world/Shuttle.toml new file mode 100644 index 00000000..f7d66cb3 --- /dev/null +++ b/bevy/hello-world/Shuttle.toml @@ -0,0 +1 @@ +assets = ["dist/*"] diff --git a/bevy/hello-world/dist/Roboto-Black.ttf b/bevy/hello-world/dist/Roboto-Black.ttf new file mode 100644 index 0000000000000000000000000000000000000000..0112e7da626ca2f959eca850c806779ba55dbfbd GIT binary patch literal 168060 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
    TJYyt(6q>rW4S(W4gHIq&3$utU3y8!9=k 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 WVelBb2)1!{_R^~ms-+tiJp5mlrotHj literal 0 HcmV?d00001 diff --git a/bevy/hello-world/dist/index.html b/bevy/hello-world/dist/index.html new file mode 100644 index 00000000..7158d7ea --- /dev/null +++ b/bevy/hello-world/dist/index.html @@ -0,0 +1,31 @@ + + + + + + + My Game + + + + + + + + diff --git a/bevy/hello-world/game/Cargo.toml b/bevy/hello-world/game/Cargo.toml new file mode 100644 index 00000000..1e0577a0 --- /dev/null +++ b/bevy/hello-world/game/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "game" +version = "0.1.0" +edition = "2021" + +[dependencies] +bevy = { version = "0.13", features = ["webgl2"] } diff --git a/bevy/hello-world/game/src/main.rs b/bevy/hello-world/game/src/main.rs new file mode 100644 index 00000000..1304c1c6 --- /dev/null +++ b/bevy/hello-world/game/src/main.rs @@ -0,0 +1,50 @@ +use bevy::diagnostic::FrameTimeDiagnosticsPlugin; +use bevy::diagnostic::LogDiagnosticsPlugin; +use bevy::prelude::*; +use bevy::window::{MonitorSelection, WindowPosition}; + +fn main() { + App::new() + .add_plugins(( + DefaultPlugins.set(WindowPlugin { + primary_window: Some(Window { + prevent_default_event_handling: false, + canvas: Some("#canvas".to_string()), + position: WindowPosition::Centered(MonitorSelection::Current), + ..default() + }), + ..default() + }), + LogDiagnosticsPlugin::default(), + FrameTimeDiagnosticsPlugin, + )) + .add_systems(Startup, setup) + .add_systems(Update, main_menu) + .run(); +} + +fn setup(mut commands: Commands) { + commands.spawn(Camera2dBundle::default()); +} + +fn main_menu(mut commands: Commands, asset_server: Res) { + let font = asset_server.load("/Roboto-Black.ttf"); + + let title_font = title_text_style(60.0, font.clone()); + + commands.spawn({ + Text2dBundle { + text: Text::from_section("Hello world!", title_font.clone()) + .with_justify(JustifyText::Center), + ..default() + } + }); +} + +fn title_text_style(font_size: f32, font: Handle) -> TextStyle { + TextStyle { + font, + font_size, + color: Color::WHITE, + } +} diff --git a/bevy/hello-world/server/Cargo.toml b/bevy/hello-world/server/Cargo.toml new file mode 100644 index 00000000..d5492685 --- /dev/null +++ b/bevy/hello-world/server/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "shuttle-bevy-ex" +version = "0.1.0" +edition = "2021" + +[dependencies] +axum = "0.7.4" +shuttle-axum = "0.41.0" +shuttle-runtime = "0.41.0" +tokio = "1.28.2" +tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/bevy/hello-world/server/src/main.rs b/bevy/hello-world/server/src/main.rs new file mode 100644 index 00000000..853fc147 --- /dev/null +++ b/bevy/hello-world/server/src/main.rs @@ -0,0 +1,11 @@ +use axum::Router; +use tower_http::services::{ServeDir, ServeFile}; + +#[shuttle_runtime::main] +async fn main() -> shuttle_axum::ShuttleAxum { + let router = Router::new().nest_service( + "/", + ServeDir::new("dist").not_found_service(ServeFile::new("dist/index.html")), + ); + Ok(router.into()) +} diff --git a/ci.sh b/ci.sh index dac2e029..e141c13b 100755 --- a/ci.sh +++ b/ci.sh @@ -10,6 +10,8 @@ DIRS=$(find . -name Cargo.toml -exec dirname {} \; | sort | awk -v from="$FROM" # Loop through each directory and run cargo fmt and cargo clippy, exit on failure for dir in $DIRS; do + grep "\[workspace\]" "$dir/Cargo.toml" > /dev/null && continue + echo "Checking $dir" cargo fmt --all --manifest-path "$dir/Cargo.toml" -- --check cargo clippy --no-deps --manifest-path "$dir/Cargo.toml" -- -D warnings diff --git a/templates.toml b/templates.toml index 4596e18d..c8374a69 100644 --- a/templates.toml +++ b/templates.toml @@ -23,6 +23,13 @@ use_cases = ["Web app"] tags = ["axum"] template = "axum" +[starters.bevy-hello-world] +title = "Bevy" +description = "Data driven game engine that compiles to WASM" +path = "bevy/hello-world" +use_cases = ["Web app", "Game"] +tags = ["bevy", "axum"] + [starters.loco-hello-world] title = "Loco" description = "Batteries included web framework based on Axum" From 732d8b16e4eeed8fb73a1784128d8c27f9af1a7f Mon Sep 17 00:00:00 2001 From: Joshua Mo <102877324+joshua-mo-143@users.noreply.github.com> Date: Tue, 12 Mar 2024 15:10:11 +0000 Subject: [PATCH 148/239] feat: Oauth2 template (#155) * fix: satisfy CI & make more prod-ready * docs: update README.md * fix: satisfy CI (deprecated fn) * fix: add to templates --------- Co-authored-by: jonaro00 <54029719+jonaro00@users.noreply.github.com> --- axum/oauth2/.gitignore | 2 + axum/oauth2/Cargo.toml | 22 ++++ axum/oauth2/README.md | 18 +++ .../migrations/20230815100114_schema.down.sql | 3 + .../migrations/20230815100114_schema.up.sql | 15 +++ axum/oauth2/src/main.rs | 93 ++++++++++++++ axum/oauth2/src/routes/errors.rs | 46 +++++++ axum/oauth2/src/routes/mod.rs | 2 + axum/oauth2/src/routes/oauth.rs | 114 ++++++++++++++++++ templates.toml | 7 ++ 10 files changed, 322 insertions(+) create mode 100644 axum/oauth2/.gitignore create mode 100644 axum/oauth2/Cargo.toml create mode 100644 axum/oauth2/README.md create mode 100644 axum/oauth2/migrations/20230815100114_schema.down.sql create mode 100644 axum/oauth2/migrations/20230815100114_schema.up.sql create mode 100644 axum/oauth2/src/main.rs create mode 100644 axum/oauth2/src/routes/errors.rs create mode 100644 axum/oauth2/src/routes/mod.rs create mode 100644 axum/oauth2/src/routes/oauth.rs diff --git a/axum/oauth2/.gitignore b/axum/oauth2/.gitignore new file mode 100644 index 00000000..4fcf1cd7 --- /dev/null +++ b/axum/oauth2/.gitignore @@ -0,0 +1,2 @@ +target/ +Secrets*.toml diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml new file mode 100644 index 00000000..881193fb --- /dev/null +++ b/axum/oauth2/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "oauth-axum-shuttle-ex" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.72" +axum = { version = "0.7.2", features = ["multipart", "macros"] } +axum-extra = { version = "0.9.2", features = ["cookie-private"] } +chrono = { version = "0.4.35", features = ["clock"] } +oauth2 = "4.4.1" +reqwest = { version = "0.11.18", features = ["json"] } +serde = { version = "1.0.183", features = ["derive"] } +shuttle-axum = "0.41.0" +shuttle-runtime = "0.41.0" +shuttle-secrets = "0.41.0" +shuttle-shared-db = { version = "0.41.0", features = ["postgres", "sqlx"] } +sqlx = { version = "0.7.2", features = ["runtime-tokio-rustls", "macros", "chrono"] } +thiserror = "1.0.57" +time = "0.3.25" +tokio = "1.28.2" +tracing = "0.1.37" diff --git a/axum/oauth2/README.md b/axum/oauth2/README.md new file mode 100644 index 00000000..bc3237a2 --- /dev/null +++ b/axum/oauth2/README.md @@ -0,0 +1,18 @@ +## OAuth Axum Rust Example +This repo is an example of how you can quickly and easily implement OAuth using the Axum web framework in Rust. Hosted on Shuttle. + +### How to Run +Make sure you set up your Google OAuth, which you can find a link to set up [here.](https://console.cloud.google.com/apis/dashboard) + +Initialise your Shuttle project with `cargo shuttle init`: +```sh +cargo shuttle init --from shuttle-hq/examples --subfolder axum/oauth2 +``` + +Set your secrets in the Secrets.toml file: +```toml +GOOGLE_OAUTH_CLIENT_ID = "your-client-id" +GOOGLE_OAUTH_CLIENT_SECRET = "your-client-secret" +``` + +Use `cargo shuttle run` and visit `http://localhost:8000` once the app is running, then try it out! diff --git a/axum/oauth2/migrations/20230815100114_schema.down.sql b/axum/oauth2/migrations/20230815100114_schema.down.sql new file mode 100644 index 00000000..16f2ef4c --- /dev/null +++ b/axum/oauth2/migrations/20230815100114_schema.down.sql @@ -0,0 +1,3 @@ +-- Add down migration script here +DROP TABLE users; +DROP TABLE sessions; \ No newline at end of file diff --git a/axum/oauth2/migrations/20230815100114_schema.up.sql b/axum/oauth2/migrations/20230815100114_schema.up.sql new file mode 100644 index 00000000..5e5d8234 --- /dev/null +++ b/axum/oauth2/migrations/20230815100114_schema.up.sql @@ -0,0 +1,15 @@ +-- Add up migration script here +CREATE TABLE IF NOT EXISTS users ( + id SERIAL PRIMARY KEY, + email VARCHAR(255) NOT NULL UNIQUE, + created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + last_updated TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE IF NOT EXISTS sessions ( + id SERIAL PRIMARY KEY, + user_id INT NOT NULL UNIQUE, + session_id VARCHAR NOT NULL, + expires_at TIMESTAMP WITH TIME ZONE NOT NULL, + FOREIGN KEY (user_id) REFERENCES users(id) +); \ No newline at end of file diff --git a/axum/oauth2/src/main.rs b/axum/oauth2/src/main.rs new file mode 100644 index 00000000..e6ff535f --- /dev/null +++ b/axum/oauth2/src/main.rs @@ -0,0 +1,93 @@ +use axum::{extract::FromRef, response::Html, routing::get, Extension, Router}; +use axum_extra::extract::cookie::Key; +use oauth2::{basic::BasicClient, AuthUrl, ClientId, ClientSecret, RedirectUrl, TokenUrl}; +use reqwest::Client; +use routes::oauth; +use shuttle_secrets::SecretStore; +use sqlx::PgPool; +pub mod routes; + +#[derive(Clone)] +pub struct AppState { + db: PgPool, + ctx: Client, + key: Key, +} + +// this impl tells `SignedCookieJar` how to access the key from our state +impl FromRef for Key { + fn from_ref(state: &AppState) -> Self { + state.key.clone() + } +} + +#[shuttle_runtime::main] +async fn axum( + #[shuttle_shared_db::Postgres] db: PgPool, + #[shuttle_secrets::Secrets] secrets: SecretStore, +) -> shuttle_axum::ShuttleAxum { + sqlx::migrate!() + .run(&db) + .await + .expect("Failed migrations :("); + + let oauth_id = secrets.get("GOOGLE_OAUTH_CLIENT_ID").unwrap(); + let oauth_secret = secrets.get("GOOGLE_OAUTH_CLIENT_SECRET").unwrap(); + + let ctx = Client::new(); + + let state = AppState { + db, + ctx, + key: Key::generate(), + }; + + let oauth_client = build_oauth_client(oauth_id.clone(), oauth_secret); + + let router = init_router(state, oauth_client, oauth_id); + + Ok(router.into()) +} + +fn init_router(state: AppState, oauth_client: BasicClient, oauth_id: String) -> Router { + let auth_router = Router::new().route("/auth/google_callback", get(oauth::google_callback)); + + let protected_router = Router::new().route("/", get(oauth::protected)); + + let homepage_router = Router::new() + .route("/", get(homepage)) + .layer(Extension(oauth_id)); + + Router::new() + .nest("/api", auth_router) + .nest("/protected", protected_router) + .nest("/", homepage_router) + .layer(Extension(oauth_client)) + .with_state(state) +} + +fn build_oauth_client(client_id: String, client_secret: String) -> BasicClient { + let redirect_url = "http://localhost:8000/api/auth/google_callback".to_string(); + + let auth_url = AuthUrl::new("https://accounts.google.com/o/oauth2/v2/auth".to_string()) + .expect("Invalid authorization endpoint URL"); + let token_url = TokenUrl::new("https://www.googleapis.com/oauth2/v3/token".to_string()) + .expect("Invalid token endpoint URL"); + + BasicClient::new( + ClientId::new(client_id), + Some(ClientSecret::new(client_secret)), + auth_url, + Some(token_url), + ) + .set_redirect_uri(RedirectUrl::new(redirect_url).unwrap()) +} + +#[axum::debug_handler] +async fn homepage(Extension(oauth_id): Extension) -> Html { + Html(format!("

    Welcome!

    + + + Click here to sign into Google! + ")) +} diff --git a/axum/oauth2/src/routes/errors.rs b/axum/oauth2/src/routes/errors.rs new file mode 100644 index 00000000..0a01fdf7 --- /dev/null +++ b/axum/oauth2/src/routes/errors.rs @@ -0,0 +1,46 @@ +use axum::http::StatusCode; +use axum::response::{IntoResponse, Response}; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum ApiError { + #[error("SQL error: {0}")] + SQL(#[from] sqlx::Error), + #[error("HTTP request error: {0}")] + Request(#[from] reqwest::Error), + #[error("OAuth token error: {0}")] + TokenError( + #[from] + oauth2::RequestTokenError< + oauth2::reqwest::Error, + oauth2::StandardErrorResponse, + >, + ), + #[error("You're not authorized!")] + Unauthorized, + #[error("Attempted to get a non-none value but found none")] + OptionError, + #[error("Attempted to parse a number to an integer but errored out: {0}")] + ParseIntError(#[from] std::num::TryFromIntError), + #[error("Encountered an error trying to convert an infallible value: {0}")] + FromRequestPartsError(#[from] std::convert::Infallible), +} + +impl IntoResponse for ApiError { + fn into_response(self) -> Response { + let response = match self { + Self::SQL(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + Self::Request(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + Self::TokenError(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + Self::Unauthorized => (StatusCode::UNAUTHORIZED, "Unauthorized!".to_string()), + Self::OptionError => ( + StatusCode::INTERNAL_SERVER_ERROR, + "Attempted to get a non-none value but found none".to_string(), + ), + Self::ParseIntError(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + Self::FromRequestPartsError(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), + }; + + response.into_response() + } +} diff --git a/axum/oauth2/src/routes/mod.rs b/axum/oauth2/src/routes/mod.rs new file mode 100644 index 00000000..11e76bc2 --- /dev/null +++ b/axum/oauth2/src/routes/mod.rs @@ -0,0 +1,2 @@ +pub mod errors; +pub mod oauth; diff --git a/axum/oauth2/src/routes/oauth.rs b/axum/oauth2/src/routes/oauth.rs new file mode 100644 index 00000000..957e3b61 --- /dev/null +++ b/axum/oauth2/src/routes/oauth.rs @@ -0,0 +1,114 @@ +use crate::routes::errors::ApiError; + +use crate::AppState; +use axum::{ + extract::{FromRequest, FromRequestParts, Query, Request, State}, + http::StatusCode, + response::{IntoResponse, Redirect}, + Extension, +}; +use axum_extra::extract::cookie::{Cookie, PrivateCookieJar}; +use chrono::{Duration, Local}; +use oauth2::{basic::BasicClient, reqwest::async_http_client, AuthorizationCode, TokenResponse}; +use serde::Deserialize; +use time::Duration as TimeDuration; + +#[derive(Debug, Deserialize)] +pub struct AuthRequest { + code: String, +} + +pub async fn google_callback( + State(state): State, + jar: PrivateCookieJar, + Query(query): Query, + Extension(oauth_client): Extension, +) -> Result { + let token = oauth_client + .exchange_code(AuthorizationCode::new(query.code)) + .request_async(async_http_client) + .await?; + + let profile = state + .ctx + .get("https://openidconnect.googleapis.com/v1/userinfo") + .bearer_auth(token.access_token().secret().to_owned()) + .send() + .await?; + + let profile = profile.json::().await?; + + let Some(secs) = token.expires_in() else { + return Err(ApiError::OptionError); + }; + + let secs: i64 = secs.as_secs().try_into()?; + + let max_age = Local::now().naive_local() + Duration::try_seconds(secs).unwrap(); + + let cookie = Cookie::build(("sid", token.access_token().secret().to_owned())) + .domain(".app.localhost") + .path("/") + .secure(true) + .http_only(true) + .max_age(TimeDuration::seconds(secs)); + + sqlx::query("INSERT INTO users (email) VALUES ($1) ON CONFLICT (email) DO NOTHING") + .bind(profile.email.clone()) + .execute(&state.db) + .await?; + + sqlx::query( + "INSERT INTO sessions (user_id, session_id, expires_at) VALUES ( + (SELECT ID FROM USERS WHERE email = $1 LIMIT 1), + $2, $3) + ON CONFLICT (user_id) DO UPDATE SET + session_id = excluded.session_id, + expires_at = excluded.expires_at", + ) + .bind(profile.email) + .bind(token.access_token().secret().to_owned()) + .bind(max_age) + .execute(&state.db) + .await?; + + Ok((jar.add(cookie), Redirect::to("/protected"))) +} + +#[derive(Deserialize, sqlx::FromRow, Clone)] +pub struct UserProfile { + email: String, +} + +#[axum::async_trait] +impl FromRequest for UserProfile { + type Rejection = ApiError; + async fn from_request(req: Request, state: &AppState) -> Result { + let state = state.to_owned(); + let (mut parts, _body) = req.into_parts(); + let cookiejar: PrivateCookieJar = + PrivateCookieJar::from_request_parts(&mut parts, &state).await?; + + let Some(cookie) = cookiejar.get("sid").map(|cookie| cookie.value().to_owned()) else { + return Err(ApiError::Unauthorized); + }; + + let res = sqlx::query_as::<_, UserProfile>( + "SELECT + users.email + FROM sessions + LEFT JOIN USERS ON sessions.user_id = users.id + WHERE sessions.session_id = $1 + LIMIT 1", + ) + .bind(cookie) + .fetch_one(&state.db) + .await?; + + Ok(Self { email: res.email }) + } +} + +pub async fn protected(profile: UserProfile) -> impl IntoResponse { + (StatusCode::OK, profile.email) +} diff --git a/templates.toml b/templates.toml index c8374a69..1054741a 100644 --- a/templates.toml +++ b/templates.toml @@ -170,6 +170,13 @@ path = "axum/jwt-authentication" use_cases = ["Web app", "Authentication"] tags = ["axum", "jwt"] +[templates.axum-oauth2] +title = "OAuth authentication" +description = "Use Google OAuth to authenticate API endpoints" +path = "axum/oauth2" +use_cases = ["Web app", "Authentication"] +tags = ["axum", "oauth"] + [templates.axum-postgres] title = "Postgres" description = "Todo list with a Postgres database" From 5010bd4c2af2c1f8277fcbf30cdf34ef0bfccc2a Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Fri, 15 Mar 2024 10:09:53 +0100 Subject: [PATCH 149/239] chore: move secrets & metadata to runtime (#153) * chore: move secrets & metadata to runtime * fix serenity * fix: revert config::Source --- actix-web/clerk/backend/Cargo.toml | 1 - actix-web/clerk/backend/src/main.rs | 4 ++-- axum/metadata/Cargo.toml | 1 - axum/metadata/src/main.rs | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 1 - fullstack-templates/saas/backend/src/main.rs | 4 ++-- loco/hello-world/Cargo.toml | 15 ++++++--------- loco/hello-world/src/bin/shuttle.rs | 6 +++--- other/standalone-binary/Cargo.toml | 1 - other/standalone-binary/src/bin/shuttle.rs | 4 ++-- poise/hello-world/Cargo.toml | 1 - poise/hello-world/src/main.rs | 4 ++-- rocket/secrets/Cargo.toml | 1 - rocket/secrets/Secrets.toml.example | 2 +- rocket/secrets/src/main.rs | 12 ++++-------- serenity/hello-world/Cargo.toml | 1 - serenity/hello-world/src/main.rs | 12 ++++-------- serenity/postgres/Cargo.toml | 1 - serenity/postgres/src/main.rs | 4 ++-- 19 files changed, 30 insertions(+), 49 deletions(-) diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml index 689d182c..2566b849 100644 --- a/actix-web/clerk/backend/Cargo.toml +++ b/actix-web/clerk/backend/Cargo.toml @@ -12,4 +12,3 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" shuttle-actix-web = "0.41.0" shuttle-runtime = "0.41.0" -shuttle-secrets = "0.41.0" diff --git a/actix-web/clerk/backend/src/main.rs b/actix-web/clerk/backend/src/main.rs index 627a5a9a..f08d3108 100644 --- a/actix-web/clerk/backend/src/main.rs +++ b/actix-web/clerk/backend/src/main.rs @@ -12,7 +12,7 @@ use clerk_rs::{ }; use serde::{Deserialize, Serialize}; use shuttle_actix_web::ShuttleActixWeb; -use shuttle_secrets::SecretStore; +use shuttle_runtime::SecretStore; struct AppState { client: Clerk, @@ -70,7 +70,7 @@ async fn get_user(state: web::Data, req: HttpRequest) -> impl Responde #[shuttle_runtime::main] async fn main( - #[shuttle_secrets::Secrets] secrets: SecretStore, + #[shuttle_runtime::Secrets] secrets: SecretStore, ) -> ShuttleActixWeb { let app_config = move |cfg: &mut ServiceConfig| { let clerk_secret_key = secrets diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index 7aa01c64..1e1f95c6 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -7,5 +7,4 @@ edition = "2021" axum = "0.7.3" shuttle-axum = "0.41.0" shuttle-runtime = "0.41.0" -shuttle-metadata = "0.41.0" tokio = "1.28.2" diff --git a/axum/metadata/src/main.rs b/axum/metadata/src/main.rs index f619aac4..77561fdd 100644 --- a/axum/metadata/src/main.rs +++ b/axum/metadata/src/main.rs @@ -1,9 +1,9 @@ use axum::{routing::get, Router}; -use shuttle_metadata::Metadata; +use shuttle_runtime::DeploymentMetadata; #[shuttle_runtime::main] async fn axum( - #[shuttle_metadata::ShuttleMetadata] metadata: Metadata, + #[shuttle_runtime::Metadata] metadata: DeploymentMetadata, ) -> shuttle_axum::ShuttleAxum { let router = Router::new().route("/", get(format!("{:?}", metadata))); diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 18f9de85..b7a348b9 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -18,7 +18,6 @@ reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } shuttle-axum = "0.41.0" shuttle-runtime = "0.41.0" -shuttle-secrets = "0.41.0" shuttle-shared-db = { version = "0.41.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.1", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } diff --git a/fullstack-templates/saas/backend/src/main.rs b/fullstack-templates/saas/backend/src/main.rs index 5608c175..6aa46ce2 100644 --- a/fullstack-templates/saas/backend/src/main.rs +++ b/fullstack-templates/saas/backend/src/main.rs @@ -35,7 +35,7 @@ impl FromRef for Key { #[shuttle_runtime::main] async fn axum( #[shuttle_shared_db::Postgres] postgres: PgPool, - #[shuttle_secrets::Secrets] secrets: shuttle_secrets::SecretStore, + #[shuttle_runtime::Secrets] secrets: shuttle_runtime::SecretStore, ) -> shuttle_axum::ShuttleAxum { sqlx::migrate!() .run(&postgres) @@ -64,7 +64,7 @@ async fn axum( Ok(router.into()) } -fn grab_secrets(secrets: shuttle_secrets::SecretStore) -> (String, String, String, String, String) { +fn grab_secrets(secrets: shuttle_runtime::SecretStore) -> (String, String, String, String, String) { let stripe_key = secrets .get("STRIPE_KEY") .unwrap_or_else(|| "None".to_string()); diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index 721d2b85..d5bfefce 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -8,19 +8,16 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -shuttle-axum = "0.38.0" -shuttle-metadata = "0.38.0" -shuttle-runtime = { version = "0.38.0", default-features = false } - +async-trait = "0.1.74" +axum = "0.7.1" +eyre = "*" loco-rs = { version = "0.3.1", default-features = false, features = ["cli"] } +shuttle-axum = "0.41.0" +shuttle-runtime = { version = "0.41.0", default-features = false } serde = "*" serde_json = "*" -eyre = "*" -tokio = { version = "1.33.0", default-features = false } -async-trait = "0.1.74" - -axum = "0.7.1" +tokio = "1.33.0" tracing = "0.1.40" tracing-subscriber = { version = "0.3.17", features = ["env-filter", "json"] } diff --git a/loco/hello-world/src/bin/shuttle.rs b/loco/hello-world/src/bin/shuttle.rs index f611a79a..c68f027e 100644 --- a/loco/hello-world/src/bin/shuttle.rs +++ b/loco/hello-world/src/bin/shuttle.rs @@ -4,11 +4,11 @@ use loco_rs::environment::Environment; #[shuttle_runtime::main] async fn main( - #[shuttle_metadata::ShuttleMetadata] meta: shuttle_metadata::Metadata, + #[shuttle_runtime::Metadata] meta: shuttle_runtime::DeploymentMetadata, ) -> shuttle_axum::ShuttleAxum { let environment = match meta.env { - shuttle_metadata::Environment::Local => Environment::Development, - shuttle_metadata::Environment::Deployment => Environment::Production, + shuttle_runtime::Environment::Local => Environment::Development, + shuttle_runtime::Environment::Deployment => Environment::Production, }; let boot_result = create_app::(StartMode::ServerOnly, &environment) .await diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 94665841..08ad5488 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -17,5 +17,4 @@ axum = "0.7.3" dotenvy = "0.15.7" shuttle-axum = "0.41.0" shuttle-runtime = "0.41.0" -shuttle-secrets = "0.41.0" tokio = "1.28.2" diff --git a/other/standalone-binary/src/bin/shuttle.rs b/other/standalone-binary/src/bin/shuttle.rs index 84fd00e8..99133ef6 100644 --- a/other/standalone-binary/src/bin/shuttle.rs +++ b/other/standalone-binary/src/bin/shuttle.rs @@ -1,10 +1,10 @@ use shuttle_axum::ShuttleAxum; -use shuttle_secrets::SecretStore; +use shuttle_runtime::SecretStore; use multi_binary::build_router; #[shuttle_runtime::main] -async fn axum(#[shuttle_secrets::Secrets] secret_store: SecretStore) -> ShuttleAxum { +async fn axum(#[shuttle_runtime::Secrets] secret_store: SecretStore) -> ShuttleAxum { // Get all resources 'the Shuttle way' let my_secret = secret_store.get("SOME_API_KEY").unwrap(); diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 03024cb5..a78d445e 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -8,7 +8,6 @@ publish = false anyhow = "1.0.68" poise = "0.6.1" shuttle-runtime = "0.41.0" -shuttle-secrets = "0.41.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity shuttle-serenity = "0.41.0" tracing = "0.1.37" diff --git a/poise/hello-world/src/main.rs b/poise/hello-world/src/main.rs index 64abe991..29b9bf99 100644 --- a/poise/hello-world/src/main.rs +++ b/poise/hello-world/src/main.rs @@ -1,6 +1,6 @@ use anyhow::Context as _; use poise::serenity_prelude::{ClientBuilder, GatewayIntents}; -use shuttle_secrets::SecretStore; +use shuttle_runtime::SecretStore; use shuttle_serenity::ShuttleSerenity; struct Data {} // User data, which is stored and accessible in all command invocations @@ -15,7 +15,7 @@ async fn hello(ctx: Context<'_>) -> Result<(), Error> { } #[shuttle_runtime::main] -async fn main(#[shuttle_secrets::Secrets] secret_store: SecretStore) -> ShuttleSerenity { +async fn main(#[shuttle_runtime::Secrets] secret_store: SecretStore) -> ShuttleSerenity { // Get the discord token set in `Secrets.toml` let discord_token = secret_store .get("DISCORD_TOKEN") diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 86126335..f138c9d7 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -8,5 +8,4 @@ anyhow = "1.0.66" rocket = "0.5.0" shuttle-rocket = "0.41.0" shuttle-runtime = "0.41.0" -shuttle-secrets = "0.41.0" tokio = "1.26.0" diff --git a/rocket/secrets/Secrets.toml.example b/rocket/secrets/Secrets.toml.example index 455ab4c8..ceedf199 100644 --- a/rocket/secrets/Secrets.toml.example +++ b/rocket/secrets/Secrets.toml.example @@ -1 +1 @@ -MY_API_KEY = 'the contents of my API key' \ No newline at end of file +MY_API_KEY = 'the contents of my API key' diff --git a/rocket/secrets/src/main.rs b/rocket/secrets/src/main.rs index 879d38ce..c6e6b18e 100644 --- a/rocket/secrets/src/main.rs +++ b/rocket/secrets/src/main.rs @@ -1,10 +1,10 @@ #[macro_use] extern crate rocket; -use anyhow::anyhow; +use anyhow::Context; use rocket::response::status::BadRequest; use rocket::State; -use shuttle_secrets::SecretStore; +use shuttle_runtime::SecretStore; #[get("/secret")] async fn secret(state: &State) -> Result> { @@ -17,14 +17,10 @@ struct MyState { #[shuttle_runtime::main] async fn rocket( - #[shuttle_secrets::Secrets] secret_store: SecretStore, + #[shuttle_runtime::Secrets] secrets: SecretStore, ) -> shuttle_rocket::ShuttleRocket { // get secret defined in `Secrets.toml` file. - let secret = if let Some(secret) = secret_store.get("MY_API_KEY") { - secret - } else { - return Err(anyhow!("secret was not found").into()); - }; + let secret = secrets.get("MY_API_KEY").context("secret was not found")?; let state = MyState { secret }; let rocket = rocket::build().mount("/", routes![secret]).manage(state); diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 7a12eba0..017ebac0 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } shuttle-runtime = "0.41.0" -shuttle-secrets = "0.41.0" shuttle-serenity = "0.41.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/hello-world/src/main.rs b/serenity/hello-world/src/main.rs index 2b01b6a8..cb59ff47 100644 --- a/serenity/hello-world/src/main.rs +++ b/serenity/hello-world/src/main.rs @@ -1,9 +1,9 @@ -use anyhow::anyhow; +use anyhow::Context as _; use serenity::async_trait; use serenity::model::channel::Message; use serenity::model::gateway::Ready; use serenity::prelude::*; -use shuttle_secrets::SecretStore; +use shuttle_runtime::SecretStore; use tracing::{error, info}; struct Bot; @@ -25,14 +25,10 @@ impl EventHandler for Bot { #[shuttle_runtime::main] async fn serenity( - #[shuttle_secrets::Secrets] secret_store: SecretStore, + #[shuttle_runtime::Secrets] secrets: SecretStore, ) -> shuttle_serenity::ShuttleSerenity { // Get the discord token set in `Secrets.toml` - let token = if let Some(token) = secret_store.get("DISCORD_TOKEN") { - token - } else { - return Err(anyhow!("'DISCORD_TOKEN' was not found").into()); - }; + let token = secrets.get("DISCORD_TOKEN").context("'DISCORD_TOKEN' was not found")?; // Set gateway intents, which decides what events the bot will be notified about let intents = GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT; diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index ab5f31df..0581ba46 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -8,7 +8,6 @@ anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } shuttle-runtime = "0.41.0" -shuttle-secrets = "0.41.0" shuttle-serenity = "0.41.0" shuttle-shared-db = { version = "0.41.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" diff --git a/serenity/postgres/src/main.rs b/serenity/postgres/src/main.rs index d908ebff..c001b979 100644 --- a/serenity/postgres/src/main.rs +++ b/serenity/postgres/src/main.rs @@ -7,7 +7,7 @@ use serenity::model::application::{CommandDataOptionValue, CommandOptionType, In use serenity::model::gateway::Ready; use serenity::model::id::GuildId; use serenity::prelude::*; -use shuttle_secrets::SecretStore; +use shuttle_runtime::SecretStore; use sqlx::{Executor, PgPool}; use tracing::{error, info}; @@ -127,7 +127,7 @@ impl EventHandler for Bot { #[shuttle_runtime::main] async fn serenity( #[shuttle_shared_db::Postgres] pool: PgPool, - #[shuttle_secrets::Secrets] secret_store: SecretStore, + #[shuttle_runtime::Secrets] secret_store: SecretStore, ) -> shuttle_serenity::ShuttleSerenity { // Get the discord token set in `Secrets.toml` let token = secret_store From e9e2ab5073bd1601a6e6d82d7584bb92b55da36e Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Fri, 15 Mar 2024 14:07:12 +0100 Subject: [PATCH 150/239] chore: v0.42.0 --- actix-web/clerk/backend/Cargo.toml | 4 ++-- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/htmx-crud/Cargo.toml | 6 +++--- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 4 ++-- axum/oauth2/Cargo.toml | 8 ++++---- axum/postgres/Cargo.toml | 6 +++--- axum/qdrant/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- bevy/hello-world/server/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 6 +++--- loco/hello-world/Cargo.toml | 4 ++-- other/standalone-binary/Cargo.toml | 4 ++-- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/opendal-memory/Cargo.toml | 6 +++--- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 4 ++-- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- salvo/image-rescaler/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 6 +++--- serenity/weather-forecast/Cargo.toml | 6 +++--- thruster/hello-world/Cargo.toml | 4 ++-- tide/hello-world/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 46 files changed, 107 insertions(+), 107 deletions(-) diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml index 2566b849..c320f374 100644 --- a/actix-web/clerk/backend/Cargo.toml +++ b/actix-web/clerk/backend/Cargo.toml @@ -10,5 +10,5 @@ clerk-rs = "0.2.3" openssl-sys = { version = "0.9.9", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-actix-web = "0.42.0" +shuttle-runtime = "0.42.0" diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index b807562b..6809f21f 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.6.0" actix-session = { version = "0.8.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-actix-web = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 941203d1..e589cee2 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-actix-web = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index dca8b58c..9af6ff81 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-actix-web = "0.42.0" +shuttle-runtime = "0.42.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.41.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.42.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index a2063e9f..2df4b0e1 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-actix-web = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index a3b96552..5210ec62 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-actix-web = "0.42.0" +shuttle-runtime = "0.42.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 066715ac..fe6162fe 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-axum = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.28.2" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index 6b7acb76..3ebef6f9 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -9,9 +9,9 @@ askama_axum = "0.4.0" axum = "0.7.4" serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.41.0" -shuttle-runtime = "0.41.0" -shuttle-shared-db = { version = "0.41.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.42.0" +shuttle-runtime = "0.42.0" +shuttle-shared-db = { version = "0.42.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.2", features = ["runtime-tokio-rustls", "postgres"] } tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index 6d55a4c9..e16af6ba 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-axum = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index 1e1f95c6..af29f494 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-axum = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.28.2" diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index 881193fb..b8b87b8b 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -11,10 +11,10 @@ chrono = { version = "0.4.35", features = ["clock"] } oauth2 = "4.4.1" reqwest = { version = "0.11.18", features = ["json"] } serde = { version = "1.0.183", features = ["derive"] } -shuttle-axum = "0.41.0" -shuttle-runtime = "0.41.0" -shuttle-secrets = "0.41.0" -shuttle-shared-db = { version = "0.41.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.42.0" +shuttle-runtime = "0.42.0" +shuttle-secrets = "0.42.0" +shuttle-shared-db = { version = "0.42.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.2", features = ["runtime-tokio-rustls", "macros", "chrono"] } thiserror = "1.0.57" time = "0.3.25" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 163b99ee..f7964f84 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.41.0" -shuttle-runtime = "0.41.0" -shuttle-shared-db = { version = "0.41.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.42.0" +shuttle-runtime = "0.42.0" +shuttle-shared-db = { version = "0.42.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index 71d57877..81b7a21b 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.7.0" -shuttle-axum = "0.41.0" -shuttle-qdrant = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-axum = "0.42.0" +shuttle-qdrant = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 34e95b95..84348263 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-axum = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 52c9e6c5..3af45ddf 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.41.0" -shuttle-runtime = "0.41.0" -shuttle-turso = "0.41.0" +shuttle-axum = "0.42.0" +shuttle-runtime = "0.42.0" +shuttle-turso = "0.42.0" libsql = "0.2.0" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index c7660ff1..c6aa95ea 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-axum = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/bevy/hello-world/server/Cargo.toml b/bevy/hello-world/server/Cargo.toml index d5492685..611d34de 100644 --- a/bevy/hello-world/server/Cargo.toml +++ b/bevy/hello-world/server/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-axum = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 8b45cc07..2b278d5e 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1", features = ["derive"] } -shuttle-service = "0.41.0" -shuttle-axum = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-service = "0.42.0" +shuttle-axum = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 64c4bf52..3f31f53d 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.41.0" +shuttle-runtime = "0.42.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index 47d23cff..3556df2c 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -10,7 +10,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-persist = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index b7a348b9..fc762ee9 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,9 +16,9 @@ lettre = "0.11.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.41.0" -shuttle-runtime = "0.41.0" -shuttle-shared-db = { version = "0.41.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.42.0" +shuttle-runtime = "0.42.0" +shuttle-shared-db = { version = "0.42.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.1", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index d5bfefce..d4dd63d3 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -13,8 +13,8 @@ async-trait = "0.1.74" axum = "0.7.1" eyre = "*" loco-rs = { version = "0.3.1", default-features = false, features = ["cli"] } -shuttle-axum = "0.41.0" -shuttle-runtime = { version = "0.41.0", default-features = false } +shuttle-axum = "0.42.0" +shuttle-runtime = { version = "0.42.0", default-features = false } serde = "*" serde_json = "*" tokio = "1.33.0" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 08ad5488..051cca17 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,6 +15,6 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-axum = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 6cef211d..a7a1d763 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "2.0.0" -shuttle-poem = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-poem = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index f295a87b..3e4a7dcb 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "2.0.0" -shuttle-poem = "0.41.0" -shuttle-shared-db = { version = "0.41.0", features = ["mongodb"] } -shuttle-runtime = "0.41.0" +shuttle-poem = "0.42.0" +shuttle-shared-db = { version = "0.42.0", features = ["mongodb"] } +shuttle-runtime = "0.42.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index a78d445e..be43b3e2 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.6.1" -shuttle-runtime = "0.41.0" +shuttle-runtime = "0.42.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity -shuttle-serenity = "0.41.0" +shuttle-serenity = "0.42.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 48e543d1..3f94922c 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" rocket_dyn_templates = { version = "0.1.0", features = ["handlebars"] } -shuttle-rocket = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-rocket = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index ccdc2b35..1d299ecc 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-rocket = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 036ae586..ce77e6eb 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-rocket = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.26.0" diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index 84e1570d..caeb1ea3 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -4,10 +4,10 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.41.0" -shuttle-opendal = "0.41.0" +shuttle-runtime = "0.42.0" +shuttle-opendal = "0.42.0" tokio = "1.26.0" -shuttle-rocket = "0.41.0" +shuttle-rocket = "0.42.0" opendal = "0.45.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index f3d7a475..e273e11e 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.41.0" -shuttle-rocket = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-persist = "0.42.0" +shuttle-rocket = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index b9bbc4ef..a59f2c3e 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.41.0" -shuttle-runtime = "0.41.0" -shuttle-shared-db = { version = "0.41.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.42.0" +shuttle-runtime = "0.42.0" +shuttle-shared-db = { version = "0.42.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index f138c9d7..59db6e71 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-rocket = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index be72fd8c..dbd0513f 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-rocket = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 6d512ee8..da86e079 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" nanoid = "0.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.41.0" -shuttle-runtime = "0.41.0" -shuttle-shared-db = { version = "0.41.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.42.0" +shuttle-runtime = "0.42.0" +shuttle-shared-db = { version = "0.42.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 30a1a3fb..8dab8125 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-rocket = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 35ab9fc8..d5a0d5bf 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] salvo = "0.63.0" -shuttle-salvo = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-salvo = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml index 95f76f4d..ef25af6f 100644 --- a/salvo/image-rescaler/Cargo.toml +++ b/salvo/image-rescaler/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] image = "0.24.8" salvo = "0.63.0" -shuttle-salvo = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-salvo = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 017ebac0..8b1ac499 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.41.0" -shuttle-serenity = "0.41.0" +shuttle-runtime = "0.42.0" +shuttle-serenity = "0.42.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 0581ba46..fe604869 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.41.0" -shuttle-serenity = "0.41.0" -shuttle-shared-db = { version = "0.41.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.42.0" +shuttle-serenity = "0.42.0" +shuttle-shared-db = { version = "0.42.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/weather-forecast/Cargo.toml b/serenity/weather-forecast/Cargo.toml index 8cb47309..a1909e96 100644 --- a/serenity/weather-forecast/Cargo.toml +++ b/serenity/weather-forecast/Cargo.toml @@ -8,8 +8,8 @@ anyhow = "1.0.66" reqwest = { version = "0.11.24", features = ["json"] } serde = "1.0.197" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.41.0" -shuttle-secrets = "0.41.0" -shuttle-serenity = "0.41.0" +shuttle-runtime = "0.42.0" +shuttle-secrets = "0.42.0" +shuttle-serenity = "0.42.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index a7a8ebcc..fb37f316 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-thruster = "0.42.0" +shuttle-runtime = "0.42.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 332e2c8a..a3f62dcc 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.41.0" -shuttle-runtime = "0.41.0" +shuttle-tide = "0.42.0" +shuttle-runtime = "0.42.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index b74c77cc..7df1ff54 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.41.0" -shuttle-tower = "0.41.0" +shuttle-runtime = "0.42.0" +shuttle-tower = "0.42.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 9ce74715..36bbdba3 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.41.0" +shuttle-actix-web = "0.42.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.41.0", default-features = false } +shuttle-runtime = { version = "0.42.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index ddb9eccb..28241a56 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.41.0" -shuttle-warp = "0.41.0" +shuttle-runtime = "0.42.0" +shuttle-warp = "0.42.0" tokio = "1.26.0" warp = "0.3.3" From ede5a233273d870c35daa87090274cb8cf137f96 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Sat, 16 Mar 2024 17:39:30 +0100 Subject: [PATCH 151/239] ci: no matrix fail fast (#158) * ci: don't fail fast in matrix * xdd --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d613fe21..84bbb72b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,6 +29,7 @@ jobs: strategy: matrix: from-to: ["a q", "q zzz"] + fail-fast: false runs-on: ubuntu-latest From c0cae7b54eeb5cad09f05a65c3adb151f0ddb611 Mon Sep 17 00:00:00 2001 From: Sourab Pramanik Date: Mon, 18 Mar 2024 17:29:15 +0530 Subject: [PATCH 152/239] ci: use patches for shuttle/main on develop branch (#154) * feat: new dev workflow * fix: rm dev workflow * feat: add ci steps fro develop branch * test: test workflow for current branch * test: test workflow for current branch * fix: change script file location * fix: add run commands * feat: change branch and step name * fix: update patch execution command Co-authored-by: jonaro00 <54029719+jonaro00@users.noreply.github.com> * fix: optimize cloning Co-authored-by: jonaro00 <54029719+jonaro00@users.noreply.github.com> * fix: check base ref name * debug variables * fix: base ref name * nit: print commit hash of shuttle checkout --------- Co-authored-by: jonaro00 <54029719+jonaro00@users.noreply.github.com> --- .github/workflows/ci.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 84bbb72b..9e8b0bf0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,6 +36,17 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Clone the Shuttle main repository + if: ${{ github.ref == 'refs/heads/develop' || github.base_ref == 'develop' }} + run: | + git clone --depth 1 --branch main https://github.com/shuttle-hq/shuttle.git + cd shuttle + git log -1 --format='%H' + + - name: Apply patches + if: ${{ github.ref == 'refs/heads/develop' || github.base_ref == 'develop' }} + run: ./shuttle/scripts/apply-patches.sh .cargo/config.toml "$(pwd)/shuttle" + - name: Install sccache run: | SCCACHE_VERSION='v0.7.7' From e0d4934bc77f651d715c229efb43246ad75c3694 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Mon, 18 Mar 2024 13:04:10 +0100 Subject: [PATCH 153/239] fix: more removals of shuttle-secrets --- axum/oauth2/Cargo.toml | 1 - axum/oauth2/src/main.rs | 4 ++-- other/standalone-binary/README.md | 2 +- rocket/secrets/src/main.rs | 4 +--- serenity/hello-world/src/main.rs | 4 +++- serenity/weather-forecast/Cargo.toml | 1 - serenity/weather-forecast/src/main.rs | 4 ++-- templates.toml | 4 ++-- 8 files changed, 11 insertions(+), 13 deletions(-) diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index b8b87b8b..ead40d00 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -13,7 +13,6 @@ reqwest = { version = "0.11.18", features = ["json"] } serde = { version = "1.0.183", features = ["derive"] } shuttle-axum = "0.42.0" shuttle-runtime = "0.42.0" -shuttle-secrets = "0.42.0" shuttle-shared-db = { version = "0.42.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.2", features = ["runtime-tokio-rustls", "macros", "chrono"] } thiserror = "1.0.57" diff --git a/axum/oauth2/src/main.rs b/axum/oauth2/src/main.rs index e6ff535f..c6dbd175 100644 --- a/axum/oauth2/src/main.rs +++ b/axum/oauth2/src/main.rs @@ -3,7 +3,7 @@ use axum_extra::extract::cookie::Key; use oauth2::{basic::BasicClient, AuthUrl, ClientId, ClientSecret, RedirectUrl, TokenUrl}; use reqwest::Client; use routes::oauth; -use shuttle_secrets::SecretStore; +use shuttle_runtime::SecretStore; use sqlx::PgPool; pub mod routes; @@ -24,7 +24,7 @@ impl FromRef for Key { #[shuttle_runtime::main] async fn axum( #[shuttle_shared_db::Postgres] db: PgPool, - #[shuttle_secrets::Secrets] secrets: SecretStore, + #[shuttle_runtime::Secrets] secrets: SecretStore, ) -> shuttle_axum::ShuttleAxum { sqlx::migrate!() .run(&db) diff --git a/other/standalone-binary/README.md b/other/standalone-binary/README.md index e8829b65..0cf3484e 100644 --- a/other/standalone-binary/README.md +++ b/other/standalone-binary/README.md @@ -7,4 +7,4 @@ All startup logic is placed in the binary source files, while the implementation - `src/bin/shuttle.rs` is the main binary with Shuttle, run with `cargo shuttle run`. Note that the `[[bin]]` entry in `Cargo.toml` needs to have the same name as the crate. The file can have any name you want. - `src/bin/standalone.rs` is without Shuttle, run with `cargo run --bin standalone` (you can change the name) -This example shows how to use separate logic for getting secrets (`shuttle-secrets` vs homemade solution), but the same approach can be applied to other resources that are initiated by Shuttle's main function. +This example shows how to use separate logic for getting secrets (Shuttle secrets vs homemade solution), but the same approach can be applied to other resources that are initiated by Shuttle's main function. diff --git a/rocket/secrets/src/main.rs b/rocket/secrets/src/main.rs index c6e6b18e..42159863 100644 --- a/rocket/secrets/src/main.rs +++ b/rocket/secrets/src/main.rs @@ -16,9 +16,7 @@ struct MyState { } #[shuttle_runtime::main] -async fn rocket( - #[shuttle_runtime::Secrets] secrets: SecretStore, -) -> shuttle_rocket::ShuttleRocket { +async fn rocket(#[shuttle_runtime::Secrets] secrets: SecretStore) -> shuttle_rocket::ShuttleRocket { // get secret defined in `Secrets.toml` file. let secret = secrets.get("MY_API_KEY").context("secret was not found")?; diff --git a/serenity/hello-world/src/main.rs b/serenity/hello-world/src/main.rs index cb59ff47..658170fa 100644 --- a/serenity/hello-world/src/main.rs +++ b/serenity/hello-world/src/main.rs @@ -28,7 +28,9 @@ async fn serenity( #[shuttle_runtime::Secrets] secrets: SecretStore, ) -> shuttle_serenity::ShuttleSerenity { // Get the discord token set in `Secrets.toml` - let token = secrets.get("DISCORD_TOKEN").context("'DISCORD_TOKEN' was not found")?; + let token = secrets + .get("DISCORD_TOKEN") + .context("'DISCORD_TOKEN' was not found")?; // Set gateway intents, which decides what events the bot will be notified about let intents = GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT; diff --git a/serenity/weather-forecast/Cargo.toml b/serenity/weather-forecast/Cargo.toml index a1909e96..344dcb00 100644 --- a/serenity/weather-forecast/Cargo.toml +++ b/serenity/weather-forecast/Cargo.toml @@ -9,7 +9,6 @@ reqwest = { version = "0.11.24", features = ["json"] } serde = "1.0.197" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } shuttle-runtime = "0.42.0" -shuttle-secrets = "0.42.0" shuttle-serenity = "0.42.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/weather-forecast/src/main.rs b/serenity/weather-forecast/src/main.rs index 36a483eb..ff3b534c 100644 --- a/serenity/weather-forecast/src/main.rs +++ b/serenity/weather-forecast/src/main.rs @@ -8,7 +8,7 @@ use serenity::builder::{ }; use serenity::model::gateway::Ready; use serenity::prelude::*; -use shuttle_secrets::SecretStore; +use shuttle_runtime::SecretStore; use tracing::info; struct Bot { @@ -87,7 +87,7 @@ impl EventHandler for Bot { #[shuttle_runtime::main] async fn serenity( - #[shuttle_secrets::Secrets] secret_store: SecretStore, + #[shuttle_runtime::Secrets] secret_store: SecretStore, ) -> shuttle_serenity::ShuttleSerenity { // Get the discord token set in `Secrets.toml` let discord_token = secret_store diff --git a/templates.toml b/templates.toml index 1054741a..18fe1535 100644 --- a/templates.toml +++ b/templates.toml @@ -315,7 +315,7 @@ tags = ["actix-web", "tracing"] [examples.metadata] title = "Shuttle Metadata" -description = "Basic usage of shuttle-metadata" +description = "Basic usage of Shuttle Metadata" path = "axum/metadata" use_cases = [] tags = ["axum"] @@ -329,7 +329,7 @@ tags = ["rocket"] [examples.secrets] title = "Shuttle Secrets" -description = "Basic usage of shuttle-secrets" +description = "Basic usage of Shuttle Secrets" path = "rocket/secrets" use_cases = ["Web app"] tags = ["rocket"] From f8c944af47701ed0fbbfd0f269855cd20390d31a Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Mon, 18 Mar 2024 13:29:14 +0100 Subject: [PATCH 154/239] ci: change shuttle checkout dir --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9e8b0bf0..717cb158 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,13 +39,13 @@ jobs: - name: Clone the Shuttle main repository if: ${{ github.ref == 'refs/heads/develop' || github.base_ref == 'develop' }} run: | - git clone --depth 1 --branch main https://github.com/shuttle-hq/shuttle.git - cd shuttle + git clone --depth 1 --branch main https://github.com/shuttle-hq/shuttle.git /home/runner/shuttle + cd /home/runner/shuttle git log -1 --format='%H' - name: Apply patches if: ${{ github.ref == 'refs/heads/develop' || github.base_ref == 'develop' }} - run: ./shuttle/scripts/apply-patches.sh .cargo/config.toml "$(pwd)/shuttle" + run: /home/runner/shuttle/scripts/apply-patches.sh .cargo/config.toml /home/runner/shuttle - name: Install sccache run: | From 42dcc1adab57f75f87a4d6df63e2abedbe5b53e2 Mon Sep 17 00:00:00 2001 From: Jaco Minnaar <40057059+Jaco-Minnaar@users.noreply.github.com> Date: Mon, 25 Mar 2024 12:24:49 +0200 Subject: [PATCH 155/239] chore: update libsql dep in axum/turso example (#159) * chore: update libsql dep in axum/turso example * fix: await row future in turso example --- axum/turso/Cargo.toml | 2 +- axum/turso/src/main.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 3af45ddf..95d664fc 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -8,7 +8,7 @@ axum = "0.7.3" shuttle-axum = "0.42.0" shuttle-runtime = "0.42.0" shuttle-turso = "0.42.0" -libsql = "0.2.0" +libsql = "0.3.1" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } serde_json = "1.0.99" diff --git a/axum/turso/src/main.rs b/axum/turso/src/main.rs index e4f67e26..02593e4a 100644 --- a/axum/turso/src/main.rs +++ b/axum/turso/src/main.rs @@ -10,7 +10,7 @@ async fn get_posts(State(client): State>) -> Json> { .await .unwrap(); let mut users = vec![]; - while let Some(row) = rows.next().unwrap() { + while let Some(row) = rows.next().await.unwrap() { users.push(User { uid: row.get::(0).unwrap(), email: row.get::(1).unwrap(), From 7629447b49124811f15fd04df90e7862fc4517af Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Thu, 28 Mar 2024 15:35:29 +0100 Subject: [PATCH 156/239] chore: v0.43.0 --- actix-web/clerk/backend/Cargo.toml | 4 ++-- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/htmx-crud/Cargo.toml | 6 +++--- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 4 ++-- axum/oauth2/Cargo.toml | 6 +++--- axum/postgres/Cargo.toml | 6 +++--- axum/qdrant/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- bevy/hello-world/server/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 6 +++--- loco/hello-world/Cargo.toml | 4 ++-- other/standalone-binary/Cargo.toml | 4 ++-- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/opendal-memory/Cargo.toml | 6 +++--- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 4 ++-- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- salvo/image-rescaler/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 6 +++--- serenity/weather-forecast/Cargo.toml | 4 ++-- thruster/hello-world/Cargo.toml | 4 ++-- tide/hello-world/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 46 files changed, 105 insertions(+), 105 deletions(-) diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml index c320f374..83e5e740 100644 --- a/actix-web/clerk/backend/Cargo.toml +++ b/actix-web/clerk/backend/Cargo.toml @@ -10,5 +10,5 @@ clerk-rs = "0.2.3" openssl-sys = { version = "0.9.9", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-actix-web = "0.43.0" +shuttle-runtime = "0.43.0" diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index 6809f21f..426cd851 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.6.0" actix-session = { version = "0.8.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-actix-web = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index e589cee2..772c989e 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-actix-web = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 9af6ff81..35a8cd3e 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-actix-web = "0.43.0" +shuttle-runtime = "0.43.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.42.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.43.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index 2df4b0e1..587491eb 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-actix-web = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 5210ec62..226e1e95 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-actix-web = "0.43.0" +shuttle-runtime = "0.43.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index fe6162fe..1cb6d2fa 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-axum = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.28.2" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index 3ebef6f9..92892c77 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -9,9 +9,9 @@ askama_axum = "0.4.0" axum = "0.7.4" serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.42.0" -shuttle-runtime = "0.42.0" -shuttle-shared-db = { version = "0.42.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.43.0" +shuttle-runtime = "0.43.0" +shuttle-shared-db = { version = "0.43.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.2", features = ["runtime-tokio-rustls", "postgres"] } tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index e16af6ba..1d78f1ba 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-axum = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index af29f494..3f944781 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-axum = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.28.2" diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index ead40d00..9c1b2b79 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -11,9 +11,9 @@ chrono = { version = "0.4.35", features = ["clock"] } oauth2 = "4.4.1" reqwest = { version = "0.11.18", features = ["json"] } serde = { version = "1.0.183", features = ["derive"] } -shuttle-axum = "0.42.0" -shuttle-runtime = "0.42.0" -shuttle-shared-db = { version = "0.42.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.43.0" +shuttle-runtime = "0.43.0" +shuttle-shared-db = { version = "0.43.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.2", features = ["runtime-tokio-rustls", "macros", "chrono"] } thiserror = "1.0.57" time = "0.3.25" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index f7964f84..91580eca 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.42.0" -shuttle-runtime = "0.42.0" -shuttle-shared-db = { version = "0.42.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.43.0" +shuttle-runtime = "0.43.0" +shuttle-shared-db = { version = "0.43.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index 81b7a21b..9bb167b2 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.7.0" -shuttle-axum = "0.42.0" -shuttle-qdrant = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-axum = "0.43.0" +shuttle-qdrant = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 84348263..826e6d61 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-axum = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 95d664fc..895b134b 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.42.0" -shuttle-runtime = "0.42.0" -shuttle-turso = "0.42.0" +shuttle-axum = "0.43.0" +shuttle-runtime = "0.43.0" +shuttle-turso = "0.43.0" libsql = "0.3.1" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index c6aa95ea..7fa49747 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-axum = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/bevy/hello-world/server/Cargo.toml b/bevy/hello-world/server/Cargo.toml index 611d34de..e54b73ba 100644 --- a/bevy/hello-world/server/Cargo.toml +++ b/bevy/hello-world/server/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-axum = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 2b278d5e..7d2f78dc 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1", features = ["derive"] } -shuttle-service = "0.42.0" -shuttle-axum = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-service = "0.43.0" +shuttle-axum = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 3f31f53d..c276c677 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.42.0" +shuttle-runtime = "0.43.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index 3556df2c..841ba488 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -10,7 +10,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-persist = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index fc762ee9..4a8f8f2d 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,9 +16,9 @@ lettre = "0.11.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.42.0" -shuttle-runtime = "0.42.0" -shuttle-shared-db = { version = "0.42.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.43.0" +shuttle-runtime = "0.43.0" +shuttle-shared-db = { version = "0.43.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.1", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index d4dd63d3..d32f418e 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -13,8 +13,8 @@ async-trait = "0.1.74" axum = "0.7.1" eyre = "*" loco-rs = { version = "0.3.1", default-features = false, features = ["cli"] } -shuttle-axum = "0.42.0" -shuttle-runtime = { version = "0.42.0", default-features = false } +shuttle-axum = "0.43.0" +shuttle-runtime = { version = "0.43.0", default-features = false } serde = "*" serde_json = "*" tokio = "1.33.0" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 051cca17..4dfe2ae0 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,6 +15,6 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-axum = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index a7a1d763..c65e0f14 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "2.0.0" -shuttle-poem = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-poem = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 3e4a7dcb..3362c9b9 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "2.0.0" -shuttle-poem = "0.42.0" -shuttle-shared-db = { version = "0.42.0", features = ["mongodb"] } -shuttle-runtime = "0.42.0" +shuttle-poem = "0.43.0" +shuttle-shared-db = { version = "0.43.0", features = ["mongodb"] } +shuttle-runtime = "0.43.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index be43b3e2..9884ae36 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.6.1" -shuttle-runtime = "0.42.0" +shuttle-runtime = "0.43.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity -shuttle-serenity = "0.42.0" +shuttle-serenity = "0.43.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 3f94922c..040b24b3 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" rocket_dyn_templates = { version = "0.1.0", features = ["handlebars"] } -shuttle-rocket = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-rocket = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 1d299ecc..353a79f6 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-rocket = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index ce77e6eb..acff10bc 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-rocket = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.26.0" diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index caeb1ea3..b391e0bf 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -4,10 +4,10 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.42.0" -shuttle-opendal = "0.42.0" +shuttle-runtime = "0.43.0" +shuttle-opendal = "0.43.0" tokio = "1.26.0" -shuttle-rocket = "0.42.0" +shuttle-rocket = "0.43.0" opendal = "0.45.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index e273e11e..6a58fb02 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.42.0" -shuttle-rocket = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-persist = "0.43.0" +shuttle-rocket = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index a59f2c3e..38e3a1e4 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.42.0" -shuttle-runtime = "0.42.0" -shuttle-shared-db = { version = "0.42.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.43.0" +shuttle-runtime = "0.43.0" +shuttle-shared-db = { version = "0.43.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 59db6e71..e6acc788 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-rocket = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index dbd0513f..ac828254 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-rocket = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index da86e079..cde5892b 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" nanoid = "0.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.42.0" -shuttle-runtime = "0.42.0" -shuttle-shared-db = { version = "0.42.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.43.0" +shuttle-runtime = "0.43.0" +shuttle-shared-db = { version = "0.43.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 8dab8125..718d655c 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-rocket = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index d5a0d5bf..fbefc5fb 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] salvo = "0.63.0" -shuttle-salvo = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-salvo = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml index ef25af6f..40fc4af4 100644 --- a/salvo/image-rescaler/Cargo.toml +++ b/salvo/image-rescaler/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] image = "0.24.8" salvo = "0.63.0" -shuttle-salvo = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-salvo = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 8b1ac499..6949ef9e 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.42.0" -shuttle-serenity = "0.42.0" +shuttle-runtime = "0.43.0" +shuttle-serenity = "0.43.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index fe604869..debfdcea 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.42.0" -shuttle-serenity = "0.42.0" -shuttle-shared-db = { version = "0.42.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.43.0" +shuttle-serenity = "0.43.0" +shuttle-shared-db = { version = "0.43.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/weather-forecast/Cargo.toml b/serenity/weather-forecast/Cargo.toml index 344dcb00..ccbce7db 100644 --- a/serenity/weather-forecast/Cargo.toml +++ b/serenity/weather-forecast/Cargo.toml @@ -8,7 +8,7 @@ anyhow = "1.0.66" reqwest = { version = "0.11.24", features = ["json"] } serde = "1.0.197" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.42.0" -shuttle-serenity = "0.42.0" +shuttle-runtime = "0.43.0" +shuttle-serenity = "0.43.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index fb37f316..43c30eef 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-thruster = "0.43.0" +shuttle-runtime = "0.43.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index a3f62dcc..767d0098 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.42.0" -shuttle-runtime = "0.42.0" +shuttle-tide = "0.43.0" +shuttle-runtime = "0.43.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 7df1ff54..65442cd5 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.42.0" -shuttle-tower = "0.42.0" +shuttle-runtime = "0.43.0" +shuttle-tower = "0.43.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 36bbdba3..e8e9ef7b 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.42.0" +shuttle-actix-web = "0.43.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.42.0", default-features = false } +shuttle-runtime = { version = "0.43.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 28241a56..a760020c 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.42.0" -shuttle-warp = "0.42.0" +shuttle-runtime = "0.43.0" +shuttle-warp = "0.43.0" tokio = "1.26.0" warp = "0.3.3" From 7d45c76bb36b277d6f1b1240a5ed4e1e393e012b Mon Sep 17 00:00:00 2001 From: Sourab Pramanik Date: Mon, 8 Apr 2024 13:26:52 +0530 Subject: [PATCH 157/239] feat: bump poem version (#161) --- poem/hello-world/Cargo.toml | 2 +- poem/mongodb/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index c65e0f14..09df26bb 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -poem = "2.0.0" +poem = "3.0.0" shuttle-poem = "0.43.0" shuttle-runtime = "0.43.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 3362c9b9..f6c4b113 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] mongodb = "2.4.0" -poem = "2.0.0" +poem = "3.0.0" shuttle-poem = "0.43.0" shuttle-shared-db = { version = "0.43.0", features = ["mongodb"] } shuttle-runtime = "0.43.0" From 1d727010909dac6b4cef72236f886ff19da77a17 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Mon, 8 Apr 2024 10:14:58 +0200 Subject: [PATCH 158/239] fix: poem AFIT --- poem/mongodb/src/main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/poem/mongodb/src/main.rs b/poem/mongodb/src/main.rs index 2c4af642..fbd676e4 100644 --- a/poem/mongodb/src/main.rs +++ b/poem/mongodb/src/main.rs @@ -14,7 +14,6 @@ use shuttle_poem::ShuttlePoem; struct ObjectIdGuard(ObjectId); -#[poem::async_trait] impl<'a> FromRequest<'a> for ObjectIdGuard { async fn from_request(req: &'a Request, _body: &mut RequestBody) -> Result { let id = req.path_params::()?; From 6f2f5037097e2ce55dfa089a19ad74386922ffc5 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Mon, 8 Apr 2024 12:05:58 +0200 Subject: [PATCH 159/239] fix: clippy --- custom-service/request-scheduler/src/error.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/custom-service/request-scheduler/src/error.rs b/custom-service/request-scheduler/src/error.rs index 5d3856d8..122508b7 100644 --- a/custom-service/request-scheduler/src/error.rs +++ b/custom-service/request-scheduler/src/error.rs @@ -5,11 +5,11 @@ use axum::{ use shuttle_persist::PersistError; #[derive(Debug)] -pub(crate) struct CrontabServiceError(PersistError); +pub(crate) struct CrontabServiceError; impl From for CrontabServiceError { - fn from(err: PersistError) -> Self { - Self(err) + fn from(_err: PersistError) -> Self { + Self } } From 55e473a8bb4fb0df0f5360c250e7dee96130e630 Mon Sep 17 00:00:00 2001 From: Joshua Mo <102877324+joshua-mo-143@users.noreply.github.com> Date: Tue, 23 Apr 2024 07:22:06 +0100 Subject: [PATCH 160/239] feat: update turso resource output type in turso example (#164) --- axum/turso/src/main.rs | 45 +++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/axum/turso/src/main.rs b/axum/turso/src/main.rs index 02593e4a..80eca09a 100644 --- a/axum/turso/src/main.rs +++ b/axum/turso/src/main.rs @@ -1,14 +1,13 @@ use std::sync::Arc; use axum::{extract::State, response::IntoResponse, routing::get, Json, Router}; -use libsql::Connection; +use libsql::Database; use serde::{Deserialize, Serialize}; -async fn get_posts(State(client): State>) -> Json> { - let mut rows = client - .query("select * from example_users", ()) - .await - .unwrap(); +async fn get_posts(State(client): State>) -> Json> { + let conn = client.connect().unwrap(); + + let mut rows = conn.query("select * from example_users", ()).await.unwrap(); let mut users = vec![]; while let Some(row) = rows.next().await.unwrap() { users.push(User { @@ -26,16 +25,16 @@ struct User { } async fn create_users( - State(client): State>, + State(client): State>, Json(user): Json, ) -> impl IntoResponse { - client - .execute( - "insert into example_users (uid, email) values (?1, ?2)", - [user.uid, user.email], - ) - .await - .unwrap(); + let conn = client.connect().unwrap(); + conn.execute( + "insert into example_users (uid, email) values (?1, ?2)", + [user.uid, user.email], + ) + .await + .unwrap(); Json(serde_json::json!({ "ok": true })) } @@ -43,17 +42,17 @@ async fn create_users( #[shuttle_runtime::main] async fn axum( #[shuttle_turso::Turso(addr = "libsql://your-db.turso.io", token = "{secrets.TURSO_DB_TOKEN}")] - client: Connection, + client: Database, ) -> shuttle_axum::ShuttleAxum { let client = Arc::new(client); - - client - .execute( - "create table if not exists example_users ( uid text primary key, email text );", - (), - ) - .await - .unwrap(); + let conn = client.connect().unwrap(); + + conn.execute( + "create table if not exists example_users ( uid text primary key, email text );", + (), + ) + .await + .unwrap(); let router = Router::new() .route("/", get(get_posts).post(create_users)) From 19dda4592a5aebb17c36336456bcf55202565dc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Tue, 23 Apr 2024 08:30:24 +0200 Subject: [PATCH 161/239] chore: v0.44.0 (#165) --- actix-web/clerk/backend/Cargo.toml | 4 ++-- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/htmx-crud/Cargo.toml | 6 +++--- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 4 ++-- axum/oauth2/Cargo.toml | 6 +++--- axum/postgres/Cargo.toml | 6 +++--- axum/qdrant/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- bevy/hello-world/server/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 6 +++--- loco/hello-world/Cargo.toml | 4 ++-- other/standalone-binary/Cargo.toml | 4 ++-- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/opendal-memory/Cargo.toml | 6 +++--- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 4 ++-- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- salvo/image-rescaler/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 6 +++--- serenity/weather-forecast/Cargo.toml | 4 ++-- thruster/hello-world/Cargo.toml | 4 ++-- tide/hello-world/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 46 files changed, 105 insertions(+), 105 deletions(-) diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml index 83e5e740..ce7fa8da 100644 --- a/actix-web/clerk/backend/Cargo.toml +++ b/actix-web/clerk/backend/Cargo.toml @@ -10,5 +10,5 @@ clerk-rs = "0.2.3" openssl-sys = { version = "0.9.9", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-actix-web = "0.44.0" +shuttle-runtime = "0.44.0" diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index 426cd851..e12d238e 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.6.0" actix-session = { version = "0.8.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-actix-web = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 772c989e..5bd8c2b5 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-actix-web = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 35a8cd3e..cae55216 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-actix-web = "0.44.0" +shuttle-runtime = "0.44.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.43.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.44.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index 587491eb..13a58be9 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-actix-web = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 226e1e95..f0b08edd 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-actix-web = "0.44.0" +shuttle-runtime = "0.44.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 1cb6d2fa..6a8f0ef9 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-axum = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.28.2" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index 92892c77..18d60fc7 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -9,9 +9,9 @@ askama_axum = "0.4.0" axum = "0.7.4" serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.43.0" -shuttle-runtime = "0.43.0" -shuttle-shared-db = { version = "0.43.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.44.0" +shuttle-runtime = "0.44.0" +shuttle-shared-db = { version = "0.44.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.2", features = ["runtime-tokio-rustls", "postgres"] } tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index 1d78f1ba..b89b5eea 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-axum = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index 3f944781..d873b1b4 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-axum = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.28.2" diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index 9c1b2b79..cbee9955 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -11,9 +11,9 @@ chrono = { version = "0.4.35", features = ["clock"] } oauth2 = "4.4.1" reqwest = { version = "0.11.18", features = ["json"] } serde = { version = "1.0.183", features = ["derive"] } -shuttle-axum = "0.43.0" -shuttle-runtime = "0.43.0" -shuttle-shared-db = { version = "0.43.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.44.0" +shuttle-runtime = "0.44.0" +shuttle-shared-db = { version = "0.44.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.2", features = ["runtime-tokio-rustls", "macros", "chrono"] } thiserror = "1.0.57" time = "0.3.25" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 91580eca..ab9580ab 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.43.0" -shuttle-runtime = "0.43.0" -shuttle-shared-db = { version = "0.43.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.44.0" +shuttle-runtime = "0.44.0" +shuttle-shared-db = { version = "0.44.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index 9bb167b2..2287daa2 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.7.0" -shuttle-axum = "0.43.0" -shuttle-qdrant = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-axum = "0.44.0" +shuttle-qdrant = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 826e6d61..65f5bf7c 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-axum = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 895b134b..4ad72d8a 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.43.0" -shuttle-runtime = "0.43.0" -shuttle-turso = "0.43.0" +shuttle-axum = "0.44.0" +shuttle-runtime = "0.44.0" +shuttle-turso = "0.44.0" libsql = "0.3.1" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 7fa49747..aaf6b359 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-axum = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/bevy/hello-world/server/Cargo.toml b/bevy/hello-world/server/Cargo.toml index e54b73ba..4d94a590 100644 --- a/bevy/hello-world/server/Cargo.toml +++ b/bevy/hello-world/server/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-axum = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 7d2f78dc..1d7c50f7 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1", features = ["derive"] } -shuttle-service = "0.43.0" -shuttle-axum = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-service = "0.44.0" +shuttle-axum = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index c276c677..ed0083a2 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.43.0" +shuttle-runtime = "0.44.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index 841ba488..c5219c01 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -10,7 +10,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-persist = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 4a8f8f2d..73c4edbf 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,9 +16,9 @@ lettre = "0.11.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.43.0" -shuttle-runtime = "0.43.0" -shuttle-shared-db = { version = "0.43.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.44.0" +shuttle-runtime = "0.44.0" +shuttle-shared-db = { version = "0.44.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.1", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index d32f418e..dc95a9c0 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -13,8 +13,8 @@ async-trait = "0.1.74" axum = "0.7.1" eyre = "*" loco-rs = { version = "0.3.1", default-features = false, features = ["cli"] } -shuttle-axum = "0.43.0" -shuttle-runtime = { version = "0.43.0", default-features = false } +shuttle-axum = "0.44.0" +shuttle-runtime = { version = "0.44.0", default-features = false } serde = "*" serde_json = "*" tokio = "1.33.0" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 4dfe2ae0..9c66e359 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,6 +15,6 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-axum = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 09df26bb..fd4d684a 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "3.0.0" -shuttle-poem = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-poem = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index f6c4b113..166a7f26 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "3.0.0" -shuttle-poem = "0.43.0" -shuttle-shared-db = { version = "0.43.0", features = ["mongodb"] } -shuttle-runtime = "0.43.0" +shuttle-poem = "0.44.0" +shuttle-shared-db = { version = "0.44.0", features = ["mongodb"] } +shuttle-runtime = "0.44.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 9884ae36..a19f6373 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.6.1" -shuttle-runtime = "0.43.0" +shuttle-runtime = "0.44.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity -shuttle-serenity = "0.43.0" +shuttle-serenity = "0.44.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 040b24b3..1a38b845 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" rocket_dyn_templates = { version = "0.1.0", features = ["handlebars"] } -shuttle-rocket = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-rocket = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 353a79f6..3433498a 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-rocket = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index acff10bc..20f01bd7 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-rocket = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.26.0" diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index b391e0bf..8c4df0e9 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -4,10 +4,10 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.43.0" -shuttle-opendal = "0.43.0" +shuttle-runtime = "0.44.0" +shuttle-opendal = "0.44.0" tokio = "1.26.0" -shuttle-rocket = "0.43.0" +shuttle-rocket = "0.44.0" opendal = "0.45.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 6a58fb02..2e0c336e 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.43.0" -shuttle-rocket = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-persist = "0.44.0" +shuttle-rocket = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 38e3a1e4..91eabf56 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.43.0" -shuttle-runtime = "0.43.0" -shuttle-shared-db = { version = "0.43.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.44.0" +shuttle-runtime = "0.44.0" +shuttle-shared-db = { version = "0.44.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index e6acc788..27e75cd7 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-rocket = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index ac828254..50708946 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-rocket = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index cde5892b..37fd1d85 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" nanoid = "0.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.43.0" -shuttle-runtime = "0.43.0" -shuttle-shared-db = { version = "0.43.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.44.0" +shuttle-runtime = "0.44.0" +shuttle-shared-db = { version = "0.44.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 718d655c..f64890ee 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-rocket = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index fbefc5fb..77b2a976 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] salvo = "0.63.0" -shuttle-salvo = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-salvo = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml index 40fc4af4..e173d351 100644 --- a/salvo/image-rescaler/Cargo.toml +++ b/salvo/image-rescaler/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] image = "0.24.8" salvo = "0.63.0" -shuttle-salvo = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-salvo = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 6949ef9e..b18fac23 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.43.0" -shuttle-serenity = "0.43.0" +shuttle-runtime = "0.44.0" +shuttle-serenity = "0.44.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index debfdcea..6d33d546 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.43.0" -shuttle-serenity = "0.43.0" -shuttle-shared-db = { version = "0.43.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.44.0" +shuttle-serenity = "0.44.0" +shuttle-shared-db = { version = "0.44.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/weather-forecast/Cargo.toml b/serenity/weather-forecast/Cargo.toml index ccbce7db..4218fd92 100644 --- a/serenity/weather-forecast/Cargo.toml +++ b/serenity/weather-forecast/Cargo.toml @@ -8,7 +8,7 @@ anyhow = "1.0.66" reqwest = { version = "0.11.24", features = ["json"] } serde = "1.0.197" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.43.0" -shuttle-serenity = "0.43.0" +shuttle-runtime = "0.44.0" +shuttle-serenity = "0.44.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 43c30eef..36f20d9d 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-thruster = "0.44.0" +shuttle-runtime = "0.44.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 767d0098..77b2dcb4 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.43.0" -shuttle-runtime = "0.43.0" +shuttle-tide = "0.44.0" +shuttle-runtime = "0.44.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 65442cd5..b142eeae 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.43.0" -shuttle-tower = "0.43.0" +shuttle-runtime = "0.44.0" +shuttle-tower = "0.44.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index e8e9ef7b..7a566f7f 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.43.0" +shuttle-actix-web = "0.44.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.43.0", default-features = false } +shuttle-runtime = { version = "0.44.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index a760020c..63b3a3c3 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.43.0" -shuttle-warp = "0.43.0" +shuttle-runtime = "0.44.0" +shuttle-warp = "0.44.0" tokio = "1.26.0" warp = "0.3.3" From ca678a9b37818ee6d042587c96d2086aae1d9785 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Tue, 23 Apr 2024 14:28:38 +0200 Subject: [PATCH 162/239] feat: templates tags, logos & some readmes (#163) * feat: logo urls * feat: READMEs for most actix and axum examples * fix: tag casing * fix: ci * clippy * fmt --- actix-web/clerk/README.md | 2 - actix-web/cookie-authentication/Cargo.toml | 4 +- actix-web/cookie-authentication/README.md | 7 +++ actix-web/cookie-authentication/src/main.rs | 19 ++++--- actix-web/postgres/README.md | 13 +++++ .../postgres/migrations/0001_init.sql | 2 - actix-web/postgres/schema.sql | 6 -- actix-web/postgres/src/main.rs | 15 ++--- actix-web/static-files/README.md | 10 ++++ actix-web/static-files/assets/index.html | 2 +- actix-web/static-files/src/main.rs | 13 ++--- actix-web/websocket-actorless/README.md | 7 +++ actix-web/websocket-actorless/src/main.rs | 2 +- axum/htmx-crud/Cargo.toml | 2 +- axum/htmx-crud/README.md | 6 ++ .../{0000_init.sql => 0001_init.sql} | 0 axum/htmx-crud/src/main.rs | 8 +-- axum/jwt-authentication/README.md | 3 + axum/metadata/src/main.rs | 2 +- axum/oauth2/README.md | 14 ++--- ...0815100114_schema.up.sql => 0001_init.sql} | 3 +- .../migrations/20230815100114_schema.down.sql | 3 - axum/oauth2/src/{routes => }/errors.rs | 0 axum/oauth2/src/main.rs | 22 ++++--- axum/oauth2/src/{routes => }/oauth.rs | 16 +++--- axum/oauth2/src/routes/mod.rs | 2 - axum/postgres/README.md | 13 +++++ axum/postgres/migrations/0001_init.sql | 4 ++ axum/postgres/src/main.rs | 5 +- axum/qdrant/README.md | 8 +++ axum/qdrant/src/main.rs | 2 +- axum/turso/src/main.rs | 2 +- axum/websocket/src/main.rs | 2 +- custom-resource/pdo/src/main.rs | 2 +- custom-service/request-scheduler/src/error.rs | 7 --- custom-service/request-scheduler/src/lib.rs | 5 +- .../request-scheduler/src/router.rs | 3 +- fullstack-templates/saas/backend/src/main.rs | 5 +- other/standalone-binary/src/bin/shuttle.rs | 2 +- rocket/dyn-templates/src/main.rs | 2 +- rocket/jwt-authentication/src/main.rs | 2 +- rocket/opendal-memory/src/main.rs | 2 +- rocket/persist/src/main.rs | 2 +- rocket/postgres/src/main.rs | 2 +- rocket/secrets/src/main.rs | 2 +- rocket/static-files/src/main.rs | 2 +- rocket/url-shortener/src/main.rs | 11 ++-- rocket/workspace/hello-world/src/main.rs | 2 +- templates.toml | 57 +++++++++++++------ tracing/custom-tracing-subscriber/src/main.rs | 2 +- 50 files changed, 201 insertions(+), 128 deletions(-) create mode 100644 actix-web/cookie-authentication/README.md create mode 100644 actix-web/postgres/README.md rename axum/postgres/migrations/1_schema.sql => actix-web/postgres/migrations/0001_init.sql (74%) delete mode 100644 actix-web/postgres/schema.sql create mode 100644 actix-web/static-files/README.md create mode 100644 actix-web/websocket-actorless/README.md rename axum/htmx-crud/migrations/{0000_init.sql => 0001_init.sql} (100%) create mode 100644 axum/jwt-authentication/README.md rename axum/oauth2/migrations/{20230815100114_schema.up.sql => 0001_init.sql} (93%) delete mode 100644 axum/oauth2/migrations/20230815100114_schema.down.sql rename axum/oauth2/src/{routes => }/errors.rs (100%) rename axum/oauth2/src/{routes => }/oauth.rs (93%) delete mode 100644 axum/oauth2/src/routes/mod.rs create mode 100644 axum/postgres/README.md create mode 100644 axum/postgres/migrations/0001_init.sql create mode 100644 axum/qdrant/README.md diff --git a/actix-web/clerk/README.md b/actix-web/clerk/README.md index b2a6abea..f7a2d47e 100644 --- a/actix-web/clerk/README.md +++ b/actix-web/clerk/README.md @@ -8,8 +8,6 @@ The template simply shows a list of all signed up users after you sign in, but i ## How to use this template -Clone this template with `cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder actix-web/clerk`. - Sign up at clerk.com, go to the dashboard and create an application with the sign-in options you prefer. Get the `CLERK_SECRET_KEY` secret and put it in `backend/Secrets.toml`. diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index e12d238e..89633067 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -4,8 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -actix-identity = "0.6.0" -actix-session = { version = "0.8.0", features = ["cookie-session"] } +actix-identity = "0.7.1" +actix-session = { version = "0.9.0", features = ["cookie-session"] } actix-web = "4.3.1" shuttle-actix-web = "0.44.0" shuttle-runtime = "0.44.0" diff --git a/actix-web/cookie-authentication/README.md b/actix-web/cookie-authentication/README.md new file mode 100644 index 00000000..a54d8987 --- /dev/null +++ b/actix-web/cookie-authentication/README.md @@ -0,0 +1,7 @@ +# Cookie authentication with actix-session + +This template uses the [actix_identity](https://docs.rs/actix-identity) and [actix_session](https://docs.rs/actix-session) crates to manage user sessions. + +Running the project and visiting will show the currently logged in user. +Visiting will log you in as `user1` (no authentication logic is in place). +Visiting will log you out again. diff --git a/actix-web/cookie-authentication/src/main.rs b/actix-web/cookie-authentication/src/main.rs index ef217955..777225da 100644 --- a/actix-web/cookie-authentication/src/main.rs +++ b/actix-web/cookie-authentication/src/main.rs @@ -2,11 +2,12 @@ use actix_identity::{Identity, IdentityMiddleware}; use actix_session::{config::PersistentSession, storage::CookieSessionStore, SessionMiddleware}; use actix_web::{ cookie::{time::Duration, Key}, - error, + error, get, http::StatusCode, - middleware, web, HttpMessage as _, HttpRequest, Responder, + middleware, + web::{self, ServiceConfig}, + HttpMessage as _, HttpRequest, Responder, }; -use actix_web::{get, web::ServiceConfig}; use shuttle_actix_web::ShuttleActixWeb; const FIVE_MINUTES: Duration = Duration::minutes(5); @@ -24,6 +25,9 @@ async fn index(identity: Option) -> actix_web::Result #[get("/login")] async fn login(req: HttpRequest) -> impl Responder { + // some kind of authentication should happen here + + // attach a verified user identity to the active session Identity::login(&req.extensions(), "user1".to_owned()).unwrap(); web::Redirect::to("/").using_status_code(StatusCode::FOUND) @@ -37,18 +41,19 @@ async fn logout(id: Identity) -> impl Responder { } #[shuttle_runtime::main] -async fn actix_web() -> ShuttleActixWeb { +async fn main() -> ShuttleActixWeb { // Generate a random secret key. Note that it is important to use a unique // secret key for every project. Anyone with access to the key can generate // authentication cookies for any user! // - // If the secret key is read from a file or the environment, make sure it is generated securely. + // When deployed the secret key should be read from deployment secrets. + // // For example, a secure random key (in base64 format) can be generated with the OpenSSL CLI: // ``` // openssl rand -base64 64 // ``` // - // Then decoded and used converted to a Key: + // Then decoded and converted to a Key: // ``` // let secret_key = Key::from(base64::decode(&private_key_base64).unwrap()); // ``` @@ -56,7 +61,7 @@ async fn actix_web() -> ShuttleActixWeb, state: web::Data) -> Result> { @@ -37,12 +37,13 @@ struct AppState { } #[shuttle_runtime::main] -async fn actix_web( +async fn main( #[shuttle_shared_db::Postgres] pool: PgPool, ) -> ShuttleActixWeb { - pool.execute(include_str!("../schema.sql")) + sqlx::migrate!() + .run(&pool) .await - .map_err(CustomError::new)?; + .expect("Failed to run migrations"); let state = web::Data::new(AppState { pool }); diff --git a/actix-web/static-files/README.md b/actix-web/static-files/README.md new file mode 100644 index 00000000..5f770281 --- /dev/null +++ b/actix-web/static-files/README.md @@ -0,0 +1,10 @@ +# Actix Web static files + +This template uses `actix_files` to serve the files in the `assets` directory. + +## Example usage + +```bash +curl localhost:8000/index.html +#

    Hello world!

    +``` diff --git a/actix-web/static-files/assets/index.html b/actix-web/static-files/assets/index.html index cd087558..597ecf5f 100644 --- a/actix-web/static-files/assets/index.html +++ b/actix-web/static-files/assets/index.html @@ -1 +1 @@ -Hello world! +

    Hello world!

    diff --git a/actix-web/static-files/src/main.rs b/actix-web/static-files/src/main.rs index 5a3923d0..fd170817 100644 --- a/actix-web/static-files/src/main.rs +++ b/actix-web/static-files/src/main.rs @@ -1,16 +1,11 @@ -use actix_files::NamedFile; -use actix_web::{get, web::ServiceConfig, Responder}; +use actix_files::Files; +use actix_web::web::ServiceConfig; use shuttle_actix_web::ShuttleActixWeb; -#[get("/")] -async fn index() -> impl Responder { - NamedFile::open_async("assets/index.html").await -} - #[shuttle_runtime::main] -async fn actix_web() -> ShuttleActixWeb { +async fn main() -> ShuttleActixWeb { let config = move |cfg: &mut ServiceConfig| { - cfg.service(index); + cfg.service(Files::new("/", "assets")); }; Ok(config.into()) diff --git a/actix-web/websocket-actorless/README.md b/actix-web/websocket-actorless/README.md new file mode 100644 index 00000000..19340c2c --- /dev/null +++ b/actix-web/websocket-actorless/README.md @@ -0,0 +1,7 @@ +# Actix Web actorless websockets + +This template shows how to use actorless websockets to build an API monitoring service and a simple chat app. + +## Example usage + +Run the app and go to . diff --git a/actix-web/websocket-actorless/src/main.rs b/actix-web/websocket-actorless/src/main.rs index 1b5ca52e..173ff3b3 100644 --- a/actix-web/websocket-actorless/src/main.rs +++ b/actix-web/websocket-actorless/src/main.rs @@ -105,7 +105,7 @@ async fn index() -> impl Responder { } #[shuttle_runtime::main] -async fn actix_web() -> ShuttleActixWeb { +async fn main() -> ShuttleActixWeb { // We're going to use channels to communicate between threads. // api state channel let (tx_api_state, rx_api_state) = watch::channel(ApiStateMessage::default()); diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index 18d60fc7..52a1fcfc 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -12,6 +12,6 @@ serde_json = "1.0.107" shuttle-axum = "0.44.0" shuttle-runtime = "0.44.0" shuttle-shared-db = { version = "0.44.0", features = ["postgres", "sqlx"] } -sqlx = { version = "0.7.2", features = ["runtime-tokio-rustls", "postgres"] } +sqlx = "0.7.2" tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/htmx-crud/README.md b/axum/htmx-crud/README.md index ebbc3114..9d09c004 100644 --- a/axum/htmx-crud/README.md +++ b/axum/htmx-crud/README.md @@ -1,3 +1,9 @@ # Axum + htmx This is an example of how you can use Shuttle with Axum, Askama and htmx to create a frontend that's easily extendable and requires zero framework knowledge, while being able to easily inject variables from the backend into the frontend. + +The app is a TODO list with a main page and an event stream page. + +## Usage + +Run the app and go to to add and remove TODOs from the list. diff --git a/axum/htmx-crud/migrations/0000_init.sql b/axum/htmx-crud/migrations/0001_init.sql similarity index 100% rename from axum/htmx-crud/migrations/0000_init.sql rename to axum/htmx-crud/migrations/0001_init.sql diff --git a/axum/htmx-crud/src/main.rs b/axum/htmx-crud/src/main.rs index d46d95ef..9fea4c0d 100644 --- a/axum/htmx-crud/src/main.rs +++ b/axum/htmx-crud/src/main.rs @@ -6,13 +6,13 @@ mod routes; mod templates; #[shuttle_runtime::main] -async fn main(#[shuttle_shared_db::Postgres] db: PgPool) -> shuttle_axum::ShuttleAxum { +async fn main(#[shuttle_shared_db::Postgres] pool: PgPool) -> shuttle_axum::ShuttleAxum { sqlx::migrate!() - .run(&db) + .run(&pool) .await - .expect("Looks like something went wrong with migrations :("); + .expect("Failed to run migrations"); - let router = router::init_router(db); + let router = router::init_router(pool); Ok(router.into()) } diff --git a/axum/jwt-authentication/README.md b/axum/jwt-authentication/README.md new file mode 100644 index 00000000..15ecfdac --- /dev/null +++ b/axum/jwt-authentication/README.md @@ -0,0 +1,3 @@ +# JWT authentication in Axum + +This template uses the `jsonwebtoken` crate to encode and decode claims in a JWT, which clients use in the Authorization HTTP header to access protected resources (endpoints). diff --git a/axum/metadata/src/main.rs b/axum/metadata/src/main.rs index 77561fdd..9ddc6ac6 100644 --- a/axum/metadata/src/main.rs +++ b/axum/metadata/src/main.rs @@ -2,7 +2,7 @@ use axum::{routing::get, Router}; use shuttle_runtime::DeploymentMetadata; #[shuttle_runtime::main] -async fn axum( +async fn main( #[shuttle_runtime::Metadata] metadata: DeploymentMetadata, ) -> shuttle_axum::ShuttleAxum { let router = Router::new().route("/", get(format!("{:?}", metadata))); diff --git a/axum/oauth2/README.md b/axum/oauth2/README.md index bc3237a2..f9ceb360 100644 --- a/axum/oauth2/README.md +++ b/axum/oauth2/README.md @@ -1,15 +1,13 @@ -## OAuth Axum Rust Example -This repo is an example of how you can quickly and easily implement OAuth using the Axum web framework in Rust. Hosted on Shuttle. +# Google OAuth in Axum -### How to Run -Make sure you set up your Google OAuth, which you can find a link to set up [here.](https://console.cloud.google.com/apis/dashboard) +This template is an example of how you can implement Google OAuth using the Axum web framework in Rust. -Initialise your Shuttle project with `cargo shuttle init`: -```sh -cargo shuttle init --from shuttle-hq/examples --subfolder axum/oauth2 -``` +## Prerequisites + +Make sure you set up your Google OAuth, which you can find a link to set up [here.](https://console.cloud.google.com/apis/dashboard) Set your secrets in the Secrets.toml file: + ```toml GOOGLE_OAUTH_CLIENT_ID = "your-client-id" GOOGLE_OAUTH_CLIENT_SECRET = "your-client-secret" diff --git a/axum/oauth2/migrations/20230815100114_schema.up.sql b/axum/oauth2/migrations/0001_init.sql similarity index 93% rename from axum/oauth2/migrations/20230815100114_schema.up.sql rename to axum/oauth2/migrations/0001_init.sql index 5e5d8234..fe76ad38 100644 --- a/axum/oauth2/migrations/20230815100114_schema.up.sql +++ b/axum/oauth2/migrations/0001_init.sql @@ -1,4 +1,3 @@ --- Add up migration script here CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, email VARCHAR(255) NOT NULL UNIQUE, @@ -12,4 +11,4 @@ CREATE TABLE IF NOT EXISTS sessions ( session_id VARCHAR NOT NULL, expires_at TIMESTAMP WITH TIME ZONE NOT NULL, FOREIGN KEY (user_id) REFERENCES users(id) -); \ No newline at end of file +); diff --git a/axum/oauth2/migrations/20230815100114_schema.down.sql b/axum/oauth2/migrations/20230815100114_schema.down.sql deleted file mode 100644 index 16f2ef4c..00000000 --- a/axum/oauth2/migrations/20230815100114_schema.down.sql +++ /dev/null @@ -1,3 +0,0 @@ --- Add down migration script here -DROP TABLE users; -DROP TABLE sessions; \ No newline at end of file diff --git a/axum/oauth2/src/routes/errors.rs b/axum/oauth2/src/errors.rs similarity index 100% rename from axum/oauth2/src/routes/errors.rs rename to axum/oauth2/src/errors.rs diff --git a/axum/oauth2/src/main.rs b/axum/oauth2/src/main.rs index c6dbd175..f21bdf6f 100644 --- a/axum/oauth2/src/main.rs +++ b/axum/oauth2/src/main.rs @@ -2,10 +2,11 @@ use axum::{extract::FromRef, response::Html, routing::get, Extension, Router}; use axum_extra::extract::cookie::Key; use oauth2::{basic::BasicClient, AuthUrl, ClientId, ClientSecret, RedirectUrl, TokenUrl}; use reqwest::Client; -use routes::oauth; use shuttle_runtime::SecretStore; use sqlx::PgPool; -pub mod routes; + +pub mod errors; +pub mod oauth; #[derive(Clone)] pub struct AppState { @@ -22,14 +23,14 @@ impl FromRef for Key { } #[shuttle_runtime::main] -async fn axum( +async fn main( #[shuttle_shared_db::Postgres] db: PgPool, #[shuttle_runtime::Secrets] secrets: SecretStore, ) -> shuttle_axum::ShuttleAxum { sqlx::migrate!() .run(&db) .await - .expect("Failed migrations :("); + .expect("Failed to run migrations"); let oauth_id = secrets.get("GOOGLE_OAUTH_CLIENT_ID").unwrap(); let oauth_secret = secrets.get("GOOGLE_OAUTH_CLIENT_SECRET").unwrap(); @@ -85,9 +86,12 @@ fn build_oauth_client(client_id: String, client_secret: String) -> BasicClient { #[axum::debug_handler] async fn homepage(Extension(oauth_id): Extension) -> Html { - Html(format!("

    Welcome!

    - - - Click here to sign into Google! - ")) + Html(format!( + r#" +

    Welcome!

    + + Click here to sign into Google! + + "# + )) } diff --git a/axum/oauth2/src/routes/oauth.rs b/axum/oauth2/src/oauth.rs similarity index 93% rename from axum/oauth2/src/routes/oauth.rs rename to axum/oauth2/src/oauth.rs index 957e3b61..2aff1cd6 100644 --- a/axum/oauth2/src/routes/oauth.rs +++ b/axum/oauth2/src/oauth.rs @@ -1,6 +1,3 @@ -use crate::routes::errors::ApiError; - -use crate::AppState; use axum::{ extract::{FromRequest, FromRequestParts, Query, Request, State}, http::StatusCode, @@ -13,6 +10,9 @@ use oauth2::{basic::BasicClient, reqwest::async_http_client, AuthorizationCode, use serde::Deserialize; use time::Duration as TimeDuration; +use crate::errors::ApiError; +use crate::AppState; + #[derive(Debug, Deserialize)] pub struct AuthRequest { code: String, @@ -62,8 +62,8 @@ pub async fn google_callback( "INSERT INTO sessions (user_id, session_id, expires_at) VALUES ( (SELECT ID FROM USERS WHERE email = $1 LIMIT 1), $2, $3) - ON CONFLICT (user_id) DO UPDATE SET - session_id = excluded.session_id, + ON CONFLICT (user_id) DO UPDATE SET + session_id = excluded.session_id, expires_at = excluded.expires_at", ) .bind(profile.email) @@ -94,11 +94,11 @@ impl FromRequest for UserProfile { }; let res = sqlx::query_as::<_, UserProfile>( - "SELECT + "SELECT users.email - FROM sessions + FROM sessions LEFT JOIN USERS ON sessions.user_id = users.id - WHERE sessions.session_id = $1 + WHERE sessions.session_id = $1 LIMIT 1", ) .bind(cookie) diff --git a/axum/oauth2/src/routes/mod.rs b/axum/oauth2/src/routes/mod.rs deleted file mode 100644 index 11e76bc2..00000000 --- a/axum/oauth2/src/routes/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod errors; -pub mod oauth; diff --git a/axum/postgres/README.md b/axum/postgres/README.md new file mode 100644 index 00000000..cccd4458 --- /dev/null +++ b/axum/postgres/README.md @@ -0,0 +1,13 @@ +# Shuttle shared Postgres DB with Axum + +This template shows how to connect a Postgres database and use it for a simple TODO list app. + +## Example usage + +```bash +curl -X POST -H 'content-type: application/json' localhost:8000/todos --data '{"note":"My todo"}' +# {"id":1,"note":"My todo"} + +curl localhost:8000/todos/1 +# {"id":1,"note":"My todo"} +``` diff --git a/axum/postgres/migrations/0001_init.sql b/axum/postgres/migrations/0001_init.sql new file mode 100644 index 00000000..0e3918a5 --- /dev/null +++ b/axum/postgres/migrations/0001_init.sql @@ -0,0 +1,4 @@ +CREATE TABLE IF NOT EXISTS todos ( + id serial PRIMARY KEY, + note TEXT NOT NULL +); diff --git a/axum/postgres/src/main.rs b/axum/postgres/src/main.rs index 623c35bc..b13219fe 100644 --- a/axum/postgres/src/main.rs +++ b/axum/postgres/src/main.rs @@ -6,7 +6,6 @@ use axum::{ Json, Router, }; use serde::{Deserialize, Serialize}; -use shuttle_runtime::CustomError; use sqlx::{FromRow, PgPool}; async fn retrieve( @@ -43,11 +42,11 @@ struct MyState { } #[shuttle_runtime::main] -async fn axum(#[shuttle_shared_db::Postgres] pool: PgPool) -> shuttle_axum::ShuttleAxum { +async fn main(#[shuttle_shared_db::Postgres] pool: PgPool) -> shuttle_axum::ShuttleAxum { sqlx::migrate!() .run(&pool) .await - .map_err(CustomError::new)?; + .expect("Failed to run migrations"); let state = MyState { pool }; let router = Router::new() diff --git a/axum/qdrant/README.md b/axum/qdrant/README.md new file mode 100644 index 00000000..cf84257c --- /dev/null +++ b/axum/qdrant/README.md @@ -0,0 +1,8 @@ +# Connect to a Qdrant Cloud DB from Shuttle + +This example shows how to use `shuttle-qdrant` to connect to a Qdrant vector database from Shuttle. + +## Prerequisites + +Go to [Qdrant](https://qdrant.tech/) and start a database. +Paste the URL and API key in the Secrets.toml file. diff --git a/axum/qdrant/src/main.rs b/axum/qdrant/src/main.rs index 7b87f778..924cef11 100644 --- a/axum/qdrant/src/main.rs +++ b/axum/qdrant/src/main.rs @@ -11,7 +11,7 @@ async fn list_collections(State(state): State>) -> String { } #[shuttle_runtime::main] -async fn axum( +async fn main( #[shuttle_qdrant::Qdrant(cloud_url = "{secrets.CLOUD_URL}", api_key = "{secrets.API_KEY}")] qdrant: QdrantClient, ) -> shuttle_axum::ShuttleAxum { diff --git a/axum/turso/src/main.rs b/axum/turso/src/main.rs index 80eca09a..d26cd9e7 100644 --- a/axum/turso/src/main.rs +++ b/axum/turso/src/main.rs @@ -40,7 +40,7 @@ async fn create_users( } #[shuttle_runtime::main] -async fn axum( +async fn main( #[shuttle_turso::Turso(addr = "libsql://your-db.turso.io", token = "{secrets.TURSO_DB_TOKEN}")] client: Database, ) -> shuttle_axum::ShuttleAxum { diff --git a/axum/websocket/src/main.rs b/axum/websocket/src/main.rs index dac3676f..2c6ad0ba 100644 --- a/axum/websocket/src/main.rs +++ b/axum/websocket/src/main.rs @@ -36,7 +36,7 @@ struct Response { } #[shuttle_runtime::main] -async fn axum() -> ShuttleAxum { +async fn main() -> ShuttleAxum { let (tx, rx) = watch::channel(Message::Text("{}".to_string())); let state = Arc::new(Mutex::new(State { diff --git a/custom-resource/pdo/src/main.rs b/custom-resource/pdo/src/main.rs index 14535844..84a7ad02 100644 --- a/custom-resource/pdo/src/main.rs +++ b/custom-resource/pdo/src/main.rs @@ -7,7 +7,7 @@ async fn hello_world(State(pdo): State>) -> String { } #[shuttle_runtime::main] -async fn axum(#[Builder(field = "value")] pdo: Pdo) -> shuttle_axum::ShuttleAxum { +async fn main(#[Builder(field = "value")] pdo: Pdo) -> shuttle_axum::ShuttleAxum { let state = Arc::new(pdo); let router = Router::new().route("/", get(hello_world)).with_state(state); diff --git a/custom-service/request-scheduler/src/error.rs b/custom-service/request-scheduler/src/error.rs index 122508b7..586462a6 100644 --- a/custom-service/request-scheduler/src/error.rs +++ b/custom-service/request-scheduler/src/error.rs @@ -2,17 +2,10 @@ use axum::{ http::StatusCode, response::{IntoResponse, Response}, }; -use shuttle_persist::PersistError; #[derive(Debug)] pub(crate) struct CrontabServiceError; -impl From for CrontabServiceError { - fn from(_err: PersistError) -> Self { - Self - } -} - impl IntoResponse for CrontabServiceError { fn into_response(self) -> Response { (StatusCode::INTERNAL_SERVER_ERROR).into_response() diff --git a/custom-service/request-scheduler/src/lib.rs b/custom-service/request-scheduler/src/lib.rs index 172c4b98..3b049285 100644 --- a/custom-service/request-scheduler/src/lib.rs +++ b/custom-service/request-scheduler/src/lib.rs @@ -108,7 +108,10 @@ impl CronRunner { crontab.jobs.push(raw); debug!("Persisting {:?} jobs", crontab.jobs.len()); - let res = self.persist.save("crontab", crontab).map_err(From::from); + let res = self + .persist + .save("crontab", crontab) + .map_err(|_| CrontabServiceError); let _ = resp.send(res); tokio::spawn(async move { diff --git a/custom-service/request-scheduler/src/router.rs b/custom-service/request-scheduler/src/router.rs index d0ff2b11..727b2282 100644 --- a/custom-service/request-scheduler/src/router.rs +++ b/custom-service/request-scheduler/src/router.rs @@ -7,7 +7,6 @@ use axum::{extract::Form, Router}; use tokio::sync::oneshot; use tracing::debug; -use crate::error::CrontabServiceError; use crate::{CrontabServiceState, Msg, RawJob}; pub(crate) fn make_router(cron_state: Arc) -> Router { @@ -19,7 +18,7 @@ pub(crate) fn make_router(cron_state: Arc) -> Router { async fn set_schedule( State(state): State>, Form(job): Form, -) -> Result { +) -> impl IntoResponse { debug!("Accepted new job: {:?}", job); let (tx, rx) = oneshot::channel(); diff --git a/fullstack-templates/saas/backend/src/main.rs b/fullstack-templates/saas/backend/src/main.rs index 6aa46ce2..afdd4613 100644 --- a/fullstack-templates/saas/backend/src/main.rs +++ b/fullstack-templates/saas/backend/src/main.rs @@ -2,7 +2,6 @@ use axum::extract::FromRef; use axum::Router; use axum_extra::extract::cookie::Key; use sqlx::PgPool; - use tower_http::services::{ServeDir, ServeFile}; mod auth; @@ -33,14 +32,14 @@ impl FromRef for Key { } #[shuttle_runtime::main] -async fn axum( +async fn main( #[shuttle_shared_db::Postgres] postgres: PgPool, #[shuttle_runtime::Secrets] secrets: shuttle_runtime::SecretStore, ) -> shuttle_axum::ShuttleAxum { sqlx::migrate!() .run(&postgres) .await - .expect("Had some errors running migrations :("); + .expect("Failed to run migrations"); let (stripe_key, stripe_sub_price, mailgun_key, mailgun_url, domain) = grab_secrets(secrets); diff --git a/other/standalone-binary/src/bin/shuttle.rs b/other/standalone-binary/src/bin/shuttle.rs index 99133ef6..456bc35d 100644 --- a/other/standalone-binary/src/bin/shuttle.rs +++ b/other/standalone-binary/src/bin/shuttle.rs @@ -4,7 +4,7 @@ use shuttle_runtime::SecretStore; use multi_binary::build_router; #[shuttle_runtime::main] -async fn axum(#[shuttle_runtime::Secrets] secret_store: SecretStore) -> ShuttleAxum { +async fn main(#[shuttle_runtime::Secrets] secret_store: SecretStore) -> ShuttleAxum { // Get all resources 'the Shuttle way' let my_secret = secret_store.get("SOME_API_KEY").unwrap(); diff --git a/rocket/dyn-templates/src/main.rs b/rocket/dyn-templates/src/main.rs index 6ef11fcb..b5f79fd3 100644 --- a/rocket/dyn-templates/src/main.rs +++ b/rocket/dyn-templates/src/main.rs @@ -22,7 +22,7 @@ pub fn hello(name: &str) -> Template { } #[shuttle_runtime::main] -async fn rocket() -> shuttle_rocket::ShuttleRocket { +async fn main() -> shuttle_rocket::ShuttleRocket { let rocket = rocket::build() // If you also wish to serve static content, uncomment line below and corresponding 'use' on line 4 // .mount("/", FileServer::from(relative!("templates"))) diff --git a/rocket/jwt-authentication/src/main.rs b/rocket/jwt-authentication/src/main.rs index 5f6651c8..47753927 100644 --- a/rocket/jwt-authentication/src/main.rs +++ b/rocket/jwt-authentication/src/main.rs @@ -70,7 +70,7 @@ fn login(login: Json) -> Result, Custom shuttle_rocket::ShuttleRocket { +async fn main() -> shuttle_rocket::ShuttleRocket { let rocket = rocket::build().mount("/", routes![public, private, login]); Ok(rocket.into()) diff --git a/rocket/opendal-memory/src/main.rs b/rocket/opendal-memory/src/main.rs index 7e5d32a7..566846ff 100644 --- a/rocket/opendal-memory/src/main.rs +++ b/rocket/opendal-memory/src/main.rs @@ -39,7 +39,7 @@ async fn retrieve(path: String, state: &State) -> Result shuttle_rocket::ShuttleRocket { let state = MyState { storage }; diff --git a/rocket/persist/src/main.rs b/rocket/persist/src/main.rs index db0bbb6b..1cf96ca3 100644 --- a/rocket/persist/src/main.rs +++ b/rocket/persist/src/main.rs @@ -51,7 +51,7 @@ async fn retrieve( } #[shuttle_runtime::main] -async fn rocket( +async fn main( #[shuttle_persist::Persist] persist: PersistInstance, ) -> shuttle_rocket::ShuttleRocket { let state = MyState { persist }; diff --git a/rocket/postgres/src/main.rs b/rocket/postgres/src/main.rs index 7b851bce..eda75fec 100644 --- a/rocket/postgres/src/main.rs +++ b/rocket/postgres/src/main.rs @@ -38,7 +38,7 @@ struct MyState { } #[shuttle_runtime::main] -async fn rocket(#[shuttle_shared_db::Postgres] pool: PgPool) -> shuttle_rocket::ShuttleRocket { +async fn main(#[shuttle_shared_db::Postgres] pool: PgPool) -> shuttle_rocket::ShuttleRocket { pool.execute(include_str!("../schema.sql")) .await .map_err(CustomError::new)?; diff --git a/rocket/secrets/src/main.rs b/rocket/secrets/src/main.rs index 42159863..c06f5dcf 100644 --- a/rocket/secrets/src/main.rs +++ b/rocket/secrets/src/main.rs @@ -16,7 +16,7 @@ struct MyState { } #[shuttle_runtime::main] -async fn rocket(#[shuttle_runtime::Secrets] secrets: SecretStore) -> shuttle_rocket::ShuttleRocket { +async fn main(#[shuttle_runtime::Secrets] secrets: SecretStore) -> shuttle_rocket::ShuttleRocket { // get secret defined in `Secrets.toml` file. let secret = secrets.get("MY_API_KEY").context("secret was not found")?; diff --git a/rocket/static-files/src/main.rs b/rocket/static-files/src/main.rs index 3c5bc59f..5da91f4e 100644 --- a/rocket/static-files/src/main.rs +++ b/rocket/static-files/src/main.rs @@ -14,7 +14,7 @@ pub async fn serve(mut path: PathBuf) -> Option { } #[shuttle_runtime::main] -async fn rocket() -> shuttle_rocket::ShuttleRocket { +async fn main() -> shuttle_rocket::ShuttleRocket { let rocket = rocket::build().mount("/", rocket::routes![serve]); Ok(rocket.into()) diff --git a/rocket/url-shortener/src/main.rs b/rocket/url-shortener/src/main.rs index 73cc139f..b7ca4d15 100644 --- a/rocket/url-shortener/src/main.rs +++ b/rocket/url-shortener/src/main.rs @@ -7,8 +7,6 @@ use rocket::{ routes, State, }; use serde::Serialize; -use shuttle_runtime::CustomError; -use sqlx::migrate::Migrator; use sqlx::{FromRow, PgPool}; use url::Url; @@ -68,11 +66,12 @@ async fn shorten(url: String, state: &State) -> Result shuttle_rocket::ShuttleRocket { - MIGRATOR.run(&pool).await.map_err(CustomError::new)?; +async fn main(#[shuttle_shared_db::Postgres] pool: PgPool) -> shuttle_rocket::ShuttleRocket { + sqlx::migrate!() + .run(&pool) + .await + .expect("Failed to run migrations"); let state = AppState { pool }; let rocket = rocket::build() diff --git a/rocket/workspace/hello-world/src/main.rs b/rocket/workspace/hello-world/src/main.rs index 2a722f6b..7b6d4f5a 100644 --- a/rocket/workspace/hello-world/src/main.rs +++ b/rocket/workspace/hello-world/src/main.rs @@ -7,7 +7,7 @@ fn index() -> &'static str { } #[shuttle_runtime::main] -async fn rocket() -> shuttle_rocket::ShuttleRocket { +async fn main() -> shuttle_rocket::ShuttleRocket { let rocket = rocket::build().mount("/", routes![index]); Ok(rocket.into()) diff --git a/templates.toml b/templates.toml index 18fe1535..d0a25e52 100644 --- a/templates.toml +++ b/templates.toml @@ -4,6 +4,29 @@ # Use `rust-script _scripts/check-templates.rs` to validate this list. version = 1 +# mapping of tag name -> image url +[logos] +actix-web = "https://avatars.githubusercontent.com/u/32776943?v=4" +axum = "https://avatars.githubusercontent.com/u/20248544?v=4" +rocket = "https://avatars.githubusercontent.com/u/106361765?v=4" +bevy = "https://avatars.githubusercontent.com/u/60047606?v=4" +loco = "https://avatars.githubusercontent.com/u/151030972?v=4" +poem = "https://avatars.githubusercontent.com/u/88869778?v=4" +poise = "https://avatars.githubusercontent.com/u/32077193?v=4" +serenity = "https://avatars.githubusercontent.com/u/32077193?v=4" +salvo = "https://avatars.githubusercontent.com/u/77909452?v=4" +tide = "https://avatars.githubusercontent.com/u/56456261?v=4" +tower = "https://avatars.githubusercontent.com/u/26263939?v=4" +postgres = "https://avatars.githubusercontent.com/u/177543?v=4" +clerk = "https://avatars.githubusercontent.com/u/49538330?v=4" +htmx = "https://raw.githubusercontent.com/bigskysoftware/htmx/8e26d12c33caf7dc99c49d4918e7b8abd8028f98/www/static/img/htmx_logo.2.png" +qdrant = "https://avatars.githubusercontent.com/u/73504361?v=4" +nextjs = "https://assets.vercel.com/image/upload/v1662130559/nextjs/Icon_light_background.png" +mongodb = "https://avatars.githubusercontent.com/u/45120?v=4" +opendal = "https://avatars.githubusercontent.com/u/47359?v=4" +# fallback +shuttle = "https://avatars.githubusercontent.com/u/54710151?v=4" + ## OFFICIAL STARTERS ## @@ -126,14 +149,14 @@ title = "Postgres" description = "Todo list with a Postgres database" path = "actix-web/postgres" use_cases = ["Web app", "Storage"] -tags = ["actix-web", "database", "postgres"] +tags = ["postgres", "actix-web", "database"] [templates.actix-web-clerk-react] title = "Clerk authentication" description = "Fullstack Rust+React with auth provider logic" path = "actix-web/clerk" use_cases = ["Web app", "Authentication"] -tags = ["actix-web", "clerk", "react", "typescript", "tailwind"] +tags = ["clerk", "actix-web", "react", "typescript", "tailwind"] [templates.actix-cookie-authentication] title = "Cookie Authentication" @@ -161,7 +184,7 @@ title = "HTMX" description = "Simple CRUD app using HTMX and Askama" path = "axum/htmx-crud" use_cases = ["Web app", "Storage"] -tags = ["axum", "htmx", "database", "postgres"] +tags = ["htmx", "axum", "database", "postgres"] [templates.axum-jwt-authentication] title = "JWT authentication" @@ -182,14 +205,14 @@ title = "Postgres" description = "Todo list with a Postgres database" path = "axum/postgres" use_cases = ["Web app", "Storage"] -tags = ["axum", "database", "postgres"] +tags = ["postgres", "axum", "database"] [templates.axum-qdrant] title = "Qdrant" description = "Connecting to Qdrant cloud with shuttle-qdrant" path = "axum/qdrant" use_cases = ["Web app", "Storage", "AI"] -tags = ["axum", "database", "qdrant"] +tags = ["qdrant", "axum", "database"] [templates.axum-static-files] title = "File server" @@ -203,7 +226,7 @@ title = "Turso" description = "Connect to a Turso DB with shuttle-turso" path = "axum/turso" use_cases = ["Web app", "Storage"] -tags = ["axum", "database", "libsql", "sqlite"] +tags = ["turso", "axum", "database", "libsql", "sqlite"] [templates.axum-websocket] title = "Websockets" @@ -224,14 +247,14 @@ title = "Fullstack SaaS" description = "Opinionated fullstack web app with pre-made routes and assets" path = "fullstack-templates/saas" use_cases = ["Web app", "Authentication", "Storage", "Monetization"] -tags = ["axum", "next.js", "database", "postgres", "typescript", "tailwind"] +tags = ["nextjs", "axum", "database", "postgres", "typescript", "tailwind"] [templates.poem-mongodb] title = "MongoDB" description = "Todo list with a MongoDB database" path = "poem/mongodb" use_cases = ["Web app", "Storage"] -tags = ["poem", "database", "mongodb"] +tags = ["mongodb", "poem", "database"] [templates.rocket-dyn-templates] title = "Handlebars dynamic templates" @@ -252,14 +275,14 @@ title = "OpenDAL in-memory store" description = "A key-value store using OpenDAL" path = "rocket/opendal-memory" use_cases = ["Web app", "Storage"] -tags = ["rocket", "opendal"] +tags = ["opendal", "rocket"] [templates.rocket-postgres] title = "Postgres" description = "Todo list with a Postgres database" path = "rocket/postgres" use_cases = ["Web app", "Storage"] -tags = ["rocket", "database", "postgres"] +tags = ["postgres", "rocket", "database"] [templates.rocket-static-files] title = "File server" @@ -307,7 +330,7 @@ tags = ["axum", "apalis", "database", "postgres"] title = "Custom Tracing Subscriber" description = "How to use a custom tracing-subscriber on Shuttle" path = "tracing/custom-tracing-subscriber" -use_cases = ["Web App", "Logging"] +use_cases = ["Web app", "Logging"] tags = ["actix-web", "tracing"] @@ -371,7 +394,7 @@ tags = ["diy", "axum"] [community_templates.actix-github-oauth] title = "GitHub Login (OAuth)" description = "Sample app demonstrating GitHub OAuth login using Actix Web" -use_cases = ["Web App", "Authentication"] +use_cases = ["Web app", "Authentication"] tags = ["actix-web", "oauth"] author = "robjtede" repo = "https://github.com/robjtede/actix-examples-oauth-github" @@ -379,15 +402,15 @@ repo = "https://github.com/robjtede/actix-examples-oauth-github" [community_templates.fullstack-rust-axum-yew] title = "Fullstack Rust" description = "A template for fullstack Rust projects with Yew" -use_cases = ["Web App"] +use_cases = ["Web app"] tags = ["axum", "yew"] author = "TylerBloom" repo = "https://github.com/TylerBloom/shuttle-fullstack-rust-example" [community_templates.axum-web-app-yew] -title = "Web App with Yew" +title = "Web app with Yew" description = "A template for a web app using the Yew framework" -use_cases = ["Web App"] +use_cases = ["Web app"] tags = ["axum", "yew"] author = "sentinel1909" repo = "https://github.com/sentinel1909/shuttle-template-yew" @@ -395,7 +418,7 @@ repo = "https://github.com/sentinel1909/shuttle-template-yew" [community_templates.actix-web-api] title = "Web API with Actix Web" description = "A template for starting an API with Actix Web" -use_cases = ["Web App"] +use_cases = ["Web app"] tags = ["actix-web"] author = "sentinel1909" repo = "https://github.com/sentinel1909/shuttle-template-actix" @@ -403,7 +426,7 @@ repo = "https://github.com/sentinel1909/shuttle-template-actix" [community_templates.rocket-yew-sled] title = "Web API with Rocket and Sled" description = "A Full Stack CRUD template for starting an API with Rocket, Sled, and Yew" -use_cases = ["Web App"] +use_cases = ["Web app"] tags = ["rocket", "yew"] author = "wiseaidev" repo = "https://github.com/wiseaidev/rocket-yew-starter-pack" diff --git a/tracing/custom-tracing-subscriber/src/main.rs b/tracing/custom-tracing-subscriber/src/main.rs index b754211e..7246d0a1 100644 --- a/tracing/custom-tracing-subscriber/src/main.rs +++ b/tracing/custom-tracing-subscriber/src/main.rs @@ -11,7 +11,7 @@ async fn hello_world() -> &'static str { } #[shuttle_runtime::main] -async fn actix_web() -> ShuttleActixWeb { +async fn main() -> ShuttleActixWeb { // We need to write to stdout for Shuttle to record our logs, so we use the // tracing::fmt subscriber which has sane defaults for applications and also // writes to stdout. From 1dd14da0c22d8f2c2cc7f2d03ff0841f752bc553 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Mon, 13 May 2024 14:07:24 +0200 Subject: [PATCH 163/239] chore: v0.45.0 (#167) --- actix-web/clerk/backend/Cargo.toml | 4 ++-- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/htmx-crud/Cargo.toml | 6 +++--- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 4 ++-- axum/oauth2/Cargo.toml | 6 +++--- axum/postgres/Cargo.toml | 6 +++--- axum/qdrant/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- bevy/hello-world/server/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 6 +++--- loco/hello-world/Cargo.toml | 4 ++-- other/standalone-binary/Cargo.toml | 4 ++-- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/opendal-memory/Cargo.toml | 6 +++--- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 4 ++-- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- salvo/image-rescaler/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 6 +++--- serenity/weather-forecast/Cargo.toml | 4 ++-- thruster/hello-world/Cargo.toml | 4 ++-- tide/hello-world/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 46 files changed, 105 insertions(+), 105 deletions(-) diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml index ce7fa8da..8b09dacd 100644 --- a/actix-web/clerk/backend/Cargo.toml +++ b/actix-web/clerk/backend/Cargo.toml @@ -10,5 +10,5 @@ clerk-rs = "0.2.3" openssl-sys = { version = "0.9.9", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-actix-web = "0.45.0" +shuttle-runtime = "0.45.0" diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index 89633067..cfc8c60a 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.7.1" actix-session = { version = "0.9.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-actix-web = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 5bd8c2b5..fa85b195 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-actix-web = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index cae55216..e19d50f6 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-actix-web = "0.45.0" +shuttle-runtime = "0.45.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.44.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.45.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index 13a58be9..7ca0e783 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-actix-web = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index f0b08edd..6f27dc86 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-actix-web = "0.45.0" +shuttle-runtime = "0.45.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 6a8f0ef9..7d70c629 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-axum = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.28.2" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index 52a1fcfc..726e025f 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -9,9 +9,9 @@ askama_axum = "0.4.0" axum = "0.7.4" serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.44.0" -shuttle-runtime = "0.44.0" -shuttle-shared-db = { version = "0.44.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.45.0" +shuttle-runtime = "0.45.0" +shuttle-shared-db = { version = "0.45.0", features = ["postgres", "sqlx"] } sqlx = "0.7.2" tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index b89b5eea..d53cad31 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-axum = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index d873b1b4..3e93c457 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-axum = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.28.2" diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index cbee9955..705cdd28 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -11,9 +11,9 @@ chrono = { version = "0.4.35", features = ["clock"] } oauth2 = "4.4.1" reqwest = { version = "0.11.18", features = ["json"] } serde = { version = "1.0.183", features = ["derive"] } -shuttle-axum = "0.44.0" -shuttle-runtime = "0.44.0" -shuttle-shared-db = { version = "0.44.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.45.0" +shuttle-runtime = "0.45.0" +shuttle-shared-db = { version = "0.45.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.2", features = ["runtime-tokio-rustls", "macros", "chrono"] } thiserror = "1.0.57" time = "0.3.25" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index ab9580ab..2e7b8dd9 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.44.0" -shuttle-runtime = "0.44.0" -shuttle-shared-db = { version = "0.44.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.45.0" +shuttle-runtime = "0.45.0" +shuttle-shared-db = { version = "0.45.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index 2287daa2..ab2757d2 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.7.0" -shuttle-axum = "0.44.0" -shuttle-qdrant = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-axum = "0.45.0" +shuttle-qdrant = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 65f5bf7c..f6784910 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-axum = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 4ad72d8a..b763fdb7 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.44.0" -shuttle-runtime = "0.44.0" -shuttle-turso = "0.44.0" +shuttle-axum = "0.45.0" +shuttle-runtime = "0.45.0" +shuttle-turso = "0.45.0" libsql = "0.3.1" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index aaf6b359..d08cda8b 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-axum = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/bevy/hello-world/server/Cargo.toml b/bevy/hello-world/server/Cargo.toml index 4d94a590..b8083722 100644 --- a/bevy/hello-world/server/Cargo.toml +++ b/bevy/hello-world/server/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-axum = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 1d7c50f7..0b7f6a98 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1", features = ["derive"] } -shuttle-service = "0.44.0" -shuttle-axum = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-service = "0.45.0" +shuttle-axum = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index ed0083a2..942a68da 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.44.0" +shuttle-runtime = "0.45.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index c5219c01..af048ed8 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -10,7 +10,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-persist = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 73c4edbf..a33adb5e 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,9 +16,9 @@ lettre = "0.11.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.44.0" -shuttle-runtime = "0.44.0" -shuttle-shared-db = { version = "0.44.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.45.0" +shuttle-runtime = "0.45.0" +shuttle-shared-db = { version = "0.45.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.1", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index dc95a9c0..32e2278a 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -13,8 +13,8 @@ async-trait = "0.1.74" axum = "0.7.1" eyre = "*" loco-rs = { version = "0.3.1", default-features = false, features = ["cli"] } -shuttle-axum = "0.44.0" -shuttle-runtime = { version = "0.44.0", default-features = false } +shuttle-axum = "0.45.0" +shuttle-runtime = { version = "0.45.0", default-features = false } serde = "*" serde_json = "*" tokio = "1.33.0" diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 9c66e359..bd168b13 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,6 +15,6 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-axum = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index fd4d684a..edd5c0b5 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "3.0.0" -shuttle-poem = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-poem = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 166a7f26..0188611a 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "3.0.0" -shuttle-poem = "0.44.0" -shuttle-shared-db = { version = "0.44.0", features = ["mongodb"] } -shuttle-runtime = "0.44.0" +shuttle-poem = "0.45.0" +shuttle-shared-db = { version = "0.45.0", features = ["mongodb"] } +shuttle-runtime = "0.45.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index a19f6373..c9878e18 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.6.1" -shuttle-runtime = "0.44.0" +shuttle-runtime = "0.45.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity -shuttle-serenity = "0.44.0" +shuttle-serenity = "0.45.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 1a38b845..ecd2682c 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" rocket_dyn_templates = { version = "0.1.0", features = ["handlebars"] } -shuttle-rocket = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-rocket = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 3433498a..3c77e139 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-rocket = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 20f01bd7..28eb7518 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-rocket = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.26.0" diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index 8c4df0e9..65d37e77 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -4,10 +4,10 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.44.0" -shuttle-opendal = "0.44.0" +shuttle-runtime = "0.45.0" +shuttle-opendal = "0.45.0" tokio = "1.26.0" -shuttle-rocket = "0.44.0" +shuttle-rocket = "0.45.0" opendal = "0.45.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 2e0c336e..642115cd 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.44.0" -shuttle-rocket = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-persist = "0.45.0" +shuttle-rocket = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 91eabf56..b722f395 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.44.0" -shuttle-runtime = "0.44.0" -shuttle-shared-db = { version = "0.44.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.45.0" +shuttle-runtime = "0.45.0" +shuttle-shared-db = { version = "0.45.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 27e75cd7..b3b3cee2 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-rocket = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index 50708946..fc954af3 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-rocket = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 37fd1d85..bc92f07e 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" nanoid = "0.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.44.0" -shuttle-runtime = "0.44.0" -shuttle-shared-db = { version = "0.44.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.45.0" +shuttle-runtime = "0.45.0" +shuttle-shared-db = { version = "0.45.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index f64890ee..6b7759df 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-rocket = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 77b2a976..002dfaa9 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] salvo = "0.63.0" -shuttle-salvo = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-salvo = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml index e173d351..33c30a7d 100644 --- a/salvo/image-rescaler/Cargo.toml +++ b/salvo/image-rescaler/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] image = "0.24.8" salvo = "0.63.0" -shuttle-salvo = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-salvo = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index b18fac23..b78ee5bc 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.44.0" -shuttle-serenity = "0.44.0" +shuttle-runtime = "0.45.0" +shuttle-serenity = "0.45.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 6d33d546..964583c7 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.44.0" -shuttle-serenity = "0.44.0" -shuttle-shared-db = { version = "0.44.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.45.0" +shuttle-serenity = "0.45.0" +shuttle-shared-db = { version = "0.45.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/weather-forecast/Cargo.toml b/serenity/weather-forecast/Cargo.toml index 4218fd92..c1f593e1 100644 --- a/serenity/weather-forecast/Cargo.toml +++ b/serenity/weather-forecast/Cargo.toml @@ -8,7 +8,7 @@ anyhow = "1.0.66" reqwest = { version = "0.11.24", features = ["json"] } serde = "1.0.197" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.44.0" -shuttle-serenity = "0.44.0" +shuttle-runtime = "0.45.0" +shuttle-serenity = "0.45.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 36f20d9d..0350cd1d 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-thruster = "0.45.0" +shuttle-runtime = "0.45.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 77b2dcb4..5d457d86 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.44.0" -shuttle-runtime = "0.44.0" +shuttle-tide = "0.45.0" +shuttle-runtime = "0.45.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index b142eeae..dd7ad36a 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.44.0" -shuttle-tower = "0.44.0" +shuttle-runtime = "0.45.0" +shuttle-tower = "0.45.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 7a566f7f..55806bfb 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.44.0" +shuttle-actix-web = "0.45.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.44.0", default-features = false } +shuttle-runtime = { version = "0.45.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 63b3a3c3..2cc9819e 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.44.0" -shuttle-warp = "0.44.0" +shuttle-runtime = "0.45.0" +shuttle-warp = "0.45.0" tokio = "1.26.0" warp = "0.3.3" From 9c3c4f152960687e1719b7938e81cd2ca6148ecb Mon Sep 17 00:00:00 2001 From: Chris Addy Date: Fri, 31 May 2024 02:02:58 -0400 Subject: [PATCH 164/239] Update templates.toml fix typo --- templates.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates.toml b/templates.toml index d0a25e52..855c7943 100644 --- a/templates.toml +++ b/templates.toml @@ -320,7 +320,7 @@ use_cases = ["Discord bot"] tags = ["serenity"] [templates.shuttle-cron] -title = "Shutte custom Cron service" +title = "Shuttle custom Cron service" description = "Schedule tasks on a cron schedule with apalis" path = "shuttle-cron" use_cases = ["Cron jobs", "Storage"] From e8588a6a82836252f26778331ae8fbb8743ee033 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Thu, 13 Jun 2024 09:49:35 +0200 Subject: [PATCH 165/239] feat: feature flag example (#171) --- other/feature-flags/Cargo.toml | 17 +++++++++++++++++ other/feature-flags/src/main.rs | 18 ++++++++++++++++++ templates.toml | 7 +++++++ 3 files changed, 42 insertions(+) create mode 100644 other/feature-flags/Cargo.toml create mode 100644 other/feature-flags/src/main.rs diff --git a/other/feature-flags/Cargo.toml b/other/feature-flags/Cargo.toml new file mode 100644 index 00000000..1907c5ae --- /dev/null +++ b/other/feature-flags/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "shuttle-feature-flag" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +axum = "0.7.3" +shuttle-axum = "0.45.0" +shuttle-runtime = "0.45.0" + +[features] +# Shuttle will disable default features and enable the feature "shuttle" if it exists. +default = ["foo"] +shuttle = ["bar"] +foo = [] +bar = [] diff --git a/other/feature-flags/src/main.rs b/other/feature-flags/src/main.rs new file mode 100644 index 00000000..6acb911b --- /dev/null +++ b/other/feature-flags/src/main.rs @@ -0,0 +1,18 @@ +use axum::{routing::get, Router}; + +#[cfg(not(feature = "shuttle"))] +async fn hello() -> &'static str { + "Hello, world!" +} + +#[cfg(feature = "shuttle")] +async fn hello() -> &'static str { + "Hello, Shuttle!" +} + +#[shuttle_runtime::main] +async fn main() -> shuttle_axum::ShuttleAxum { + let router = Router::new().route("/", get(hello)); + + Ok(router.into()) +} diff --git a/templates.toml b/templates.toml index 855c7943..b6c4d95b 100644 --- a/templates.toml +++ b/templates.toml @@ -371,6 +371,13 @@ path = "custom-resource/pdo" use_cases = [] tags = ["diy"] +[examples.feature-flags] +title = "Shuttle feature flag" +description = "How to use cargo feature flags on Shuttle" +path = "other/feature-flags" +use_cases = [] +tags = ["diy", "axum"] + [examples.standalone-binary] title = "Standalone binary" description = "How to run an app both with Shuttle and standalone" From 03845273d9907bf37af309416b990d46734633f0 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Thu, 13 Jun 2024 10:49:42 +0200 Subject: [PATCH 166/239] chore: 0.46.0 --- actix-web/clerk/backend/Cargo.toml | 4 ++-- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/htmx-crud/Cargo.toml | 6 +++--- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 4 ++-- axum/oauth2/Cargo.toml | 6 +++--- axum/postgres/Cargo.toml | 6 +++--- axum/qdrant/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- bevy/hello-world/server/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 6 +++--- loco/hello-world/Cargo.toml | 4 ++-- other/feature-flags/Cargo.toml | 4 ++-- other/standalone-binary/Cargo.toml | 4 ++-- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/opendal-memory/Cargo.toml | 8 ++++---- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 4 ++-- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- salvo/image-rescaler/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 6 +++--- serenity/weather-forecast/Cargo.toml | 4 ++-- thruster/hello-world/Cargo.toml | 4 ++-- tide/hello-world/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 47 files changed, 108 insertions(+), 108 deletions(-) diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml index 8b09dacd..045f76b2 100644 --- a/actix-web/clerk/backend/Cargo.toml +++ b/actix-web/clerk/backend/Cargo.toml @@ -10,5 +10,5 @@ clerk-rs = "0.2.3" openssl-sys = { version = "0.9.9", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-actix-web = "0.46.0" +shuttle-runtime = "0.46.0" diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index cfc8c60a..db7126bb 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.7.1" actix-session = { version = "0.9.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-actix-web = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index fa85b195..6f813d23 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-actix-web = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index e19d50f6..f9f7366b 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-actix-web = "0.46.0" +shuttle-runtime = "0.46.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.45.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.46.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index 7ca0e783..5ff483c1 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-actix-web = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 6f27dc86..6687f21c 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-actix-web = "0.46.0" +shuttle-runtime = "0.46.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 7d70c629..72dd1905 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-axum = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.28.2" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index 726e025f..614dba6d 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -9,9 +9,9 @@ askama_axum = "0.4.0" axum = "0.7.4" serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.45.0" -shuttle-runtime = "0.45.0" -shuttle-shared-db = { version = "0.45.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.46.0" +shuttle-runtime = "0.46.0" +shuttle-shared-db = { version = "0.46.0", features = ["postgres", "sqlx"] } sqlx = "0.7.2" tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index d53cad31..44ea0c84 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-axum = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index 3e93c457..ffe76973 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-axum = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.28.2" diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index 705cdd28..9a8f7ca1 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -11,9 +11,9 @@ chrono = { version = "0.4.35", features = ["clock"] } oauth2 = "4.4.1" reqwest = { version = "0.11.18", features = ["json"] } serde = { version = "1.0.183", features = ["derive"] } -shuttle-axum = "0.45.0" -shuttle-runtime = "0.45.0" -shuttle-shared-db = { version = "0.45.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.46.0" +shuttle-runtime = "0.46.0" +shuttle-shared-db = { version = "0.46.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.2", features = ["runtime-tokio-rustls", "macros", "chrono"] } thiserror = "1.0.57" time = "0.3.25" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 2e7b8dd9..cb40d10b 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.45.0" -shuttle-runtime = "0.45.0" -shuttle-shared-db = { version = "0.45.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.46.0" +shuttle-runtime = "0.46.0" +shuttle-shared-db = { version = "0.46.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index ab2757d2..66ca1817 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.7.0" -shuttle-axum = "0.45.0" -shuttle-qdrant = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-axum = "0.46.0" +shuttle-qdrant = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index f6784910..af622437 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-axum = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index b763fdb7..8073b885 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.45.0" -shuttle-runtime = "0.45.0" -shuttle-turso = "0.45.0" +shuttle-axum = "0.46.0" +shuttle-runtime = "0.46.0" +shuttle-turso = "0.46.0" libsql = "0.3.1" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index d08cda8b..423386a1 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-axum = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/bevy/hello-world/server/Cargo.toml b/bevy/hello-world/server/Cargo.toml index b8083722..005c7253 100644 --- a/bevy/hello-world/server/Cargo.toml +++ b/bevy/hello-world/server/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-axum = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 0b7f6a98..48f228f3 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1", features = ["derive"] } -shuttle-service = "0.45.0" -shuttle-axum = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-service = "0.46.0" +shuttle-axum = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 942a68da..90fa0961 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.45.0" +shuttle-runtime = "0.46.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index af048ed8..c6d554c3 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -10,7 +10,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-persist = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index a33adb5e..6d57284b 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,9 +16,9 @@ lettre = "0.11.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.45.0" -shuttle-runtime = "0.45.0" -shuttle-shared-db = { version = "0.45.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.46.0" +shuttle-runtime = "0.46.0" +shuttle-shared-db = { version = "0.46.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.1", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index 32e2278a..fecbd3a5 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -13,8 +13,8 @@ async-trait = "0.1.74" axum = "0.7.1" eyre = "*" loco-rs = { version = "0.3.1", default-features = false, features = ["cli"] } -shuttle-axum = "0.45.0" -shuttle-runtime = { version = "0.45.0", default-features = false } +shuttle-axum = "0.46.0" +shuttle-runtime = { version = "0.46.0", default-features = false } serde = "*" serde_json = "*" tokio = "1.33.0" diff --git a/other/feature-flags/Cargo.toml b/other/feature-flags/Cargo.toml index 1907c5ae..42a6f2f2 100644 --- a/other/feature-flags/Cargo.toml +++ b/other/feature-flags/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-axum = "0.46.0" +shuttle-runtime = "0.46.0" [features] # Shuttle will disable default features and enable the feature "shuttle" if it exists. diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index bd168b13..9f4e7924 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,6 +15,6 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-axum = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index edd5c0b5..7b2cccbd 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "3.0.0" -shuttle-poem = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-poem = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 0188611a..6eda9f90 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "3.0.0" -shuttle-poem = "0.45.0" -shuttle-shared-db = { version = "0.45.0", features = ["mongodb"] } -shuttle-runtime = "0.45.0" +shuttle-poem = "0.46.0" +shuttle-shared-db = { version = "0.46.0", features = ["mongodb"] } +shuttle-runtime = "0.46.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index c9878e18..7012935c 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.6.1" -shuttle-runtime = "0.45.0" +shuttle-runtime = "0.46.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity -shuttle-serenity = "0.45.0" +shuttle-serenity = "0.46.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index ecd2682c..de1c0afa 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" rocket_dyn_templates = { version = "0.1.0", features = ["handlebars"] } -shuttle-rocket = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-rocket = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 3c77e139..24978886 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-rocket = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 28eb7518..5f3eff6a 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-rocket = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.26.0" diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index 65d37e77..63c31300 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -4,10 +4,10 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.45.0" -shuttle-opendal = "0.45.0" +shuttle-runtime = "0.46.0" +shuttle-opendal = "0.46.0" tokio = "1.26.0" -shuttle-rocket = "0.45.0" -opendal = "0.45.0" +shuttle-rocket = "0.46.0" +opendal = "0.46.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 642115cd..3c68157c 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.45.0" -shuttle-rocket = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-persist = "0.46.0" +shuttle-rocket = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index b722f395..04b464f4 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.45.0" -shuttle-runtime = "0.45.0" -shuttle-shared-db = { version = "0.45.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.46.0" +shuttle-runtime = "0.46.0" +shuttle-shared-db = { version = "0.46.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index b3b3cee2..f17044c4 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-rocket = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index fc954af3..c74b1f92 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-rocket = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index bc92f07e..1c3c2133 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" nanoid = "0.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.45.0" -shuttle-runtime = "0.45.0" -shuttle-shared-db = { version = "0.45.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.46.0" +shuttle-runtime = "0.46.0" +shuttle-shared-db = { version = "0.46.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 6b7759df..0653e35e 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-rocket = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 002dfaa9..6385e521 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] salvo = "0.63.0" -shuttle-salvo = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-salvo = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml index 33c30a7d..5b106428 100644 --- a/salvo/image-rescaler/Cargo.toml +++ b/salvo/image-rescaler/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] image = "0.24.8" salvo = "0.63.0" -shuttle-salvo = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-salvo = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index b78ee5bc..c1bf1e95 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.45.0" -shuttle-serenity = "0.45.0" +shuttle-runtime = "0.46.0" +shuttle-serenity = "0.46.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 964583c7..fd370dec 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.45.0" -shuttle-serenity = "0.45.0" -shuttle-shared-db = { version = "0.45.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.46.0" +shuttle-serenity = "0.46.0" +shuttle-shared-db = { version = "0.46.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/weather-forecast/Cargo.toml b/serenity/weather-forecast/Cargo.toml index c1f593e1..8bfed6c4 100644 --- a/serenity/weather-forecast/Cargo.toml +++ b/serenity/weather-forecast/Cargo.toml @@ -8,7 +8,7 @@ anyhow = "1.0.66" reqwest = { version = "0.11.24", features = ["json"] } serde = "1.0.197" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.45.0" -shuttle-serenity = "0.45.0" +shuttle-runtime = "0.46.0" +shuttle-serenity = "0.46.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 0350cd1d..c3c0d5a0 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-thruster = "0.46.0" +shuttle-runtime = "0.46.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 5d457d86..038eaf08 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.45.0" -shuttle-runtime = "0.45.0" +shuttle-tide = "0.46.0" +shuttle-runtime = "0.46.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index dd7ad36a..197242b1 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.45.0" -shuttle-tower = "0.45.0" +shuttle-runtime = "0.46.0" +shuttle-tower = "0.46.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 55806bfb..aa7824e5 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.45.0" +shuttle-actix-web = "0.46.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.45.0", default-features = false } +shuttle-runtime = { version = "0.46.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 2cc9819e..8acdce55 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.45.0" -shuttle-warp = "0.45.0" +shuttle-runtime = "0.46.0" +shuttle-warp = "0.46.0" tokio = "1.26.0" warp = "0.3.3" From 574312509e3159f601d69e9ff032a1b958d95852 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Thu, 13 Jun 2024 13:35:50 +0200 Subject: [PATCH 167/239] fix: opendal version (#173) --- rocket/opendal-memory/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index 63c31300..760d07e2 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -8,6 +8,6 @@ shuttle-runtime = "0.46.0" shuttle-opendal = "0.46.0" tokio = "1.26.0" shuttle-rocket = "0.46.0" -opendal = "0.46.0" +opendal = "0.45" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } From 613f54dd422d37757b9fa096112bfeb479d136bc Mon Sep 17 00:00:00 2001 From: Samuel Bruin Date: Mon, 8 Jul 2024 20:20:42 +0200 Subject: [PATCH 168/239] Add shell true to turbowatch in `fullstack-templates/saas` --- fullstack-templates/saas/turbowatch.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/fullstack-templates/saas/turbowatch.ts b/fullstack-templates/saas/turbowatch.ts index 34eb6123..4b335926 100644 --- a/fullstack-templates/saas/turbowatch.ts +++ b/fullstack-templates/saas/turbowatch.ts @@ -15,6 +15,7 @@ function executeCommand(command: string | string[], abortSignal?: AbortSignal): process = spawn(cmd, args, { cwd: __dirname, stdio: 'inherit', + shell: true, }); // When the process exits, resolve or reject the promise From 5576692fcf593f2530bb12bdb5718948b977f8cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Mon, 22 Jul 2024 17:19:38 +0200 Subject: [PATCH 169/239] chore: upgrade qdrant to 1.10.1 (#177) --- axum/qdrant/Cargo.toml | 2 +- axum/qdrant/src/main.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index 66ca1817..5c70e9ad 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.3" -qdrant-client = "1.7.0" +qdrant-client = "1.10.1" shuttle-axum = "0.46.0" shuttle-qdrant = "0.46.0" shuttle-runtime = "0.46.0" diff --git a/axum/qdrant/src/main.rs b/axum/qdrant/src/main.rs index 924cef11..5359b30d 100644 --- a/axum/qdrant/src/main.rs +++ b/axum/qdrant/src/main.rs @@ -1,9 +1,9 @@ use axum::{extract::State, routing::get, Router}; -use qdrant_client::prelude::*; +use qdrant_client::Qdrant; use std::sync::Arc; struct AppState { - qdrant: QdrantClient, + qdrant: Qdrant, } async fn list_collections(State(state): State>) -> String { @@ -13,7 +13,7 @@ async fn list_collections(State(state): State>) -> String { #[shuttle_runtime::main] async fn main( #[shuttle_qdrant::Qdrant(cloud_url = "{secrets.CLOUD_URL}", api_key = "{secrets.API_KEY}")] - qdrant: QdrantClient, + qdrant: Qdrant, ) -> shuttle_axum::ShuttleAxum { let state = Arc::new(AppState { qdrant }); From 0d0693d4622c0d658f69aa5762fe61f775ed1520 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Mon, 22 Jul 2024 18:09:35 +0200 Subject: [PATCH 170/239] chore: 0.47.0 (#178) --- actix-web/clerk/backend/Cargo.toml | 4 ++-- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/htmx-crud/Cargo.toml | 6 +++--- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 4 ++-- axum/oauth2/Cargo.toml | 6 +++--- axum/postgres/Cargo.toml | 6 +++--- axum/qdrant/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- bevy/hello-world/server/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 6 +++--- loco/hello-world/Cargo.toml | 4 ++-- other/feature-flags/Cargo.toml | 4 ++-- other/standalone-binary/Cargo.toml | 4 ++-- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/opendal-memory/Cargo.toml | 6 +++--- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 4 ++-- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- salvo/image-rescaler/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 6 +++--- serenity/weather-forecast/Cargo.toml | 4 ++-- thruster/hello-world/Cargo.toml | 4 ++-- tide/hello-world/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 47 files changed, 107 insertions(+), 107 deletions(-) diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml index 045f76b2..66d16ba0 100644 --- a/actix-web/clerk/backend/Cargo.toml +++ b/actix-web/clerk/backend/Cargo.toml @@ -10,5 +10,5 @@ clerk-rs = "0.2.3" openssl-sys = { version = "0.9.9", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-actix-web = "0.47.0" +shuttle-runtime = "0.47.0" diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index db7126bb..5b7b4521 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.7.1" actix-session = { version = "0.9.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-actix-web = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 6f813d23..00621904 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-actix-web = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index f9f7366b..d9e59266 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-actix-web = "0.47.0" +shuttle-runtime = "0.47.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.46.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index 5ff483c1..dcbd7416 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-actix-web = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 6687f21c..de871ff6 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-actix-web = "0.47.0" +shuttle-runtime = "0.47.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 72dd1905..5460ee82 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-axum = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.28.2" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index 614dba6d..a0081241 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -9,9 +9,9 @@ askama_axum = "0.4.0" axum = "0.7.4" serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.46.0" -shuttle-runtime = "0.46.0" -shuttle-shared-db = { version = "0.46.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.47.0" +shuttle-runtime = "0.47.0" +shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } sqlx = "0.7.2" tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index 44ea0c84..3fe2929d 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-axum = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index ffe76973..ec054b9a 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-axum = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.28.2" diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index 9a8f7ca1..2fc330c9 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -11,9 +11,9 @@ chrono = { version = "0.4.35", features = ["clock"] } oauth2 = "4.4.1" reqwest = { version = "0.11.18", features = ["json"] } serde = { version = "1.0.183", features = ["derive"] } -shuttle-axum = "0.46.0" -shuttle-runtime = "0.46.0" -shuttle-shared-db = { version = "0.46.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.47.0" +shuttle-runtime = "0.47.0" +shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.2", features = ["runtime-tokio-rustls", "macros", "chrono"] } thiserror = "1.0.57" time = "0.3.25" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index cb40d10b..7b29ed70 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.46.0" -shuttle-runtime = "0.46.0" -shuttle-shared-db = { version = "0.46.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.47.0" +shuttle-runtime = "0.47.0" +shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index 5c70e9ad..acfd58bc 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.10.1" -shuttle-axum = "0.46.0" -shuttle-qdrant = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-axum = "0.47.0" +shuttle-qdrant = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index af622437..0792e5e9 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-axum = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 8073b885..f8f69235 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.46.0" -shuttle-runtime = "0.46.0" -shuttle-turso = "0.46.0" +shuttle-axum = "0.47.0" +shuttle-runtime = "0.47.0" +shuttle-turso = "0.47.0" libsql = "0.3.1" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 423386a1..fcb64f8a 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-axum = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/bevy/hello-world/server/Cargo.toml b/bevy/hello-world/server/Cargo.toml index 005c7253..dc1293f0 100644 --- a/bevy/hello-world/server/Cargo.toml +++ b/bevy/hello-world/server/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-axum = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 48f228f3..dac296dd 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1", features = ["derive"] } -shuttle-service = "0.46.0" -shuttle-axum = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-service = "0.47.0" +shuttle-axum = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 90fa0961..36d95733 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.46.0" +shuttle-runtime = "0.47.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index c6d554c3..60f93159 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -10,7 +10,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-persist = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 6d57284b..c616581d 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,9 +16,9 @@ lettre = "0.11.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.46.0" -shuttle-runtime = "0.46.0" -shuttle-shared-db = { version = "0.46.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.47.0" +shuttle-runtime = "0.47.0" +shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.7.1", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index fecbd3a5..0a649d3a 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -13,8 +13,8 @@ async-trait = "0.1.74" axum = "0.7.1" eyre = "*" loco-rs = { version = "0.3.1", default-features = false, features = ["cli"] } -shuttle-axum = "0.46.0" -shuttle-runtime = { version = "0.46.0", default-features = false } +shuttle-axum = "0.47.0" +shuttle-runtime = { version = "0.47.0", default-features = false } serde = "*" serde_json = "*" tokio = "1.33.0" diff --git a/other/feature-flags/Cargo.toml b/other/feature-flags/Cargo.toml index 42a6f2f2..8dcf269d 100644 --- a/other/feature-flags/Cargo.toml +++ b/other/feature-flags/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-axum = "0.47.0" +shuttle-runtime = "0.47.0" [features] # Shuttle will disable default features and enable the feature "shuttle" if it exists. diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 9f4e7924..f87a900a 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,6 +15,6 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-axum = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 7b2cccbd..f62525fc 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "3.0.0" -shuttle-poem = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-poem = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 6eda9f90..3d0af509 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "3.0.0" -shuttle-poem = "0.46.0" -shuttle-shared-db = { version = "0.46.0", features = ["mongodb"] } -shuttle-runtime = "0.46.0" +shuttle-poem = "0.47.0" +shuttle-shared-db = { version = "0.47.0", features = ["mongodb"] } +shuttle-runtime = "0.47.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 7012935c..338475cd 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.6.1" -shuttle-runtime = "0.46.0" +shuttle-runtime = "0.47.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity -shuttle-serenity = "0.46.0" +shuttle-serenity = "0.47.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index de1c0afa..aa2d17de 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" rocket_dyn_templates = { version = "0.1.0", features = ["handlebars"] } -shuttle-rocket = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-rocket = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 24978886..466a2b0c 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-rocket = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 5f3eff6a..730d9a13 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-rocket = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.26.0" diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index 760d07e2..8631c824 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -4,10 +4,10 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.46.0" -shuttle-opendal = "0.46.0" +shuttle-runtime = "0.47.0" +shuttle-opendal = "0.47.0" tokio = "1.26.0" -shuttle-rocket = "0.46.0" +shuttle-rocket = "0.47.0" opendal = "0.45" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index 3c68157c..e558278c 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.46.0" -shuttle-rocket = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-persist = "0.47.0" +shuttle-rocket = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 04b464f4..7391e82b 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.46.0" -shuttle-runtime = "0.46.0" -shuttle-shared-db = { version = "0.46.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.47.0" +shuttle-runtime = "0.47.0" +shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index f17044c4..c0a72dd4 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-rocket = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index c74b1f92..7e07e905 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-rocket = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 1c3c2133..e572b453 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" nanoid = "0.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.46.0" -shuttle-runtime = "0.46.0" -shuttle-shared-db = { version = "0.46.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.47.0" +shuttle-runtime = "0.47.0" +shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 0653e35e..da36d440 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-rocket = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 6385e521..225021f1 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] salvo = "0.63.0" -shuttle-salvo = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-salvo = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml index 5b106428..2adffab0 100644 --- a/salvo/image-rescaler/Cargo.toml +++ b/salvo/image-rescaler/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] image = "0.24.8" salvo = "0.63.0" -shuttle-salvo = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-salvo = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index c1bf1e95..197c2cd9 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.46.0" -shuttle-serenity = "0.46.0" +shuttle-runtime = "0.47.0" +shuttle-serenity = "0.47.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index fd370dec..0aecf398 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.46.0" -shuttle-serenity = "0.46.0" -shuttle-shared-db = { version = "0.46.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.47.0" +shuttle-serenity = "0.47.0" +shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } sqlx = "0.7.1" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/weather-forecast/Cargo.toml b/serenity/weather-forecast/Cargo.toml index 8bfed6c4..8651c42b 100644 --- a/serenity/weather-forecast/Cargo.toml +++ b/serenity/weather-forecast/Cargo.toml @@ -8,7 +8,7 @@ anyhow = "1.0.66" reqwest = { version = "0.11.24", features = ["json"] } serde = "1.0.197" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.46.0" -shuttle-serenity = "0.46.0" +shuttle-runtime = "0.47.0" +shuttle-serenity = "0.47.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index c3c0d5a0..c6826e1d 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-thruster = "0.47.0" +shuttle-runtime = "0.47.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 038eaf08..f240d7e1 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.46.0" -shuttle-runtime = "0.46.0" +shuttle-tide = "0.47.0" +shuttle-runtime = "0.47.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 197242b1..d36e6052 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.46.0" -shuttle-tower = "0.46.0" +shuttle-runtime = "0.47.0" +shuttle-tower = "0.47.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index aa7824e5..1dd4af4f 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.46.0" +shuttle-actix-web = "0.47.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.46.0", default-features = false } +shuttle-runtime = { version = "0.47.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 8acdce55..45a5114b 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.46.0" -shuttle-warp = "0.46.0" +shuttle-runtime = "0.47.0" +shuttle-warp = "0.47.0" tokio = "1.26.0" warp = "0.3.3" From 3480af7269197c67ff9e14b373282dbc4072b355 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Mon, 22 Jul 2024 19:52:53 +0200 Subject: [PATCH 171/239] feat: openai example (#180) * feat: openai example * add template * readme --- axum/openai/Cargo.toml | 13 ++++++++++ axum/openai/README.md | 7 ++++++ axum/openai/Secrets.toml | 1 + axum/openai/src/main.rs | 53 ++++++++++++++++++++++++++++++++++++++++ templates.toml | 8 ++++++ 5 files changed, 82 insertions(+) create mode 100644 axum/openai/Cargo.toml create mode 100644 axum/openai/README.md create mode 100644 axum/openai/Secrets.toml create mode 100644 axum/openai/src/main.rs diff --git a/axum/openai/Cargo.toml b/axum/openai/Cargo.toml new file mode 100644 index 00000000..8147f477 --- /dev/null +++ b/axum/openai/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "shuttle-axum-openai" +version = "0.1.0" +edition = "2021" + +[dependencies] +async-openai = "0.23.0" +axum = "0.7.3" +serde_json = "1" +shuttle-axum = "0.47.0" +shuttle-openai = "0.47.0" +shuttle-runtime = "0.47.0" +tokio = "1.26.0" diff --git a/axum/openai/README.md b/axum/openai/README.md new file mode 100644 index 00000000..776fbbdb --- /dev/null +++ b/axum/openai/README.md @@ -0,0 +1,7 @@ +A simple endpoint that sends a chat message to ChatGPT and returns the response. + +Set your OpenAI API key in `Secrets.toml`, then try it on a local run with: + +```sh +curl http://localhost:8000 -H 'content-type: application/json' --data '{"message":"What is shuttle.rs?"}' +``` diff --git a/axum/openai/Secrets.toml b/axum/openai/Secrets.toml new file mode 100644 index 00000000..0dcefec8 --- /dev/null +++ b/axum/openai/Secrets.toml @@ -0,0 +1 @@ +OPENAI_API_KEY = 'your_api_key' diff --git a/axum/openai/src/main.rs b/axum/openai/src/main.rs new file mode 100644 index 00000000..1d6c794a --- /dev/null +++ b/axum/openai/src/main.rs @@ -0,0 +1,53 @@ +use std::sync::Arc; + +use async_openai::{ + config::OpenAIConfig, + types::{ + ChatCompletionRequestMessage, ChatCompletionRequestUserMessageArgs, + CreateChatCompletionRequestArgs, + }, + Client, +}; +use axum::{extract::State, routing::post, Json, Router}; +use serde_json::{json, Value}; + +struct AppState { + openai: Client, +} + +async fn chat(State(state): State>, Json(v): Json) -> Result, ()> { + let user_msg: ChatCompletionRequestMessage = ChatCompletionRequestUserMessageArgs::default() + .content(v["message"].as_str().unwrap()) + .build() + .unwrap() + .into(); + let req = CreateChatCompletionRequestArgs::default() + .model("gpt-4o-mini") + .messages(vec![user_msg]) + .n(1) + .build() + .unwrap(); + let res = state.openai.chat().create(req).await.unwrap(); + let reply = res + .choices + .first() + .unwrap() + .message + .content + .as_ref() + .unwrap() + .to_owned(); + + Ok(Json(json!({ "response": reply }))) +} + +#[shuttle_runtime::main] +async fn main( + #[shuttle_openai::OpenAI(api_key = "{secrets.OPENAI_API_KEY}")] openai: Client, +) -> shuttle_axum::ShuttleAxum { + let state = Arc::new(AppState { openai }); + + let router = Router::new().route("/", post(chat)).with_state(state); + + Ok(router.into()) +} diff --git a/templates.toml b/templates.toml index b6c4d95b..7497d2a0 100644 --- a/templates.toml +++ b/templates.toml @@ -24,6 +24,7 @@ qdrant = "https://avatars.githubusercontent.com/u/73504361?v=4" nextjs = "https://assets.vercel.com/image/upload/v1662130559/nextjs/Icon_light_background.png" mongodb = "https://avatars.githubusercontent.com/u/45120?v=4" opendal = "https://avatars.githubusercontent.com/u/47359?v=4" +openai = "https://avatars.githubusercontent.com/u/14957082?v=4" # fallback shuttle = "https://avatars.githubusercontent.com/u/54710151?v=4" @@ -200,6 +201,13 @@ path = "axum/oauth2" use_cases = ["Web app", "Authentication"] tags = ["axum", "oauth"] +[templates.axum-openai] +title = "OpenAI ChatGPT chat" +description = "Connect your app to OpenAI ChatGPT" +path = "axum/openai" +use_cases = ["Web app", "AI"] +tags = ["openai", "axum"] + [templates.axum-postgres] title = "Postgres" description = "Todo list with a Postgres database" From 9cc7a8e0097d822f3bfde6bfbb1366fee2858283 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Thu, 15 Aug 2024 04:17:52 -0700 Subject: [PATCH 172/239] bump sqlx to 0.8 in database examples (#181) * improvement: bump sqlx to 0.8 in database examples * feat: bump more version * fix * fix: downgrade shuttle-cron runtime for sqlx compat --------- Co-authored-by: jonaro00 <54029719+jonaro00@users.noreply.github.com> --- actix-web/postgres/Cargo.toml | 2 +- axum/htmx-crud/Cargo.toml | 2 +- axum/oauth2/Cargo.toml | 2 +- axum/postgres/Cargo.toml | 2 +- fullstack-templates/saas/backend/Cargo.toml | 2 +- rocket/postgres/Cargo.toml | 2 +- rocket/url-shortener/Cargo.toml | 2 +- serenity/postgres/Cargo.toml | 2 +- shuttle-cron/Cargo.toml | 6 +++--- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index d9e59266..345dd72d 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -9,5 +9,5 @@ shuttle-actix-web = "0.47.0" shuttle-runtime = "0.47.0" serde = "1.0.148" shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } -sqlx = "0.7.1" +sqlx = "0.8.0" tokio = "1.26.0" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index a0081241..f286c053 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -12,6 +12,6 @@ serde_json = "1.0.107" shuttle-axum = "0.47.0" shuttle-runtime = "0.47.0" shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } -sqlx = "0.7.2" +sqlx = "0.8.0" tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index 2fc330c9..329c7894 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -14,7 +14,7 @@ serde = { version = "1.0.183", features = ["derive"] } shuttle-axum = "0.47.0" shuttle-runtime = "0.47.0" shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } -sqlx = { version = "0.7.2", features = ["runtime-tokio-rustls", "macros", "chrono"] } +sqlx = { version = "0.8.0", features = ["macros", "chrono"] } thiserror = "1.0.57" time = "0.3.25" tokio = "1.28.2" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 7b29ed70..7a3d49f3 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -9,5 +9,5 @@ serde = { version = "1.0.188", features = ["derive"] } shuttle-axum = "0.47.0" shuttle-runtime = "0.47.0" shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } -sqlx = "0.7.1" +sqlx = "0.8.0" tokio = "1.28.2" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index c616581d..f370fb34 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -19,7 +19,7 @@ serde = { version = "1.0.160", features = ["derive"] } shuttle-axum = "0.47.0" shuttle-runtime = "0.47.0" shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } -sqlx = { version = "0.7.1", features = ["time"] } +sqlx = { version = "0.8.0", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" tower = "0.4.13" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 7391e82b..5d854a54 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -9,5 +9,5 @@ serde = "1.0.148" shuttle-rocket = "0.47.0" shuttle-runtime = "0.47.0" shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } -sqlx = "0.7.1" +sqlx = "0.8.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index e572b453..c879d13b 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -10,6 +10,6 @@ serde = "1.0.148" shuttle-rocket = "0.47.0" shuttle-runtime = "0.47.0" shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } -sqlx = "0.7.1" +sqlx = "0.8.0" tokio = "1.26.0" url = "2.3.1" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 0aecf398..0b82ee69 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -10,6 +10,6 @@ serenity = { version = "0.12.0", default-features = false, features = ["client", shuttle-runtime = "0.47.0" shuttle-serenity = "0.47.0" shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } -sqlx = "0.7.1" +sqlx = "0.8.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/shuttle-cron/Cargo.toml b/shuttle-cron/Cargo.toml index 973652ab..d6375298 100644 --- a/shuttle-cron/Cargo.toml +++ b/shuttle-cron/Cargo.toml @@ -8,8 +8,8 @@ publish = false apalis = { version = "0.4.9", features = ["cron", "postgres", "extensions", "retry"] } chrono = { version = "0.4.32", features = ["clock", "serde"] } serde = { version = "1.0.195", features = ["derive"] } -shuttle-runtime = "0.37.0" -shuttle-shared-db = { version = "0.37.0", features = ["postgres"] } -sqlx = { version = "0.7.3", features = ["runtime-tokio-native-tls", "postgres"] } +shuttle-runtime = "0.46.0" +shuttle-shared-db = { version = "0.46.0", features = ["postgres"] } +sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1" tower = { version = "0.4.13" } From cda84a7ff31ac24da0ac39910c4521c9a6653deb Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 4 Sep 2024 11:32:16 +0200 Subject: [PATCH 173/239] chore: bump sqlx to 0.8.2 --- actix-web/postgres/Cargo.toml | 2 +- axum/htmx-crud/Cargo.toml | 2 +- axum/oauth2/Cargo.toml | 2 +- axum/postgres/Cargo.toml | 2 +- fullstack-templates/saas/backend/Cargo.toml | 2 +- rocket/postgres/Cargo.toml | 2 +- rocket/url-shortener/Cargo.toml | 2 +- serenity/postgres/Cargo.toml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 345dd72d..b5272da8 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -9,5 +9,5 @@ shuttle-actix-web = "0.47.0" shuttle-runtime = "0.47.0" serde = "1.0.148" shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } -sqlx = "0.8.0" +sqlx = "0.8.2" tokio = "1.26.0" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index f286c053..4e27fc1d 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -12,6 +12,6 @@ serde_json = "1.0.107" shuttle-axum = "0.47.0" shuttle-runtime = "0.47.0" shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } -sqlx = "0.8.0" +sqlx = "0.8.2" tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index 329c7894..b2c690fe 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -14,7 +14,7 @@ serde = { version = "1.0.183", features = ["derive"] } shuttle-axum = "0.47.0" shuttle-runtime = "0.47.0" shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } -sqlx = { version = "0.8.0", features = ["macros", "chrono"] } +sqlx = { version = "0.8.2", features = ["macros", "chrono"] } thiserror = "1.0.57" time = "0.3.25" tokio = "1.28.2" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 7a3d49f3..329e6599 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -9,5 +9,5 @@ serde = { version = "1.0.188", features = ["derive"] } shuttle-axum = "0.47.0" shuttle-runtime = "0.47.0" shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } -sqlx = "0.8.0" +sqlx = "0.8.2" tokio = "1.28.2" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index f370fb34..7f83ec72 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -19,7 +19,7 @@ serde = { version = "1.0.160", features = ["derive"] } shuttle-axum = "0.47.0" shuttle-runtime = "0.47.0" shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } -sqlx = { version = "0.8.0", features = ["time"] } +sqlx = { version = "0.8.2", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" tower = "0.4.13" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 5d854a54..9f663735 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -9,5 +9,5 @@ serde = "1.0.148" shuttle-rocket = "0.47.0" shuttle-runtime = "0.47.0" shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } -sqlx = "0.8.0" +sqlx = "0.8.2" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index c879d13b..826d9f86 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -10,6 +10,6 @@ serde = "1.0.148" shuttle-rocket = "0.47.0" shuttle-runtime = "0.47.0" shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } -sqlx = "0.8.0" +sqlx = "0.8.2" tokio = "1.26.0" url = "2.3.1" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 0b82ee69..89c3b2e1 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -10,6 +10,6 @@ serenity = { version = "0.12.0", default-features = false, features = ["client", shuttle-runtime = "0.47.0" shuttle-serenity = "0.47.0" shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } -sqlx = "0.8.0" +sqlx = "0.8.2" tokio = "1.26.0" tracing = "0.1.37" From 3ec07434119ad8675397df0a21dd2ba5f18427f8 Mon Sep 17 00:00:00 2001 From: Elad Kaplan Date: Thu, 19 Sep 2024 16:07:49 +0300 Subject: [PATCH 174/239] bump loco version to 0.9.0 (#186) * bump loco version to 0.9.0 * fix: clippy --------- Co-authored-by: jonaro00 <54029719+jonaro00@users.noreply.github.com> --- .../saas/backend/src/dashboard.rs | 3 +-- loco/hello-world/Cargo.toml | 5 ++--- loco/hello-world/README.md | 19 ++++++++++++++----- loco/hello-world/src/bin/main.rs | 2 +- loco/hello-world/src/controllers/home.rs | 2 +- 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/fullstack-templates/saas/backend/src/dashboard.rs b/fullstack-templates/saas/backend/src/dashboard.rs index 5430334f..ab927568 100644 --- a/fullstack-templates/saas/backend/src/dashboard.rs +++ b/fullstack-templates/saas/backend/src/dashboard.rs @@ -1,6 +1,5 @@ use axum::{extract::State, http::StatusCode, response::IntoResponse, Json}; use serde::{Deserialize, Serialize}; -// use time::Date; use crate::AppState; @@ -50,7 +49,7 @@ pub async fn get_dashboard_data( FROM deals WHERE owner_id = (SELECT id FROM users WHERE email = $1)", ) - .bind(&req.email.to_string()) + .bind(&req.email) .fetch_one(&state.postgres) .await { diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index 0a649d3a..1d5ae2e3 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -11,8 +11,7 @@ edition = "2021" async-trait = "0.1.74" axum = "0.7.1" -eyre = "*" -loco-rs = { version = "0.3.1", default-features = false, features = ["cli"] } +loco-rs = { version = "0.9.0", default-features = false, features = ["cli"] } shuttle-axum = "0.47.0" shuttle-runtime = { version = "0.47.0", default-features = false } serde = "*" @@ -33,7 +32,7 @@ path = "src/bin/shuttle.rs" [dev-dependencies] serial_test = "*" rstest = "*" -loco-rs = { version = "0.3.1", default-features = false, features = [ +loco-rs = { version = "0.9.0", default-features = false, features = [ "testing", "cli", ] } diff --git a/loco/hello-world/README.md b/loco/hello-world/README.md index 9bbcc76f..2a56f692 100644 --- a/loco/hello-world/README.md +++ b/loco/hello-world/README.md @@ -1,11 +1,20 @@ # Shuttle Loco template :train: Welcome to the [Loco](https://loco.rs) Hello World Shuttle Template, designed with a focus on controllers and views (response schema). This minimalistic template comes with several features to kickstart your project: -- **REST API Service without a Database** -- **Workers**: Full-blown background job processing -- **Task**: Ad-hoc functionalities to handle specific aspects of your application -- **Tests**: Testing facility and examples -- And More Loco Features + +### **REST API Service without a Database** + +* **Controllers:** Handle web requests parameters, body, validation, and render a response that is content-aware. We use Axum for the best performance, simplicity, and extensibility. Controllers also allow you to easily build middlewares, which can be used to add logic such as authentication, logging, or error handling before passing requests to the main controller actions. +* **Views:** Loco can integrate with templating engines to generate dynamic HTML content from templates. +* **Background Jobs:** Perform compute or I/O intensive jobs in the background with a Redis backed queue, or with threads. Implementing a worker is as simple as implementing a perform function for the Worker trait. +* **Scheduler:** Simplifies the traditional, often cumbersome crontab system, making it easier and more elegant to schedule tasks or shell scripts. +* **Mailers:** A mailer will deliver emails in the background using the existing loco background worker infrastructure. It will all be seamless for you. +* **Storage:** In Loco Storage, we facilitate working with files through multiple operations. Storage can be in-memory, on disk, or use cloud services such as AWS S3, GCP, and Azure. +* **Cache:** Loco provides an cache layer to improve application performance by storing frequently accessed data. + +So see more Loco features, check out our [documentation website](https://loco.rs/docs/getting-started/tour/). + + ## Quick Start diff --git a/loco/hello-world/src/bin/main.rs b/loco/hello-world/src/bin/main.rs index 236149e2..e35b0305 100644 --- a/loco/hello-world/src/bin/main.rs +++ b/loco/hello-world/src/bin/main.rs @@ -2,6 +2,6 @@ use hello_world::app::App; use loco_rs::cli; #[tokio::main] -async fn main() -> eyre::Result<()> { +async fn main() -> loco_rs::Result<()> { cli::main::().await } diff --git a/loco/hello-world/src/controllers/home.rs b/loco/hello-world/src/controllers/home.rs index 9e6345d3..863b4b9b 100644 --- a/loco/hello-world/src/controllers/home.rs +++ b/loco/hello-world/src/controllers/home.rs @@ -2,7 +2,7 @@ use loco_rs::prelude::*; use crate::views::home::HomeResponse; -async fn current() -> Result> { +async fn current() -> Result { format::json(HomeResponse::new("loco")) } From 3f2b1c4eb02cf594c7bedf78a47576b1e3e63bce Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Fri, 27 Sep 2024 17:02:15 +0200 Subject: [PATCH 175/239] chore: ignore shuttle files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 246d500b..1920cdea 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ target/ Cargo.lock .cargo +.shuttle* From d08ff9dc9fb346b9d3858c98cf5ff9fc9cd62411 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Tue, 1 Oct 2024 12:29:37 +0200 Subject: [PATCH 176/239] chore: 0.48.0 --- actix-web/clerk/backend/Cargo.toml | 4 ++-- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/htmx-crud/Cargo.toml | 6 +++--- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 4 ++-- axum/oauth2/Cargo.toml | 6 +++--- axum/openai/Cargo.toml | 6 +++--- axum/postgres/Cargo.toml | 6 +++--- axum/qdrant/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- bevy/hello-world/server/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 6 +++--- loco/hello-world/Cargo.toml | 4 ++-- other/feature-flags/Cargo.toml | 4 ++-- other/standalone-binary/Cargo.toml | 4 ++-- poem/hello-world/Cargo.toml | 4 ++-- poem/mongodb/Cargo.toml | 6 +++--- poise/hello-world/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/opendal-memory/Cargo.toml | 6 +++--- rocket/persist/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 4 ++-- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- salvo/image-rescaler/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 6 +++--- serenity/weather-forecast/Cargo.toml | 4 ++-- thruster/hello-world/Cargo.toml | 4 ++-- tide/hello-world/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 48 files changed, 110 insertions(+), 110 deletions(-) diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml index 66d16ba0..629bf653 100644 --- a/actix-web/clerk/backend/Cargo.toml +++ b/actix-web/clerk/backend/Cargo.toml @@ -10,5 +10,5 @@ clerk-rs = "0.2.3" openssl-sys = { version = "0.9.9", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-actix-web = "0.48.0" +shuttle-runtime = "0.48.0" diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index 5b7b4521..dcd1e223 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.7.1" actix-session = { version = "0.9.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-actix-web = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 00621904..74821e20 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-actix-web = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index b5272da8..7d543398 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-actix-web = "0.48.0" +shuttle-runtime = "0.48.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.48.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index dcbd7416..8a137d0c 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-actix-web = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index de871ff6..80893824 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-actix-web = "0.48.0" +shuttle-runtime = "0.48.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 5460ee82..7ab2ee6f 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-axum = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.28.2" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index 4e27fc1d..d3ab04dc 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -9,9 +9,9 @@ askama_axum = "0.4.0" axum = "0.7.4" serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.47.0" -shuttle-runtime = "0.47.0" -shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.48.0" +shuttle-runtime = "0.48.0" +shuttle-shared-db = { version = "0.48.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index 3fe2929d..45d184cd 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-axum = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index ec054b9a..c5640c1d 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-axum = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.28.2" diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index b2c690fe..1c986719 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -11,9 +11,9 @@ chrono = { version = "0.4.35", features = ["clock"] } oauth2 = "4.4.1" reqwest = { version = "0.11.18", features = ["json"] } serde = { version = "1.0.183", features = ["derive"] } -shuttle-axum = "0.47.0" -shuttle-runtime = "0.47.0" -shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.48.0" +shuttle-runtime = "0.48.0" +shuttle-shared-db = { version = "0.48.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["macros", "chrono"] } thiserror = "1.0.57" time = "0.3.25" diff --git a/axum/openai/Cargo.toml b/axum/openai/Cargo.toml index 8147f477..8c211847 100644 --- a/axum/openai/Cargo.toml +++ b/axum/openai/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-openai = "0.23.0" axum = "0.7.3" serde_json = "1" -shuttle-axum = "0.47.0" -shuttle-openai = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-axum = "0.48.0" +shuttle-openai = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.26.0" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 329e6599..1987e88d 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.47.0" -shuttle-runtime = "0.47.0" -shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.48.0" +shuttle-runtime = "0.48.0" +shuttle-shared-db = { version = "0.48.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index acfd58bc..4010645c 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.10.1" -shuttle-axum = "0.47.0" -shuttle-qdrant = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-axum = "0.48.0" +shuttle-qdrant = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 0792e5e9..f482f2f3 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-axum = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index f8f69235..2428f1f8 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.47.0" -shuttle-runtime = "0.47.0" -shuttle-turso = "0.47.0" +shuttle-axum = "0.48.0" +shuttle-runtime = "0.48.0" +shuttle-turso = "0.48.0" libsql = "0.3.1" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index fcb64f8a..90a1c2e5 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-axum = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/bevy/hello-world/server/Cargo.toml b/bevy/hello-world/server/Cargo.toml index dc1293f0..b9638d6b 100644 --- a/bevy/hello-world/server/Cargo.toml +++ b/bevy/hello-world/server/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-axum = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index dac296dd..70a67c2c 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1", features = ["derive"] } -shuttle-service = "0.47.0" -shuttle-axum = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-service = "0.48.0" +shuttle-axum = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 36d95733..3e072d69 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.47.0" +shuttle-runtime = "0.48.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index 60f93159..382c094d 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -10,7 +10,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-persist = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 7f83ec72..35703047 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,9 +16,9 @@ lettre = "0.11.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.47.0" -shuttle-runtime = "0.47.0" -shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.48.0" +shuttle-runtime = "0.48.0" +shuttle-shared-db = { version = "0.48.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index 1d5ae2e3..31a33af2 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -12,8 +12,8 @@ edition = "2021" async-trait = "0.1.74" axum = "0.7.1" loco-rs = { version = "0.9.0", default-features = false, features = ["cli"] } -shuttle-axum = "0.47.0" -shuttle-runtime = { version = "0.47.0", default-features = false } +shuttle-axum = "0.48.0" +shuttle-runtime = { version = "0.48.0", default-features = false } serde = "*" serde_json = "*" tokio = "1.33.0" diff --git a/other/feature-flags/Cargo.toml b/other/feature-flags/Cargo.toml index 8dcf269d..5e52ab51 100644 --- a/other/feature-flags/Cargo.toml +++ b/other/feature-flags/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-axum = "0.48.0" +shuttle-runtime = "0.48.0" [features] # Shuttle will disable default features and enable the feature "shuttle" if it exists. diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index f87a900a..3257ad10 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,6 +15,6 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-axum = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index f62525fc..7bbff9bb 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "3.0.0" -shuttle-poem = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-poem = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.26.0" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml index 3d0af509..08577de8 100644 --- a/poem/mongodb/Cargo.toml +++ b/poem/mongodb/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" [dependencies] mongodb = "2.4.0" poem = "3.0.0" -shuttle-poem = "0.47.0" -shuttle-shared-db = { version = "0.47.0", features = ["mongodb"] } -shuttle-runtime = "0.47.0" +shuttle-poem = "0.48.0" +shuttle-shared-db = { version = "0.48.0", features = ["mongodb"] } +shuttle-runtime = "0.48.0" serde = { version = "1.0.148", features = ["derive"] } serde_json = "1.0.89" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 338475cd..53c76214 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.6.1" -shuttle-runtime = "0.47.0" +shuttle-runtime = "0.48.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity -shuttle-serenity = "0.47.0" +shuttle-serenity = "0.48.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index aa2d17de..bfb1e3bb 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" rocket_dyn_templates = { version = "0.1.0", features = ["handlebars"] } -shuttle-rocket = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-rocket = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 466a2b0c..1744d13c 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-rocket = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 730d9a13..8dc7ebae 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-rocket = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.26.0" diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index 8631c824..94cce033 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -4,10 +4,10 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.47.0" -shuttle-opendal = "0.47.0" +shuttle-runtime = "0.48.0" +shuttle-opendal = "0.48.0" tokio = "1.26.0" -shuttle-rocket = "0.47.0" +shuttle-rocket = "0.48.0" opendal = "0.45" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml index e558278c..dc327353 100644 --- a/rocket/persist/Cargo.toml +++ b/rocket/persist/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.47.0" -shuttle-rocket = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-persist = "0.48.0" +shuttle-rocket = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 9f663735..ab880017 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.47.0" -shuttle-runtime = "0.47.0" -shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.48.0" +shuttle-runtime = "0.48.0" +shuttle-shared-db = { version = "0.48.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index c0a72dd4..fc5aa038 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-rocket = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index 7e07e905..841325c4 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-rocket = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 826d9f86..5b582f69 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" nanoid = "0.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.47.0" -shuttle-runtime = "0.47.0" -shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.48.0" +shuttle-runtime = "0.48.0" +shuttle-shared-db = { version = "0.48.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index da36d440..a6bee465 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-rocket = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 225021f1..47346f7a 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] salvo = "0.63.0" -shuttle-salvo = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-salvo = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml index 2adffab0..03c94fc7 100644 --- a/salvo/image-rescaler/Cargo.toml +++ b/salvo/image-rescaler/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] image = "0.24.8" salvo = "0.63.0" -shuttle-salvo = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-salvo = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 197c2cd9..89382cf0 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.47.0" -shuttle-serenity = "0.47.0" +shuttle-runtime = "0.48.0" +shuttle-serenity = "0.48.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 89c3b2e1..a0092c60 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.47.0" -shuttle-serenity = "0.47.0" -shuttle-shared-db = { version = "0.47.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.48.0" +shuttle-serenity = "0.48.0" +shuttle-shared-db = { version = "0.48.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/weather-forecast/Cargo.toml b/serenity/weather-forecast/Cargo.toml index 8651c42b..f6861fd4 100644 --- a/serenity/weather-forecast/Cargo.toml +++ b/serenity/weather-forecast/Cargo.toml @@ -8,7 +8,7 @@ anyhow = "1.0.66" reqwest = { version = "0.11.24", features = ["json"] } serde = "1.0.197" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.47.0" -shuttle-serenity = "0.47.0" +shuttle-runtime = "0.48.0" +shuttle-serenity = "0.48.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index c6826e1d..ad67ec9e 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-thruster = "0.48.0" +shuttle-runtime = "0.48.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index f240d7e1..bad3fbf0 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.47.0" -shuttle-runtime = "0.47.0" +shuttle-tide = "0.48.0" +shuttle-runtime = "0.48.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index d36e6052..c0712657 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.47.0" -shuttle-tower = "0.47.0" +shuttle-runtime = "0.48.0" +shuttle-tower = "0.48.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 1dd4af4f..e1157a30 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.47.0" +shuttle-actix-web = "0.48.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.47.0", default-features = false } +shuttle-runtime = { version = "0.48.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 45a5114b..68590be4 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.47.0" -shuttle-warp = "0.47.0" +shuttle-runtime = "0.48.0" +shuttle-warp = "0.48.0" tokio = "1.26.0" warp = "0.3.3" From 1a807fed768009a166bbc18bcbe000acb084e9e9 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:00:06 +0200 Subject: [PATCH 177/239] actix web + axum Shuttle.toml --- actix-web/clerk/Shuttle.toml | 7 ++++++- actix-web/hello-world/Shuttle.toml | 1 - actix-web/static-files/Shuttle.toml | 5 ++++- actix-web/websocket-actorless/Shuttle.toml | 5 ++++- axum/hello-world/Shuttle.toml | 1 - axum/metadata/Shuttle.toml | 1 - axum/static-files/Shuttle.toml | 4 ++++ axum/turso/Shuttle.toml | 1 - axum/websocket/Shuttle.toml | 5 ++++- 9 files changed, 22 insertions(+), 8 deletions(-) delete mode 100644 actix-web/hello-world/Shuttle.toml delete mode 100644 axum/hello-world/Shuttle.toml delete mode 100644 axum/metadata/Shuttle.toml create mode 100644 axum/static-files/Shuttle.toml delete mode 100644 axum/turso/Shuttle.toml diff --git a/actix-web/clerk/Shuttle.toml b/actix-web/clerk/Shuttle.toml index 96eab060..ceefa534 100644 --- a/actix-web/clerk/Shuttle.toml +++ b/actix-web/clerk/Shuttle.toml @@ -1,4 +1,9 @@ -name = "shuttle-actix-react-clerk" +[deploy] +include = [ + "frontend/dist/*", +] + +[build] assets = [ "frontend/dist/*", ] diff --git a/actix-web/hello-world/Shuttle.toml b/actix-web/hello-world/Shuttle.toml deleted file mode 100644 index df9da3fe..00000000 --- a/actix-web/hello-world/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "hello-world-actix-web-app" \ No newline at end of file diff --git a/actix-web/static-files/Shuttle.toml b/actix-web/static-files/Shuttle.toml index 7bc2b0dd..944532ac 100644 --- a/actix-web/static-files/Shuttle.toml +++ b/actix-web/static-files/Shuttle.toml @@ -1 +1,4 @@ -assets = ["assets/*"] +[build] +assets = [ + "assets/*", +] diff --git a/actix-web/websocket-actorless/Shuttle.toml b/actix-web/websocket-actorless/Shuttle.toml index 3254b9d5..db4a4884 100644 --- a/actix-web/websocket-actorless/Shuttle.toml +++ b/actix-web/websocket-actorless/Shuttle.toml @@ -1 +1,4 @@ -name = "websocket-actorless-actix-web-app" +[build] +assets = [ + "static/*", +] diff --git a/axum/hello-world/Shuttle.toml b/axum/hello-world/Shuttle.toml deleted file mode 100644 index db50aed0..00000000 --- a/axum/hello-world/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "hello-world-axum-app" \ No newline at end of file diff --git a/axum/metadata/Shuttle.toml b/axum/metadata/Shuttle.toml deleted file mode 100644 index 17fcfc4f..00000000 --- a/axum/metadata/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "metadata-axum-app" diff --git a/axum/static-files/Shuttle.toml b/axum/static-files/Shuttle.toml new file mode 100644 index 00000000..a783bac5 --- /dev/null +++ b/axum/static-files/Shuttle.toml @@ -0,0 +1,4 @@ +[build] +assets = [ + "assets", +] diff --git a/axum/turso/Shuttle.toml b/axum/turso/Shuttle.toml deleted file mode 100644 index 3ab32fe4..00000000 --- a/axum/turso/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "turso-example" diff --git a/axum/websocket/Shuttle.toml b/axum/websocket/Shuttle.toml index a98513a3..095a5946 100644 --- a/axum/websocket/Shuttle.toml +++ b/axum/websocket/Shuttle.toml @@ -1 +1,4 @@ -name = "websocket-axum-app" +[build] +assets = [ + "static", +] From 3f35b742b906acdd39bcb7271034319cc2290c50 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:09:38 +0200 Subject: [PATCH 178/239] bevy - rocket Shuttle.toml --- bevy/hello-world/Shuttle.toml | 10 +++- fullstack-templates/saas/Shuttle.toml | 6 +++ loco/hello-world/Shuttle.toml | 1 - poem/hello-world/Shuttle.toml | 1 - poem/mongodb/Cargo.toml | 14 ----- poem/mongodb/Shuttle.toml | 1 - poem/mongodb/src/main.rs | 71 -------------------------- rocket/dyn-templates/Shuttle.toml | 5 +- rocket/hello-world/Shuttle.toml | 1 - rocket/jwt-authentication/Shuttle.toml | 1 - rocket/opendal-memory/Shuttle.toml | 1 - rocket/persist/Cargo.toml | 12 ----- rocket/persist/README.md | 21 -------- rocket/persist/Shuttle.toml | 1 - rocket/persist/src/main.rs | 63 ----------------------- rocket/postgres/Shuttle.toml | 1 - rocket/secrets/Shuttle.toml | 1 - rocket/static-files/Shuttle.toml | 5 +- rocket/url-shortener/Shuttle.toml | 1 - 19 files changed, 23 insertions(+), 194 deletions(-) delete mode 100644 loco/hello-world/Shuttle.toml delete mode 100644 poem/hello-world/Shuttle.toml delete mode 100644 poem/mongodb/Cargo.toml delete mode 100644 poem/mongodb/Shuttle.toml delete mode 100644 poem/mongodb/src/main.rs delete mode 100644 rocket/hello-world/Shuttle.toml delete mode 100644 rocket/jwt-authentication/Shuttle.toml delete mode 100644 rocket/opendal-memory/Shuttle.toml delete mode 100644 rocket/persist/Cargo.toml delete mode 100644 rocket/persist/README.md delete mode 100644 rocket/persist/Shuttle.toml delete mode 100644 rocket/persist/src/main.rs delete mode 100644 rocket/postgres/Shuttle.toml delete mode 100644 rocket/secrets/Shuttle.toml delete mode 100644 rocket/url-shortener/Shuttle.toml diff --git a/bevy/hello-world/Shuttle.toml b/bevy/hello-world/Shuttle.toml index f7d66cb3..7edd1b8f 100644 --- a/bevy/hello-world/Shuttle.toml +++ b/bevy/hello-world/Shuttle.toml @@ -1 +1,9 @@ -assets = ["dist/*"] +[deploy] +include = [ + "dist/*", +] + +[build] +assets = [ + "dist/*", +] diff --git a/fullstack-templates/saas/Shuttle.toml b/fullstack-templates/saas/Shuttle.toml index 69125769..7edd1b8f 100644 --- a/fullstack-templates/saas/Shuttle.toml +++ b/fullstack-templates/saas/Shuttle.toml @@ -1,3 +1,9 @@ +[deploy] +include = [ + "dist/*", +] + +[build] assets = [ "dist/*", ] diff --git a/loco/hello-world/Shuttle.toml b/loco/hello-world/Shuttle.toml deleted file mode 100644 index b6451e25..00000000 --- a/loco/hello-world/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "hello-world" diff --git a/poem/hello-world/Shuttle.toml b/poem/hello-world/Shuttle.toml deleted file mode 100644 index 83fe477b..00000000 --- a/poem/hello-world/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "hello-world-poem-app" diff --git a/poem/mongodb/Cargo.toml b/poem/mongodb/Cargo.toml deleted file mode 100644 index 08577de8..00000000 --- a/poem/mongodb/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "mongodb-poem-app" -version = "0.1.0" -edition = "2021" - -[dependencies] -mongodb = "2.4.0" -poem = "3.0.0" -shuttle-poem = "0.48.0" -shuttle-shared-db = { version = "0.48.0", features = ["mongodb"] } -shuttle-runtime = "0.48.0" -serde = { version = "1.0.148", features = ["derive"] } -serde_json = "1.0.89" -tokio = "1.26.0" diff --git a/poem/mongodb/Shuttle.toml b/poem/mongodb/Shuttle.toml deleted file mode 100644 index d1a1e3a7..00000000 --- a/poem/mongodb/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "mongodb-poem-app" diff --git a/poem/mongodb/src/main.rs b/poem/mongodb/src/main.rs deleted file mode 100644 index fbd676e4..00000000 --- a/poem/mongodb/src/main.rs +++ /dev/null @@ -1,71 +0,0 @@ -use mongodb::bson::doc; -use mongodb::bson::oid::ObjectId; -use mongodb::{Collection, Database}; -use poem::{ - error::{BadRequest, NotFoundError}, - get, handler, - middleware::AddData, - post, - web::{Data, Json}, - EndpointExt, FromRequest, Request, RequestBody, Result, Route, -}; -use serde::{Deserialize, Serialize}; -use shuttle_poem::ShuttlePoem; - -struct ObjectIdGuard(ObjectId); - -impl<'a> FromRequest<'a> for ObjectIdGuard { - async fn from_request(req: &'a Request, _body: &mut RequestBody) -> Result { - let id = req.path_params::()?; - let obj_id = ObjectId::parse_str(id).map_err(BadRequest)?; - Ok(ObjectIdGuard(obj_id)) - } -} - -#[handler] -async fn retrieve( - ObjectIdGuard(id): ObjectIdGuard, - collection: Data<&Collection>, -) -> Result> { - let filter = doc! {"_id": id}; - let todo = collection - .find_one(filter, None) - .await - .map_err(BadRequest)?; - - match todo { - Some(todo) => Ok(Json(serde_json::json!(todo))), - None => Err(NotFoundError.into()), - } -} - -#[handler] -async fn add(Json(todo): Json, collection: Data<&Collection>) -> Result { - let todo_id = collection - .insert_one(todo, None) - .await - .map_err(BadRequest)?; - - Ok(todo_id - .inserted_id - .as_object_id() - .expect("id is objectId") - .to_string()) -} - -#[shuttle_runtime::main] -async fn poem(#[shuttle_shared_db::MongoDb] db: Database) -> ShuttlePoem { - let collection = db.collection::("todos"); - - let app = Route::new() - .at("/todo", post(add)) - .at("/todo/:id", get(retrieve)) - .with(AddData::new(collection)); - - Ok(app.into()) -} - -#[derive(Debug, Serialize, Deserialize)] -struct Todo { - pub note: String, -} diff --git a/rocket/dyn-templates/Shuttle.toml b/rocket/dyn-templates/Shuttle.toml index 148562f8..dd80627d 100644 --- a/rocket/dyn-templates/Shuttle.toml +++ b/rocket/dyn-templates/Shuttle.toml @@ -1 +1,4 @@ -name = "static-files-rocket-app" +[build] +assets = [ + "templates", +] diff --git a/rocket/hello-world/Shuttle.toml b/rocket/hello-world/Shuttle.toml deleted file mode 100644 index 6d22450a..00000000 --- a/rocket/hello-world/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "hello-world-rocket-app" diff --git a/rocket/jwt-authentication/Shuttle.toml b/rocket/jwt-authentication/Shuttle.toml deleted file mode 100644 index 716d4370..00000000 --- a/rocket/jwt-authentication/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "authentication-rocket-app" diff --git a/rocket/opendal-memory/Shuttle.toml b/rocket/opendal-memory/Shuttle.toml deleted file mode 100644 index d823d288..00000000 --- a/rocket/opendal-memory/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "rocket-opendal-memory-example-app" diff --git a/rocket/persist/Cargo.toml b/rocket/persist/Cargo.toml deleted file mode 100644 index dc327353..00000000 --- a/rocket/persist/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "persist" -version = "0.1.0" -edition = "2021" - -[dependencies] -rocket = { version = "0.5.0", features = ["json"] } -serde = { version = "1.0.148", features = ["derive"] } -shuttle-persist = "0.48.0" -shuttle-rocket = "0.48.0" -shuttle-runtime = "0.48.0" -tokio = "1.26.0" diff --git a/rocket/persist/README.md b/rocket/persist/README.md deleted file mode 100644 index d9f245c7..00000000 --- a/rocket/persist/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Persist Example - -An example app to show what you can do with shuttle. - -## How to deploy the example - -```bash -cargo shuttle project start --name=$PROJECT_NAME -cargo shuttle deploy --name=$PROJECT_NAME -``` - -Once deployed you can post to the endpoint the following values: -```bash -curl -X POST -H "Content-Type: application/json" -d '{"date":"2020-12-22", "temp_high":5, "temp_low":5, "precipitation": 5}' {$PROJECT_NAME}.shuttleapp.rs -``` - -The json data will then persist within Shuttle it can be queried with the following curl request - -```bash -curl {$PROJECT_NAME}.shuttleapp.rs/2020-12-22 -``` diff --git a/rocket/persist/Shuttle.toml b/rocket/persist/Shuttle.toml deleted file mode 100644 index 8ab3c88f..00000000 --- a/rocket/persist/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "persist-rocket-app" diff --git a/rocket/persist/src/main.rs b/rocket/persist/src/main.rs deleted file mode 100644 index 1cf96ca3..00000000 --- a/rocket/persist/src/main.rs +++ /dev/null @@ -1,63 +0,0 @@ -#[macro_use] -extern crate rocket; - -use rocket::response::status::BadRequest; -use rocket::serde::json::Json; -use rocket::State; -use serde::{Deserialize, Serialize}; - -use shuttle_persist::PersistInstance; - -#[derive(Serialize, Deserialize, Clone)] -struct Weather { - date: String, - temp_high: f32, - temp_low: f32, - precipitation: f32, -} - -struct MyState { - persist: PersistInstance, -} - -#[post("/", data = "")] -async fn add( - data: Json, - state: &State, -) -> Result, BadRequest> { - // Change data Json to Weather - let weather: Weather = data.into_inner(); - - state - .persist - .save::( - format!("weather_{}", &weather.date.as_str()).as_str(), - weather.clone(), - ) - .map_err(|e| BadRequest(e.to_string()))?; - Ok(Json(weather)) -} - -#[get("/")] -async fn retrieve( - date: String, - state: &State, -) -> Result, BadRequest> { - let weather = state - .persist - .load::(format!("weather_{}", &date).as_str()) - .map_err(|e| BadRequest(e.to_string()))?; - Ok(Json(weather)) -} - -#[shuttle_runtime::main] -async fn main( - #[shuttle_persist::Persist] persist: PersistInstance, -) -> shuttle_rocket::ShuttleRocket { - let state = MyState { persist }; - let rocket = rocket::build() - .mount("/", routes![retrieve, add]) - .manage(state); - - Ok(rocket.into()) -} diff --git a/rocket/postgres/Shuttle.toml b/rocket/postgres/Shuttle.toml deleted file mode 100644 index 539d434b..00000000 --- a/rocket/postgres/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "postgres-rocket-app" diff --git a/rocket/secrets/Shuttle.toml b/rocket/secrets/Shuttle.toml deleted file mode 100644 index 7febf30c..00000000 --- a/rocket/secrets/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "secrets-rocket-app" diff --git a/rocket/static-files/Shuttle.toml b/rocket/static-files/Shuttle.toml index 7bc2b0dd..a783bac5 100644 --- a/rocket/static-files/Shuttle.toml +++ b/rocket/static-files/Shuttle.toml @@ -1 +1,4 @@ -assets = ["assets/*"] +[build] +assets = [ + "assets", +] diff --git a/rocket/url-shortener/Shuttle.toml b/rocket/url-shortener/Shuttle.toml deleted file mode 100644 index c7d17758..00000000 --- a/rocket/url-shortener/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "s" From 2906047e8e2b4e8ee2b974f95d376e0f3a5e7b44 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:37:07 +0200 Subject: [PATCH 179/239] fix: mentions of cargo shuttle --- README.md | 22 +++++------ actix-web/clerk/README.md | 4 +- axum/oauth2/README.md | 2 +- bevy/hello-world/Makefile | 4 +- bevy/hello-world/README.md | 2 +- custom-service/request-scheduler/README.md | 2 +- fullstack-templates/saas/README.md | 4 +- fullstack-templates/saas/package.json | 8 +--- fullstack-templates/saas/turbowatch.ts | 14 +++---- loco/hello-world/README.md | 8 ++-- other/standalone-binary/README.md | 4 +- rocket/dyn-templates/templates/index.html.hbs | 2 +- rocket/jwt-authentication/README.md | 11 ++++-- rocket/url-shortener/README.md | 37 +------------------ salvo/hello-world/Shuttle.toml | 1 - shuttle-cron/README.md | 18 --------- thruster/hello-world/Shuttle.toml | 1 - 17 files changed, 43 insertions(+), 101 deletions(-) delete mode 100644 salvo/hello-world/Shuttle.toml delete mode 100644 shuttle-cron/README.md delete mode 100644 thruster/hello-world/Shuttle.toml diff --git a/README.md b/README.md index a1e9de46..f029664b 100644 --- a/README.md +++ b/README.md @@ -6,35 +6,33 @@ The examples in this repository, consists of *"Hello, world!"* examples of all o ## How to clone, run and deploy an example -To clone an example, use the `init` command of the [`cargo-shuttle`](https://docs.shuttle.rs/introduction/installation) binary and specify the git URL and optional subfolder: +To clone an example, use the `init` command of the [`cargo-shuttle`](https://docs.shuttle.rs/introduction/installation) CLI and specify the git URL and optional subfolder: ```bash -cargo shuttle init --from https://github.com/shuttle-hq/shuttle-examples --subfolder axum/hello-world +shuttle init --from https://github.com/shuttle-hq/shuttle-examples --subfolder axum/hello-world ### Other forms: # GitHub prefix. Change to 'gl:' or 'bb:' for GitLab or BitBucket -cargo shuttle init --from gh:username/repository +shuttle init --from gh:username/repository # Also GitHub -cargo shuttle init --from username/repository +shuttle init --from username/repository # From local folder -cargo shuttle init --from ./path/to/folder -cargo shuttle init --from ../../another/folder -cargo shuttle init --from /home/user/some/folder +shuttle init --from ./path/to/folder +shuttle init --from ../../another/folder +shuttle init --from /home/user/some/folder # Clone into 'my-folder', and use the project name 'my-project-name' -cargo shuttle init --from username/repository --name my-project-name my-folder +shuttle init --from username/repository --name my-project-name my-folder ``` Then, you can navigate into the folder where it was created, and use these commands to run the example locally, and to deploy it. ```bash # Run locally -cargo shuttle run +shuttle run -# Start the Shuttle environment, make sure the project has a unique name -cargo shuttle project start # Deploy to Shuttle -cargo shuttle deploy +shuttle deploy ``` diff --git a/actix-web/clerk/README.md b/actix-web/clerk/README.md index f7a2d47e..621fd7cd 100644 --- a/actix-web/clerk/README.md +++ b/actix-web/clerk/README.md @@ -20,8 +20,8 @@ Get the `VITE_CLERK_PUBLISHABLE_KEY` secret and put it in `frontend/.env`. cd into the frontend and run `npm install` and `npm run build`. This builds the frontend assets and places them in `frontend/dist`. -cd back to the root and run `cargo shuttle run`. +cd back to the root and run `shuttle run`. The backend serves the web page from the dist folder, and an auth-protected API that fetches the list of all users that have signed up so far. -You can then do `cargo shuttle project start` and `cargo shuttle deploy`, but consider switching to a production key from Clerk. +You can then do `shuttle deploy`, but consider switching to a production key from Clerk. The development key can still be used in `Secrets.dev.toml`. diff --git a/axum/oauth2/README.md b/axum/oauth2/README.md index f9ceb360..a867d286 100644 --- a/axum/oauth2/README.md +++ b/axum/oauth2/README.md @@ -13,4 +13,4 @@ GOOGLE_OAUTH_CLIENT_ID = "your-client-id" GOOGLE_OAUTH_CLIENT_SECRET = "your-client-secret" ``` -Use `cargo shuttle run` and visit `http://localhost:8000` once the app is running, then try it out! +Use `shuttle run` and visit `http://localhost:8000` once the app is running, then try it out! diff --git a/bevy/hello-world/Makefile b/bevy/hello-world/Makefile index 3f921b4e..337f1d79 100644 --- a/bevy/hello-world/Makefile +++ b/bevy/hello-world/Makefile @@ -1,5 +1,5 @@ build: cargo build --package game --release --target wasm32-unknown-unknown && \ - wasm-bindgen --out-dir dist --target web target/wasm32-unknown-unknown/release/game.wasm + wasm-bindgen --out-dir dist --target web target/wasm32-unknown-unknown/release/game.wasm up: build - cargo shuttle run + shuttle run diff --git a/bevy/hello-world/README.md b/bevy/hello-world/README.md index b2bbc7d5..634df8b5 100644 --- a/bevy/hello-world/README.md +++ b/bevy/hello-world/README.md @@ -17,4 +17,4 @@ If you don't have `make` installed, you can run the command manually. make build ``` -Go to the project workspace root or the `server` folder, run `cargo shuttle run`, then visit `http://localhost:8000/game`, you should see your Bevy program in action! +Go to the project workspace root or the `server` folder, run `shuttle run`, then visit `http://localhost:8000/game`, you should see your Bevy program in action! diff --git a/custom-service/request-scheduler/README.md b/custom-service/request-scheduler/README.md index b43b27b8..5f90e955 100644 --- a/custom-service/request-scheduler/README.md +++ b/custom-service/request-scheduler/README.md @@ -13,7 +13,7 @@ and sets up an [`axum::Server`](https://github.com/tokio-rs/axum) that sends jobs to a `CronRunner`. # Usage -Run `cargo shuttle run` to spin up the service locally. +Run `shuttle run` to spin up the service locally. Fire a POST request to the `set-schedule` URL to create a new cron job. Use the provided `request.sh` for a quick example or the below snippet: diff --git a/fullstack-templates/saas/README.md b/fullstack-templates/saas/README.md index f11521b0..be6310d5 100644 --- a/fullstack-templates/saas/README.md +++ b/fullstack-templates/saas/README.md @@ -26,7 +26,7 @@ users will be able to view their customers, sales records as well as some analyt - Initialize the template with: ```sh - cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder fullstack-templates/saas + shuttle init --from shuttle-hq/shuttle-examples --subfolder fullstack-templates/saas ``` - cd into the folder @@ -61,4 +61,4 @@ users will be able to view their customers, sales records as well as some analyt like [psql](https://www.postgresql.org/docs/current/app-psql.html) or [pgAdmin](https://www.pgadmin.org/). - If connecting to external services like Stripe doesn't work, try checking your Secrets.toml file. - Shuttle connects by default to port 8000 - if you're currently already using something at port 8000, you can add - the `--port ` to the `cargo shuttle run` command to change this. + the `--port ` to the `shuttle run` command to change this. diff --git a/fullstack-templates/saas/package.json b/fullstack-templates/saas/package.json index a2589597..80d89388 100644 --- a/fullstack-templates/saas/package.json +++ b/fullstack-templates/saas/package.json @@ -7,12 +7,8 @@ "next-dev": "next dev --turbo", "analyze": "cross-env ANALYZE=true next build", "build": "next build && cargo build", - "shuttle-login": "cargo shuttle login", - "full": "cargo shuttle run --port 8001", - "start": "cargo shuttle project start --idle-minutes 0", - "restart": "cargo shuttle project restart --idle-minutes 0", - "stop": "cargo shuttle project stop", - "deploy": "npm run build && cargo shuttle deploy --allow-dirty", + "full": "shuttle run --port 8001", + "deploy": "npm run build && shuttle deploy", "lint": "next lint" }, "dependencies": { diff --git a/fullstack-templates/saas/turbowatch.ts b/fullstack-templates/saas/turbowatch.ts index 4b335926..0ee7b496 100644 --- a/fullstack-templates/saas/turbowatch.ts +++ b/fullstack-templates/saas/turbowatch.ts @@ -38,10 +38,10 @@ function executeCommand(command: string | string[], abortSignal?: AbortSignal): let shuttleCliAvailable = false; -// Function to check if cargo shuttle is installed +// Function to check if shuttle is installed function checkShuttleCli(): Promise { return new Promise((resolve, reject) => { - exec('cargo shuttle --version', (error, stdout, _stderr) => { + exec('shuttle --version', (error, stdout, _stderr) => { if (error) { console.error(`Shuttle check failed: ${error}`); return reject(error); @@ -53,13 +53,13 @@ function checkShuttleCli(): Promise { }); } -// Check for cargo shuttle once at the start +// Check for shuttle once at the start (async () => { try { - console.log('Checking for cargo shuttle...'); + console.log('Checking for shuttle CLI...'); await checkShuttleCli(); } catch (error) { - console.error('Failed to check cargo shuttle:', error); + console.error('Failed to check shuttle CLI:', error); shuttleCliAvailable = false; } })(); @@ -108,9 +108,9 @@ export default defineConfig({ // Routine that is executed when file changes are detected onChange: async ({abortSignal}) => { if (shuttleCliAvailable) { - await executeCommand(['cargo', 'shuttle', 'run'], abortSignal); + await executeCommand(['shuttle', 'run'], abortSignal); } else { - console.error('Shuttle not available, skipping cargo shuttle run'); + console.error('Shuttle not available, skipping shuttle run'); } }, // Retry a task if it fails. Otherwise, watch program will throw an error if trigger fails. diff --git a/loco/hello-world/README.md b/loco/hello-world/README.md index 2a56f692..43915f96 100644 --- a/loco/hello-world/README.md +++ b/loco/hello-world/README.md @@ -2,7 +2,7 @@ Welcome to the [Loco](https://loco.rs) Hello World Shuttle Template, designed with a focus on controllers and views (response schema). This minimalistic template comes with several features to kickstart your project: -### **REST API Service without a Database** +## REST API Service without a Database * **Controllers:** Handle web requests parameters, body, validation, and render a response that is content-aware. We use Axum for the best performance, simplicity, and extensibility. Controllers also allow you to easily build middlewares, which can be used to add logic such as authentication, logging, or error handling before passing requests to the main controller actions. * **Views:** Loco can integrate with templating engines to generate dynamic HTML content from templates. @@ -14,12 +14,10 @@ Welcome to the [Loco](https://loco.rs) Hello World Shuttle Template, designed wi So see more Loco features, check out our [documentation website](https://loco.rs/docs/getting-started/tour/). - - ## Quick Start To launch your app, simply use the following command: ```sh -$ cargo shuttle run -``` \ No newline at end of file +shuttle run +``` diff --git a/other/standalone-binary/README.md b/other/standalone-binary/README.md index 0cf3484e..bdf1749f 100644 --- a/other/standalone-binary/README.md +++ b/other/standalone-binary/README.md @@ -1,10 +1,10 @@ # Standalone binary - run an app with Shuttle or standalone -This example shows how to separate a project's Shuttle logic from its core functionality so that two binaries can be made: one for running with `cargo shuttle run` and deploying to Shuttle, and one that can be run with `cargo run --bin ...`. +This example shows how to separate a project's Shuttle logic from its core functionality so that two binaries can be made: one for running with `shuttle run` and deploying to Shuttle, and one that can be run with `cargo run --bin ...`. All startup logic is placed in the binary source files, while the implementation (endpoints etc) is moved to the library of the crate. -- `src/bin/shuttle.rs` is the main binary with Shuttle, run with `cargo shuttle run`. Note that the `[[bin]]` entry in `Cargo.toml` needs to have the same name as the crate. The file can have any name you want. +- `src/bin/shuttle.rs` is the main binary with Shuttle, run with `shuttle run`. Note that the `[[bin]]` entry in `Cargo.toml` needs to have the same name as the crate. The file can have any name you want. - `src/bin/standalone.rs` is without Shuttle, run with `cargo run --bin standalone` (you can change the name) This example shows how to use separate logic for getting secrets (Shuttle secrets vs homemade solution), but the same approach can be applied to other resources that are initiated by Shuttle's main function. diff --git a/rocket/dyn-templates/templates/index.html.hbs b/rocket/dyn-templates/templates/index.html.hbs index 06a28b64..1c2c6ae9 100644 --- a/rocket/dyn-templates/templates/index.html.hbs +++ b/rocket/dyn-templates/templates/index.html.hbs @@ -15,7 +15,7 @@
-

Templates are evaluated on request, so if you edit a template while running locally using cargo shuttle run there is no need to rebuild.

+

Templates are evaluated on request, so if you edit a template while running locally using shuttle run there is no need to rebuild.

diff --git a/rocket/jwt-authentication/README.md b/rocket/jwt-authentication/README.md index 7b077d30..9fa918fd 100644 --- a/rocket/jwt-authentication/README.md +++ b/rocket/jwt-authentication/README.md @@ -1,4 +1,5 @@ # Issue and verify JWT for authentication + This example shows how to use [Rocket request guards](https://rocket.rs/v0.5-rc/guide/requests/#request-guards) for authentication with [JSON Web Tokens](https://jwt.io/) (JWT for short). The idea is that all requests authenticate first at to get a JWT. Then the JWT is sent with all requests requiring authentication using the HTTP header `Authorization: Bearer `. @@ -7,30 +8,35 @@ This example uses the [`jsonwebtoken`](https://github.com/Keats/jsonwebtoken) wh However, this example only makes use of symmetric encoding and validation on the expiration claim. ## Structure + This example has two files to register routes and handle JWT claims. ### src/main.rs + Three Rocker routes are registered in this file: + 1. `/public`: a route that can be called without needing any authentication. 2. `/login`: a route for posting a JSON object with a username and password to get a JWT. 3. `/private`: a route that can only be accessed with a valid JWT. ### src/claims.rs + The bulk of this example is in this file. Most of the code can be transferred to other frameworks except for the `FromRequest` implementation, which is Rocket specific. This file contains a `Claims` object which can be expanded with more claims. A `Claims` can be created from a `Bearer ` string using `Claims::from_authorization()`. And a `Claims` object can also be converted to a token using `to_token()`. ## Deploy + After logging into shuttle, use the following command to deploy this example: ```sh -cargo shuttle project start -cargo shuttle deploy +shuttle deploy ``` Now make a note of the `Host` for the deploy to use in the examples below. Or just use `authentication-rocket-app.shuttleapp.rs` as the host below. ### Seeing it in action + First, we should be able to access the public endpoint without any authentication using: ```sh @@ -45,7 +51,6 @@ curl https:///private So let's get a JWT from the login route first: - ```sh curl --request POST --data '{"username": "username", "password": "password"}' https:///login ``` diff --git a/rocket/url-shortener/README.md b/rocket/url-shortener/README.md index ccffb3fd..708beff5 100644 --- a/rocket/url-shortener/README.md +++ b/rocket/url-shortener/README.md @@ -22,40 +22,5 @@ you will get the shortened URL back (something like this `https://s.shuttleapp.r The project consists of the following files -- `Shuttle.toml` contains the name of the app (if name is `s` domain will be `s.shuttleapp.rs`) - `migrations` folder is for DB migration files created by [sqlx-cli](https://github.com/launchbadge/sqlx/tree/master/sqlx-cli) -- `src/lib.rs` is where all the magic happens - it creates a shuttle service with two endpoints: one for creating new short URLs and one for handling shortened URLs. - -## How to deploy - -To deploy this app, check out the repository locally - -```bash -git clone https://github.com/shuttle-hq/shuttle.git -``` - -navigate to `examples/rocket/url-shortener` - -```bash -cd examples/rocket/url-shortener -``` - -install shuttle - -```bash -cargo install cargo-shuttle -``` - -login to shuttle - -```bash -cargo shuttle login -``` - -Pick a project name that is something unique - in shuttle, -projects are globally unique. Then run - -```bash -cargo shuttle project start --name=$PROJECT_NAME -cargo shuttle deploy --name=$PROJECT_NAME -``` +- `src/main.rs` is where all the magic happens - it creates a shuttle service with two endpoints: one for creating new short URLs and one for handling shortened URLs. diff --git a/salvo/hello-world/Shuttle.toml b/salvo/hello-world/Shuttle.toml deleted file mode 100644 index 152ba13a..00000000 --- a/salvo/hello-world/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "hello-world-salvo-app" diff --git a/shuttle-cron/README.md b/shuttle-cron/README.md deleted file mode 100644 index e4c55764..00000000 --- a/shuttle-cron/README.md +++ /dev/null @@ -1,18 +0,0 @@ -## Shuttle Cron Template -This repository is an example of how you can deploy a cronjob to [Shuttle](https://www.shuttle.rs), the Rust-native dev cloud platform. - -### Usage -Make sure you have `cargo-shuttle` installed! If not, you can use `cargo install cargo-shuttle` to do so. Requires Rust 1.70+ installed. - -Run the following to initialise this project: -```bash -cargo shuttle init --from shuttle-hq/shuttle-examples --subfolder shuttle-cron -``` - -Follow the prompt, then make any changes you want. Once done, you can deploy: -```bash -cargo shuttle deploy - -# use this if on a dirty Git branch -cargo shuttle deploy --allow-dirty -``` diff --git a/thruster/hello-world/Shuttle.toml b/thruster/hello-world/Shuttle.toml deleted file mode 100644 index 8dca93ff..00000000 --- a/thruster/hello-world/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "hello-world-thruster-app" From 6c015b06abae06b6e42fc8ab71927544d77041eb Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:39:29 +0200 Subject: [PATCH 180/239] final Shuttle.toml --- tide/hello-world/Shuttle.toml | 1 - tower/hello-world/Shuttle.toml | 1 - tracing/custom-tracing-subscriber/Shuttle.toml | 1 - warp/hello-world/Shuttle.toml | 1 - 4 files changed, 4 deletions(-) delete mode 100644 tide/hello-world/Shuttle.toml delete mode 100644 tower/hello-world/Shuttle.toml delete mode 100644 tracing/custom-tracing-subscriber/Shuttle.toml delete mode 100644 warp/hello-world/Shuttle.toml diff --git a/tide/hello-world/Shuttle.toml b/tide/hello-world/Shuttle.toml deleted file mode 100644 index 31927196..00000000 --- a/tide/hello-world/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "hello-world-tide-app" diff --git a/tower/hello-world/Shuttle.toml b/tower/hello-world/Shuttle.toml deleted file mode 100644 index b99b1f92..00000000 --- a/tower/hello-world/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "hello-world-tower-app" diff --git a/tracing/custom-tracing-subscriber/Shuttle.toml b/tracing/custom-tracing-subscriber/Shuttle.toml deleted file mode 100644 index e5147946..00000000 --- a/tracing/custom-tracing-subscriber/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "custom-tracing-subscriber-actix-web-app" diff --git a/warp/hello-world/Shuttle.toml b/warp/hello-world/Shuttle.toml deleted file mode 100644 index a8e7f48a..00000000 --- a/warp/hello-world/Shuttle.toml +++ /dev/null @@ -1 +0,0 @@ -name = "hello-world-warp-app" From ae1a39443cb8a223e8d4e6e4ed3a961d1f466e5e Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Thu, 10 Oct 2024 12:28:35 +0200 Subject: [PATCH 181/239] fix: templates.toml --- templates.toml | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/templates.toml b/templates.toml index 7497d2a0..1e9af22e 100644 --- a/templates.toml +++ b/templates.toml @@ -22,7 +22,6 @@ clerk = "https://avatars.githubusercontent.com/u/49538330?v=4" htmx = "https://raw.githubusercontent.com/bigskysoftware/htmx/8e26d12c33caf7dc99c49d4918e7b8abd8028f98/www/static/img/htmx_logo.2.png" qdrant = "https://avatars.githubusercontent.com/u/73504361?v=4" nextjs = "https://assets.vercel.com/image/upload/v1662130559/nextjs/Icon_light_background.png" -mongodb = "https://avatars.githubusercontent.com/u/45120?v=4" opendal = "https://avatars.githubusercontent.com/u/47359?v=4" openai = "https://avatars.githubusercontent.com/u/14957082?v=4" # fallback @@ -257,13 +256,6 @@ path = "fullstack-templates/saas" use_cases = ["Web app", "Authentication", "Storage", "Monetization"] tags = ["nextjs", "axum", "database", "postgres", "typescript", "tailwind"] -[templates.poem-mongodb] -title = "MongoDB" -description = "Todo list with a MongoDB database" -path = "poem/mongodb" -use_cases = ["Web app", "Storage"] -tags = ["mongodb", "poem", "database"] - [templates.rocket-dyn-templates] title = "Handlebars dynamic templates" description = "HTML templating with Handlebars" @@ -351,13 +343,6 @@ path = "axum/metadata" use_cases = [] tags = ["axum"] -[examples.persist] -title = "Shuttle Persist" -description = "Basic usage of shuttle-persist" -path = "rocket/persist" -use_cases = ["Web app", "Storage"] -tags = ["rocket"] - [examples.secrets] title = "Shuttle Secrets" description = "Basic usage of Shuttle Secrets" From 330c62636e0c6013fb8471ce7dc90b87e5c1b07c Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Thu, 10 Oct 2024 12:58:00 +0200 Subject: [PATCH 182/239] nit: move ci script --- .github/workflows/ci.yml | 2 +- ci.sh => _scripts/ci.sh | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename ci.sh => _scripts/ci.sh (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 717cb158..216f4986 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,7 +60,7 @@ jobs: - name: Check formatting and Clippy shell: bash - run: ./ci.sh ${{ matrix.from-to }} + run: _scripts/ci.sh ${{ matrix.from-to }} env: RUSTC_WRAPPER: /home/runner/.cargo/bin/sccache CARGO_TARGET_DIR: /tmp/target diff --git a/ci.sh b/_scripts/ci.sh similarity index 100% rename from ci.sh rename to _scripts/ci.sh From c3ee721ed60c7615d5067dec1dfca4956b768a71 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Thu, 10 Oct 2024 12:58:02 +0200 Subject: [PATCH 183/239] nit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f029664b..4d25c645 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ shuttle init --from https://github.com/shuttle-hq/shuttle-examples --subfolder a # GitHub prefix. Change to 'gl:' or 'bb:' for GitLab or BitBucket shuttle init --from gh:username/repository -# Also GitHub +# By default, 'gh:' (GitHub) is assumed shuttle init --from username/repository # From local folder From a6b5f0d4c819b30a99c59c2bc3aa7b5cf4fda8fe Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:57:54 +0200 Subject: [PATCH 184/239] readme link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4d25c645..bdda807d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ The examples in this repository, consists of *"Hello, world!"* examples of all o ## How to clone, run and deploy an example -To clone an example, use the `init` command of the [`cargo-shuttle`](https://docs.shuttle.rs/introduction/installation) CLI and specify the git URL and optional subfolder: +To clone an example, use the `init` command of the [CLI](https://docs.shuttle.dev/getting-started/installation) and specify the git URL and optional subfolder: ```bash shuttle init --from https://github.com/shuttle-hq/shuttle-examples --subfolder axum/hello-world From e6a0199f7f4e832b849f4a9d31e39257c7ff0937 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Tue, 29 Oct 2024 02:09:08 +0100 Subject: [PATCH 185/239] fix: websocket examples urls --- actix-web/websocket-actorless/src/main.rs | 4 ++-- axum/websocket/src/main.rs | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/actix-web/websocket-actorless/src/main.rs b/actix-web/websocket-actorless/src/main.rs index 173ff3b3..0cba83f7 100644 --- a/actix-web/websocket-actorless/src/main.rs +++ b/actix-web/websocket-actorless/src/main.rs @@ -15,7 +15,7 @@ use std::{ use tokio::sync::{mpsc, watch}; const PAUSE_SECS: u64 = 15; -const STATUS_URI: &str = "https://api.shuttle.rs"; +const STATUS_URI: &str = "https://api.shuttle.dev/.healthz"; type AppState = ( mpsc::UnboundedSender, @@ -191,5 +191,5 @@ async fn main() -> ShuttleActixWeb bool { let response = client.get(STATUS_URI).send().await; - response.is_ok() + response.is_ok_and(|r| r.status().is_success()) } diff --git a/axum/websocket/src/main.rs b/axum/websocket/src/main.rs index 2c6ad0ba..654847fc 100644 --- a/axum/websocket/src/main.rs +++ b/axum/websocket/src/main.rs @@ -25,7 +25,7 @@ struct State { } const PAUSE_SECS: u64 = 15; -const STATUS_URI: &str = "https://api.shuttle.rs"; +const STATUS_URI: &str = "https://api.shuttle.dev/.healthz"; #[derive(Serialize)] struct Response { @@ -50,8 +50,9 @@ async fn main() -> ShuttleAxum { let duration = Duration::from_secs(PAUSE_SECS); loop { - let is_up = reqwest::get(STATUS_URI).await; - let is_up = is_up.is_ok(); + let is_up = reqwest::get(STATUS_URI) + .await + .is_ok_and(|r| r.status().is_success()); let response = Response { clients_count: state_send.lock().await.clients_count, From 25fd5dedeeba6e15e1f4a5d3b97bf9f5a8c36c15 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Tue, 12 Nov 2024 13:38:29 +0100 Subject: [PATCH 186/239] chore: v0.49.0 --- actix-web/clerk/backend/Cargo.toml | 4 ++-- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/htmx-crud/Cargo.toml | 6 +++--- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 4 ++-- axum/oauth2/Cargo.toml | 6 +++--- axum/openai/Cargo.toml | 6 +++--- axum/postgres/Cargo.toml | 6 +++--- axum/qdrant/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- bevy/hello-world/server/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 6 +++--- loco/hello-world/Cargo.toml | 4 ++-- other/feature-flags/Cargo.toml | 4 ++-- other/standalone-binary/Cargo.toml | 4 ++-- poem/hello-world/Cargo.toml | 4 ++-- poise/hello-world/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/opendal-memory/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 4 ++-- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- salvo/image-rescaler/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 6 +++--- serenity/weather-forecast/Cargo.toml | 4 ++-- thruster/hello-world/Cargo.toml | 4 ++-- tide/hello-world/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 46 files changed, 104 insertions(+), 104 deletions(-) diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml index 629bf653..01ce5229 100644 --- a/actix-web/clerk/backend/Cargo.toml +++ b/actix-web/clerk/backend/Cargo.toml @@ -10,5 +10,5 @@ clerk-rs = "0.2.3" openssl-sys = { version = "0.9.9", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-actix-web = "0.49.0" +shuttle-runtime = "0.49.0" diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index dcd1e223..71f83ea1 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.7.1" actix-session = { version = "0.9.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-actix-web = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 74821e20..7838fdf4 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-actix-web = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 7d543398..2e935ce9 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-actix-web = "0.49.0" +shuttle-runtime = "0.49.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.48.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.49.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index 8a137d0c..d4ab777a 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-actix-web = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 80893824..f2036e76 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-actix-web = "0.49.0" +shuttle-runtime = "0.49.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 7ab2ee6f..90108dc9 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-axum = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.28.2" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index d3ab04dc..700b0348 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -9,9 +9,9 @@ askama_axum = "0.4.0" axum = "0.7.4" serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.48.0" -shuttle-runtime = "0.48.0" -shuttle-shared-db = { version = "0.48.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.49.0" +shuttle-runtime = "0.49.0" +shuttle-shared-db = { version = "0.49.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index 45d184cd..6965aaeb 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-axum = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index c5640c1d..edcdec9a 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-axum = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.28.2" diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index 1c986719..4f571ba5 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -11,9 +11,9 @@ chrono = { version = "0.4.35", features = ["clock"] } oauth2 = "4.4.1" reqwest = { version = "0.11.18", features = ["json"] } serde = { version = "1.0.183", features = ["derive"] } -shuttle-axum = "0.48.0" -shuttle-runtime = "0.48.0" -shuttle-shared-db = { version = "0.48.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.49.0" +shuttle-runtime = "0.49.0" +shuttle-shared-db = { version = "0.49.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["macros", "chrono"] } thiserror = "1.0.57" time = "0.3.25" diff --git a/axum/openai/Cargo.toml b/axum/openai/Cargo.toml index 8c211847..1eacadba 100644 --- a/axum/openai/Cargo.toml +++ b/axum/openai/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-openai = "0.23.0" axum = "0.7.3" serde_json = "1" -shuttle-axum = "0.48.0" -shuttle-openai = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-axum = "0.49.0" +shuttle-openai = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.26.0" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 1987e88d..2796e91f 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.48.0" -shuttle-runtime = "0.48.0" -shuttle-shared-db = { version = "0.48.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.49.0" +shuttle-runtime = "0.49.0" +shuttle-shared-db = { version = "0.49.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index 4010645c..62a6b6d6 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.10.1" -shuttle-axum = "0.48.0" -shuttle-qdrant = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-axum = "0.49.0" +shuttle-qdrant = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index f482f2f3..6e057d9f 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-axum = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 2428f1f8..eb60f02e 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.48.0" -shuttle-runtime = "0.48.0" -shuttle-turso = "0.48.0" +shuttle-axum = "0.49.0" +shuttle-runtime = "0.49.0" +shuttle-turso = "0.49.0" libsql = "0.3.1" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 90a1c2e5..be93e51b 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-axum = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/bevy/hello-world/server/Cargo.toml b/bevy/hello-world/server/Cargo.toml index b9638d6b..752a60af 100644 --- a/bevy/hello-world/server/Cargo.toml +++ b/bevy/hello-world/server/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-axum = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 70a67c2c..fbbdb321 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1", features = ["derive"] } -shuttle-service = "0.48.0" -shuttle-axum = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-service = "0.49.0" +shuttle-axum = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 3e072d69..93fafc26 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.48.0" +shuttle-runtime = "0.49.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index 382c094d..23c730cf 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -10,7 +10,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-persist = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 35703047..db794b34 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,9 +16,9 @@ lettre = "0.11.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.48.0" -shuttle-runtime = "0.48.0" -shuttle-shared-db = { version = "0.48.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.49.0" +shuttle-runtime = "0.49.0" +shuttle-shared-db = { version = "0.49.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index 31a33af2..5e904458 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -12,8 +12,8 @@ edition = "2021" async-trait = "0.1.74" axum = "0.7.1" loco-rs = { version = "0.9.0", default-features = false, features = ["cli"] } -shuttle-axum = "0.48.0" -shuttle-runtime = { version = "0.48.0", default-features = false } +shuttle-axum = "0.49.0" +shuttle-runtime = { version = "0.49.0", default-features = false } serde = "*" serde_json = "*" tokio = "1.33.0" diff --git a/other/feature-flags/Cargo.toml b/other/feature-flags/Cargo.toml index 5e52ab51..48e87df8 100644 --- a/other/feature-flags/Cargo.toml +++ b/other/feature-flags/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-axum = "0.49.0" +shuttle-runtime = "0.49.0" [features] # Shuttle will disable default features and enable the feature "shuttle" if it exists. diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 3257ad10..5ce98024 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,6 +15,6 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-axum = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 7bbff9bb..50491120 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "3.0.0" -shuttle-poem = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-poem = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 53c76214..a93fdae6 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.6.1" -shuttle-runtime = "0.48.0" +shuttle-runtime = "0.49.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity -shuttle-serenity = "0.48.0" +shuttle-serenity = "0.49.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index bfb1e3bb..2ff700ea 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" rocket_dyn_templates = { version = "0.1.0", features = ["handlebars"] } -shuttle-rocket = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-rocket = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 1744d13c..3b063abe 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-rocket = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 8dc7ebae..b10bc8f1 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-rocket = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.26.0" diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index 94cce033..200832d9 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -4,10 +4,10 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.48.0" -shuttle-opendal = "0.48.0" +shuttle-runtime = "0.49.0" +shuttle-opendal = "0.49.0" tokio = "1.26.0" -shuttle-rocket = "0.48.0" +shuttle-rocket = "0.49.0" opendal = "0.45" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index ab880017..9c06843f 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.48.0" -shuttle-runtime = "0.48.0" -shuttle-shared-db = { version = "0.48.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.49.0" +shuttle-runtime = "0.49.0" +shuttle-shared-db = { version = "0.49.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index fc5aa038..875d04b2 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-rocket = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index 841325c4..9555bf25 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-rocket = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 5b582f69..8e5c49e2 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" nanoid = "0.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.48.0" -shuttle-runtime = "0.48.0" -shuttle-shared-db = { version = "0.48.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.49.0" +shuttle-runtime = "0.49.0" +shuttle-shared-db = { version = "0.49.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index a6bee465..b32ab17c 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-rocket = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 47346f7a..b988a186 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] salvo = "0.63.0" -shuttle-salvo = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-salvo = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml index 03c94fc7..d51a68e7 100644 --- a/salvo/image-rescaler/Cargo.toml +++ b/salvo/image-rescaler/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] image = "0.24.8" salvo = "0.63.0" -shuttle-salvo = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-salvo = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 89382cf0..9030b9c2 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.48.0" -shuttle-serenity = "0.48.0" +shuttle-runtime = "0.49.0" +shuttle-serenity = "0.49.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index a0092c60..9c3826e4 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.48.0" -shuttle-serenity = "0.48.0" -shuttle-shared-db = { version = "0.48.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.49.0" +shuttle-serenity = "0.49.0" +shuttle-shared-db = { version = "0.49.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/weather-forecast/Cargo.toml b/serenity/weather-forecast/Cargo.toml index f6861fd4..fa656821 100644 --- a/serenity/weather-forecast/Cargo.toml +++ b/serenity/weather-forecast/Cargo.toml @@ -8,7 +8,7 @@ anyhow = "1.0.66" reqwest = { version = "0.11.24", features = ["json"] } serde = "1.0.197" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.48.0" -shuttle-serenity = "0.48.0" +shuttle-runtime = "0.49.0" +shuttle-serenity = "0.49.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index ad67ec9e..0d3de3e7 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-thruster = "0.49.0" +shuttle-runtime = "0.49.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index bad3fbf0..ad7e9d00 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.48.0" -shuttle-runtime = "0.48.0" +shuttle-tide = "0.49.0" +shuttle-runtime = "0.49.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index c0712657..feb280c4 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.48.0" -shuttle-tower = "0.48.0" +shuttle-runtime = "0.49.0" +shuttle-tower = "0.49.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index e1157a30..c6577f97 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.48.0" +shuttle-actix-web = "0.49.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.48.0", default-features = false } +shuttle-runtime = { version = "0.49.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 68590be4..4ccebf21 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.48.0" -shuttle-warp = "0.48.0" +shuttle-runtime = "0.49.0" +shuttle-warp = "0.49.0" tokio = "1.26.0" warp = "0.3.3" From 4185a78966a10a88d768347dbbb0820f3093e9bf Mon Sep 17 00:00:00 2001 From: Joshua Mo <102877324+joshua-mo-143@users.noreply.github.com> Date: Mon, 25 Nov 2024 13:15:33 +0000 Subject: [PATCH 187/239] feat: update openai template (#193) * feat: update openai template * chore: satisfy ci * docs: update README --- axum/openai/.gitignore | 3 + axum/openai/Cargo.toml | 21 +- axum/openai/README.md | 22 +- axum/openai/Shuttle.toml | 5 + axum/openai/frontend/.eslintrc.json | 3 + axum/openai/frontend/.gitignore | 43 + axum/openai/frontend/app/app/page.tsx | 167 + axum/openai/frontend/app/favicon.ico | Bin 0 -> 25931 bytes .../frontend/app/fonts/GeistMonoVF.woff | Bin 0 -> 67864 bytes axum/openai/frontend/app/fonts/GeistVF.woff | Bin 0 -> 66268 bytes axum/openai/frontend/app/globals.css | 21 + axum/openai/frontend/app/layout.tsx | 35 + axum/openai/frontend/app/login/page.tsx | 92 + axum/openai/frontend/app/page.tsx | 35 + axum/openai/frontend/app/register/page.tsx | 93 + .../frontend/components/ChatMessage.tsx | 23 + .../components/ConversationButton.tsx | 39 + axum/openai/frontend/components/Footer.tsx | 53 + axum/openai/frontend/next.config.js | 10 + axum/openai/frontend/package-lock.json | 6319 +++++++++++++++++ axum/openai/frontend/package.json | 29 + axum/openai/frontend/postcss.config.mjs | 8 + axum/openai/frontend/public/file.svg | 1 + axum/openai/frontend/public/globe.svg | 1 + axum/openai/frontend/public/next.svg | 1 + axum/openai/frontend/public/shuttle-logo.webp | Bin 0 -> 47880 bytes axum/openai/frontend/public/vercel.svg | 1 + axum/openai/frontend/public/window.svg | 1 + axum/openai/frontend/tailwind.config.ts | 18 + axum/openai/frontend/tsconfig.json | 42 + axum/openai/hurl/register.hurl | 38 + axum/openai/justfile | 19 + .../migrations/20241115220707_init.down.sql | 1 + .../migrations/20241115220707_init.up.sql | 16 + axum/openai/src/endpoints/auth.rs | 190 + axum/openai/src/endpoints/mod.rs | 6 + axum/openai/src/endpoints/openai.rs | 226 + axum/openai/src/main.rs | 96 +- axum/openai/src/state.rs | 37 + 39 files changed, 7666 insertions(+), 49 deletions(-) create mode 100644 axum/openai/.gitignore create mode 100644 axum/openai/Shuttle.toml create mode 100644 axum/openai/frontend/.eslintrc.json create mode 100644 axum/openai/frontend/.gitignore create mode 100644 axum/openai/frontend/app/app/page.tsx create mode 100644 axum/openai/frontend/app/favicon.ico create mode 100644 axum/openai/frontend/app/fonts/GeistMonoVF.woff create mode 100644 axum/openai/frontend/app/fonts/GeistVF.woff create mode 100644 axum/openai/frontend/app/globals.css create mode 100644 axum/openai/frontend/app/layout.tsx create mode 100644 axum/openai/frontend/app/login/page.tsx create mode 100644 axum/openai/frontend/app/page.tsx create mode 100644 axum/openai/frontend/app/register/page.tsx create mode 100644 axum/openai/frontend/components/ChatMessage.tsx create mode 100644 axum/openai/frontend/components/ConversationButton.tsx create mode 100644 axum/openai/frontend/components/Footer.tsx create mode 100644 axum/openai/frontend/next.config.js create mode 100644 axum/openai/frontend/package-lock.json create mode 100644 axum/openai/frontend/package.json create mode 100644 axum/openai/frontend/postcss.config.mjs create mode 100644 axum/openai/frontend/public/file.svg create mode 100644 axum/openai/frontend/public/globe.svg create mode 100644 axum/openai/frontend/public/next.svg create mode 100644 axum/openai/frontend/public/shuttle-logo.webp create mode 100644 axum/openai/frontend/public/vercel.svg create mode 100644 axum/openai/frontend/public/window.svg create mode 100644 axum/openai/frontend/tailwind.config.ts create mode 100644 axum/openai/frontend/tsconfig.json create mode 100644 axum/openai/hurl/register.hurl create mode 100644 axum/openai/justfile create mode 100644 axum/openai/migrations/20241115220707_init.down.sql create mode 100644 axum/openai/migrations/20241115220707_init.up.sql create mode 100644 axum/openai/src/endpoints/auth.rs create mode 100644 axum/openai/src/endpoints/mod.rs create mode 100644 axum/openai/src/endpoints/openai.rs create mode 100644 axum/openai/src/state.rs diff --git a/axum/openai/.gitignore b/axum/openai/.gitignore new file mode 100644 index 00000000..cfcbc42b --- /dev/null +++ b/axum/openai/.gitignore @@ -0,0 +1,3 @@ +/target +.shuttle* +Secrets*.toml diff --git a/axum/openai/Cargo.toml b/axum/openai/Cargo.toml index 1eacadba..12cc57e7 100644 --- a/axum/openai/Cargo.toml +++ b/axum/openai/Cargo.toml @@ -5,9 +5,22 @@ edition = "2021" [dependencies] async-openai = "0.23.0" -axum = "0.7.3" -serde_json = "1" +argon2 = "0.5.3" +axum = "0.7.4" +axum-extra = { version = "0.9.4", features = ["cookie", "cookie-private"] } +derive_more = { version = "1.0.0", features = ["full"] } +jsonwebtoken = "9.3.0" +serde = { version = "1.0.215", features = ["derive"] } +serde_json = "1.0.133" + +sqlx = { version = "0.8.2", features = [ + "runtime-tokio-rustls", + "postgres", + "macros", +] } +tokio = { version = "1.28.2", features = ["macros", "rt-multi-thread"] } +tower-http = { version = "0.6.2", features = ["cors", "fs"] } +shuttle-runtime = "0.49.0" shuttle-axum = "0.49.0" +shuttle-shared-db = { version = "0.49.0", features = ["postgres"] } shuttle-openai = "0.49.0" -shuttle-runtime = "0.49.0" -tokio = "1.26.0" diff --git a/axum/openai/README.md b/axum/openai/README.md index 776fbbdb..65a6c9ac 100644 --- a/axum/openai/README.md +++ b/axum/openai/README.md @@ -1,7 +1,19 @@ -A simple endpoint that sends a chat message to ChatGPT and returns the response. +## Shuttle AI Playground +This template enables you to spin up an AI playground in the style of OpenAI. -Set your OpenAI API key in `Secrets.toml`, then try it on a local run with: +## Features +- Frontend (via Next.js) +- Authentication and sign-ups with cookie-wrapped JWTs +- Database +- OpenAI -```sh -curl http://localhost:8000 -H 'content-type: application/json' --data '{"message":"What is shuttle.rs?"}' -``` +## How to use +Before using this, you will need an OpenAI API key. + +1) Ensure the OpenAI API key is in your `Secrets.toml` file (see file for syntax if not sure how to use). +2) Run `npm --prefix frontend install && npm --prefix frontend run build` to build the Next.js frontend. +3) Use `shuttle run` to run the template locally - or use `shuttle deploy` to deploy! + +## Troubleshooting +- The default port is at 8000. If you are already running something here, you can use `--port` to select a different port. +- Your OpenAI client may error out if you don't have your OpenAI API key set correctly (should be `OPENAI_API_KEY` in Secrets.toml). diff --git a/axum/openai/Shuttle.toml b/axum/openai/Shuttle.toml new file mode 100644 index 00000000..687c82d6 --- /dev/null +++ b/axum/openai/Shuttle.toml @@ -0,0 +1,5 @@ +[build] +assets = ["frontend/dist/*"] + +[deploy] +include = ["frontend/dist/*"] diff --git a/axum/openai/frontend/.eslintrc.json b/axum/openai/frontend/.eslintrc.json new file mode 100644 index 00000000..37224185 --- /dev/null +++ b/axum/openai/frontend/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": ["next/core-web-vitals", "next/typescript"] +} diff --git a/axum/openai/frontend/.gitignore b/axum/openai/frontend/.gitignore new file mode 100644 index 00000000..46e7866f --- /dev/null +++ b/axum/openai/frontend/.gitignore @@ -0,0 +1,43 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + +# build +dist diff --git a/axum/openai/frontend/app/app/page.tsx b/axum/openai/frontend/app/app/page.tsx new file mode 100644 index 00000000..beb5b175 --- /dev/null +++ b/axum/openai/frontend/app/app/page.tsx @@ -0,0 +1,167 @@ +"use client"; +import { ChatMessage } from "@/components/ChatMessage"; +import { ConversationButton } from "@/components/ConversationButton"; +import { useRouter } from "next/navigation"; +import { useEffect, useState } from "react"; + +export interface GPTMessage { + role: string; + message: string; +} + +export default function AppPage() { + const router = useRouter(); + const [model, setModel] = useState("gpt-4o"); + const [message, setMessage] = useState(""); + const [conversationId, setConversationId] = useState(0); + const [conversationList, setConversationList] = useState([]); + const [messages, setMessages] = useState([]); + const [loading, setLoading] = useState(false); + + function newChat() { + setConversationId(0); + setMessages([]); + } + + async function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + + if (conversationId === 0) { + const res = await fetch(`/api/chat/create`, { + method: "POST", + headers: { + "content-type": "application/json", + }, + body: JSON.stringify({ + prompt: message, + model: model, + }), + }); + + const data = await res.json(); + + const new_conversation_list = conversationList; + new_conversation_list.unshift(data.conversation_id); + console.log(data.conversation_id); + setConversationId(data.conversation_id); + setConversationList(new_conversation_list); + } + + setMessages((prev) => { + return [...prev, { message: message, role: "user" }]; + }); + setMessage(""); + setLoading(true); + + const conversation_res = await fetch( + `/api/chat/conversations/${conversationId}`, + { + method: "POST", + headers: { + "content-type": "application/json", + }, + body: JSON.stringify({ + prompt: message, + model: model, + }), + }, + ); + + const promptReqData = await conversation_res.json(); + + setMessages((prev) => { + return [...prev, { message: promptReqData.response, role: "system" }]; + }); + setLoading(false); + } + + useEffect(() => { + const fetchData = async () => { + const res = await fetch("/api/chat/conversations"); + if (res.ok) { + const data = await res.json(); + setConversationList(data); + } else { + router.replace("/login"); + } + }; + + fetchData(); + }, []); + + return ( +
+ +
+ +
+ {messages.map((x, idx) => ( + + ))} + {loading ?

Waiting for response...

: null} +
+
handleSubmit(e)} + > + setMessage((e.target as HTMLInputElement).value)} + required + > + +
+
+
+ ); +} diff --git a/axum/openai/frontend/app/favicon.ico b/axum/openai/frontend/app/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..718d6fea4835ec2d246af9800eddb7ffb276240c GIT binary patch literal 25931 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 LrJugUA?W`A8`#=m literal 0 HcmV?d00001 diff --git a/axum/openai/frontend/app/fonts/GeistMonoVF.woff b/axum/openai/frontend/app/fonts/GeistMonoVF.woff new file mode 100644 index 0000000000000000000000000000000000000000..f2ae185cbfd16946a534d819e9eb03924abbcc49 GIT binary patch literal 67864 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ϣ%UY8`RWp~V-U_7 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 CLkb=M literal 0 HcmV?d00001 diff --git a/axum/openai/frontend/app/fonts/GeistVF.woff b/axum/openai/frontend/app/fonts/GeistVF.woff new file mode 100644 index 0000000000000000000000000000000000000000..1b62daacff96dad6584e71cd962051b82957c313 GIT binary patch literal 66268 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 >-Aun5A4Gp>4U0IQJ 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 G)cz05(PHWV literal 0 HcmV?d00001 diff --git a/axum/openai/frontend/app/globals.css b/axum/openai/frontend/app/globals.css new file mode 100644 index 00000000..6b717ad3 --- /dev/null +++ b/axum/openai/frontend/app/globals.css @@ -0,0 +1,21 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + --background: #ffffff; + --foreground: #171717; +} + +@media (prefers-color-scheme: dark) { + :root { + --background: #0a0a0a; + --foreground: #ededed; + } +} + +body { + color: var(--foreground); + background: var(--background); + font-family: Arial, Helvetica, sans-serif; +} diff --git a/axum/openai/frontend/app/layout.tsx b/axum/openai/frontend/app/layout.tsx new file mode 100644 index 00000000..a36cde01 --- /dev/null +++ b/axum/openai/frontend/app/layout.tsx @@ -0,0 +1,35 @@ +import type { Metadata } from "next"; +import localFont from "next/font/local"; +import "./globals.css"; + +const geistSans = localFont({ + src: "./fonts/GeistVF.woff", + variable: "--font-geist-sans", + weight: "100 900", +}); +const geistMono = localFont({ + src: "./fonts/GeistMonoVF.woff", + variable: "--font-geist-mono", + weight: "100 900", +}); + +export const metadata: Metadata = { + title: "Create Next App", + description: "Generated by create next app", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + + {children} + + + ); +} diff --git a/axum/openai/frontend/app/login/page.tsx b/axum/openai/frontend/app/login/page.tsx new file mode 100644 index 00000000..3affa6b3 --- /dev/null +++ b/axum/openai/frontend/app/login/page.tsx @@ -0,0 +1,92 @@ +"use client"; +import { Footer } from "@/components/Footer"; +import Link from "next/link"; +import { useRouter } from "next/navigation"; +import { useState } from "react"; + +export default function Login() { + const router = useRouter(); + + const [username, setUsername] = useState(""); + const [password, setPassword] = useState(""); + + async function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + + const res = await fetch("/api/auth/login", { + method: "POST", + headers: { + "content-type": "application/json", + }, + body: JSON.stringify({ + username: username, + password: password, + }), + }); + + if (res.ok) { + router.replace("/app"); + } + } + return ( +
+
+
handleSubmit(e)} + > +

Log In

+
+ + + +
+
+ + I don't have an account + +
+
+
+
+
+ ); +} diff --git a/axum/openai/frontend/app/page.tsx b/axum/openai/frontend/app/page.tsx new file mode 100644 index 00000000..105d49d2 --- /dev/null +++ b/axum/openai/frontend/app/page.tsx @@ -0,0 +1,35 @@ +import { Footer } from "@/components/Footer"; +import Image from "next/image"; +import Link from "next/link"; + +export default function Home() { + return ( +
+
+ Shuttle logo +

Shuttle AI Playground

+
+ + Register + + + Log In + +
+
+
+
+ ); +} diff --git a/axum/openai/frontend/app/register/page.tsx b/axum/openai/frontend/app/register/page.tsx new file mode 100644 index 00000000..1d28408b --- /dev/null +++ b/axum/openai/frontend/app/register/page.tsx @@ -0,0 +1,93 @@ +"use client"; +import { Footer } from "@/components/Footer"; +import Link from "next/link"; +import { useRouter } from "next/navigation"; +import { useState } from "react"; + +export default function Register() { + const router = useRouter(); + + const [username, setUsername] = useState(""); + const [password, setPassword] = useState(""); + + async function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + + const res = await fetch("/api/auth/register", { + method: "POST", + headers: { + "content-type": "application/json", + }, + body: JSON.stringify({ + username: username, + password: password, + }), + }); + + if (res.ok) { + router.replace("/login"); + } + } + + return ( +
+
+
handleSubmit(e)} + > +

Register

+
+ + + +
+
+ + I already have an account + +
+
+
+
+
+ ); +} diff --git a/axum/openai/frontend/components/ChatMessage.tsx b/axum/openai/frontend/components/ChatMessage.tsx new file mode 100644 index 00000000..b5ddff79 --- /dev/null +++ b/axum/openai/frontend/components/ChatMessage.tsx @@ -0,0 +1,23 @@ +import Markdown from "react-markdown"; +import remarkGfm from "remark-gfm"; + +interface Props { + message: string; + role: string; +} + +export const ChatMessage = ({ message, role }: Props) => { + const color = role === "user" ? "bg-slate-300" : "bg-orange-500"; + const align = role === "user" ? "self-end" : "self-start"; + return ( +
+ {role === "user" ? ( +

{message}

+ ) : ( + {message} + )} +
+ ); +}; diff --git a/axum/openai/frontend/components/ConversationButton.tsx b/axum/openai/frontend/components/ConversationButton.tsx new file mode 100644 index 00000000..8b977f68 --- /dev/null +++ b/axum/openai/frontend/components/ConversationButton.tsx @@ -0,0 +1,39 @@ +"use client"; + +import { GPTMessage } from "@/app/app/page"; +import { SetStateAction } from "react"; + +interface Props { + setMessages: React.Dispatch>; + setConversationId: React.Dispatch>; + id: number; + active: boolean; +} + +export const ConversationButton = ({ + setMessages, + setConversationId, + id, + active, +}: Props) => { + async function handleClick(e: React.MouseEvent) { + e.preventDefault(); + + const res = await fetch(`/api/chat/conversations/${id}`); + const data = await res.json(); + setMessages(data.messages); + setConversationId(id); + } + + const isActiveClasses = active + ? "bg-gradient-to-r from-orange-700 to-yellow-400 text-slate-200" + : "text-white bg-slate-100/10"; + return ( + + ); +}; diff --git a/axum/openai/frontend/components/Footer.tsx b/axum/openai/frontend/components/Footer.tsx new file mode 100644 index 00000000..5d2a8bfd --- /dev/null +++ b/axum/openai/frontend/components/Footer.tsx @@ -0,0 +1,53 @@ +import Image from "next/image"; + +export const Footer = () => { + return ( +
+ ); +}; diff --git a/axum/openai/frontend/next.config.js b/axum/openai/frontend/next.config.js new file mode 100644 index 00000000..6b79dd8a --- /dev/null +++ b/axum/openai/frontend/next.config.js @@ -0,0 +1,10 @@ +const nextConfig = { + output: "export", + trailingSlash: true, + distDir: "dist", + images: { + unoptimized: true, + }, +}; + +export default nextConfig; diff --git a/axum/openai/frontend/package-lock.json b/axum/openai/frontend/package-lock.json new file mode 100644 index 00000000..5bd7698e --- /dev/null +++ b/axum/openai/frontend/package-lock.json @@ -0,0 +1,6319 @@ +{ + "name": "frontend", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "frontend", + "version": "0.1.0", + "dependencies": { + "next": "14", + "react": "18.2.0", + "react-dom": "18.2.0", + "react-markdown": "^9.0.1", + "remark-gfm": "^4.0.0" + }, + "devDependencies": { + "@types/node": "^20", + "@types/react": "^18", + "@types/react-dom": "^18", + "eslint": "^8", + "eslint-config-next": "15.0.3", + "postcss": "^8", + "tailwindcss": "^3.4.1", + "typescript": "^5" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@next/env": { + "version": "14.2.18", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.18.tgz", + "integrity": "sha512-2vWLOUwIPgoqMJKG6dt35fVXVhgM09tw4tK3/Q34GFXDrfiHlG7iS33VA4ggnjWxjiz9KV5xzfsQzJX6vGAekA==" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.0.3.tgz", + "integrity": "sha512-3Ln/nHq2V+v8uIaxCR6YfYo7ceRgZNXfTd3yW1ukTaFbO+/I8jNakrjYWODvG9BuR2v5kgVtH/C8r0i11quOgw==", + "dev": true, + "dependencies": { + "fast-glob": "3.3.1" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.2.18", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.18.tgz", + "integrity": "sha512-tOBlDHCjGdyLf0ube/rDUs6VtwNOajaWV+5FV/ajPgrvHeisllEdymY/oDgv2cx561+gJksfMUtqf8crug7sbA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.18", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.18.tgz", + "integrity": "sha512-uJCEjutt5VeJ30jjrHV1VIHCsbMYnEqytQgvREx+DjURd/fmKy15NaVK4aR/u98S1LGTnjq35lRTnRyygglxoA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.18", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.18.tgz", + "integrity": "sha512-IL6rU8vnBB+BAm6YSWZewc+qvdL1EaA+VhLQ6tlUc0xp+kkdxQrVqAnh8Zek1ccKHlTDFRyAft0e60gteYmQ4A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.18", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.18.tgz", + "integrity": "sha512-RCaENbIZqKKqTlL8KNd+AZV/yAdCsovblOpYFp0OJ7ZxgLNbV5w23CUU1G5On+0fgafrsGcW+GdMKdFjaRwyYA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.2.18", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.18.tgz", + "integrity": "sha512-3kmv8DlyhPRCEBM1Vavn8NjyXtMeQ49ID0Olr/Sut7pgzaQTo4h01S7Z8YNE0VtbowyuAL26ibcz0ka6xCTH5g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.18", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.18.tgz", + "integrity": "sha512-mliTfa8seVSpTbVEcKEXGjC18+TDII8ykW4a36au97spm9XMPqQTpdGPNBJ9RySSFw9/hLuaCMByluQIAnkzlw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.18", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.18.tgz", + "integrity": "sha512-J5g0UFPbAjKYmqS3Cy7l2fetFmWMY9Oao32eUsBPYohts26BdrMUyfCJnZFQkX9npYaHNDOWqZ6uV9hSDPw9NA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.18", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.18.tgz", + "integrity": "sha512-Ynxuk4ZgIpdcN7d16ivJdjsDG1+3hTvK24Pp8DiDmIa2+A4CfhJSEHHVndCHok6rnLUzAZD+/UOKESQgTsAZGg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.18", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.18.tgz", + "integrity": "sha512-dtRGMhiU9TN5nyhwzce+7c/4CCeykYS+ipY/4mIrGzJ71+7zNo55ZxCB7cAVuNqdwtYniFNR2c9OFQ6UdFIMcg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz", + "integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==", + "dev": true + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + }, + "node_modules/@swc/helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", + "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "dependencies": { + "@swc/counter": "^0.1.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" + }, + "node_modules/@types/node": { + "version": "20.17.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.6.tgz", + "integrity": "sha512-VEI7OdvK2wP7XHnsuXbAJnEpEkF6NjSN45QJlL4VGqZSXsnicpesdTWsg9RISeSdYd3yeRj/y3k5KGjUXYnFwQ==", + "dev": true, + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==" + }, + "node_modules/@types/react": { + "version": "18.3.12", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", + "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.15.0.tgz", + "integrity": "sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/type-utils": "8.15.0", + "@typescript-eslint/utils": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.15.0.tgz", + "integrity": "sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.15.0.tgz", + "integrity": "sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.15.0.tgz", + "integrity": "sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/utils": "8.15.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.15.0.tgz", + "integrity": "sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.15.0.tgz", + "integrity": "sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.15.0.tgz", + "integrity": "sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.15.0.tgz", + "integrity": "sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz", + "integrity": "sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001680", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001680.tgz", + "integrity": "sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/es-abstract": { + "version": "1.23.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.5.tgz", + "integrity": "sha512-vlmniQ0WNPwXqA0BnmwV3Ng7HxiGlh6r5U6JcTMNx8OilcAGqVJBHJcPjqOMaczU9fRuRK5Px2BdVyPRnKMMVQ==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.3", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.0.tgz", + "integrity": "sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.3", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-next": { + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.0.3.tgz", + "integrity": "sha512-IGP2DdQQrgjcr4mwFPve4DrCqo7CVVez1WoYY47XwKSrYO4hC0Dlb+iJA60i0YfICOzgNADIb8r28BpQ5Zs0wg==", + "dev": true, + "dependencies": { + "@next/eslint-plugin-next": "15.0.3", + "@rushstack/eslint-patch": "^1.10.3", + "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-react": "^7.35.0", + "eslint-plugin-react-hooks": "^5.0.0" + }, + "peerDependencies": { + "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.3.tgz", + "integrity": "sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA==", + "dev": true, + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.3.5", + "enhanced-resolve": "^5.15.0", + "eslint-module-utils": "^2.8.1", + "fast-glob": "^3.3.2", + "get-tsconfig": "^4.7.5", + "is-bun-module": "^1.0.2", + "is-glob": "^4.0.3" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "dev": true, + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "dev": true, + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", + "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.1.0", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0.tgz", + "integrity": "sha512-hIOwI+5hYGpJEc4uPRmz2ulCjAGD/N13Lukkh8cLV0i2IRk/bdZDYjgLVHj+U9Z704kLIdIO6iueGvxNur0sgw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", + "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.2.tgz", + "integrity": "sha512-1ngXYb+V9UT5h+PxNRa1O1FYguZK/XL+gkeqvp7EdHlB9oHUG0eYRo/vY5inBdcqo3RkPMC58/H94HvkbfGdyg==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/html-url-attributes": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", + "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/inline-style-parser": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", + "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==" + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bun-module": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.2.1.tgz", + "integrity": "sha512-AmidtEM6D6NmUiLOvvU7+IePxjEjOzra2h0pSrsfSAcXwl/83zLLXDByafUJy9k/rKK0pvXMLdwKwGHlX2Ke6Q==", + "dev": true, + "dependencies": { + "semver": "^7.6.3" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/iterator.prototype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz", + "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.1.tgz", + "integrity": "sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz", + "integrity": "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.0.0.tgz", + "integrity": "sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.3.tgz", + "integrity": "sha512-bfOjvNt+1AcbPLTFMFWY149nJz0OjmewJs3LQQ5pIyVGxP4CdOqNVJL6kTaM5c68p8q82Xv3nCyFfUnuEcH3UQ==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromark": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.1.tgz", + "integrity": "sha512-eBPdkcoCNvYcxQOAKAlceo5SNdzZWfF+FcSupREAzdAh9rRmE239CEQAiTwIgblwnoM8zzj35sZ5ZwvSEOF6Kw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.2.tgz", + "integrity": "sha512-FKjQKbxd1cibWMM1P9N+H8TwlgGgSkWZMmfuVucLCHaYqeSvJ0hFeHsIa65pA2nYbes0f8LDHPMrd9X7Ujxg9w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz", + "integrity": "sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.3.tgz", + "integrity": "sha512-VXJJuNxYWSoYL6AJ6OQECCFGhIU2GGHMw8tahogePBrjkG8aCCas3ibkp7RnVOSTClg2is05/R7maAhF1XyQMg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-types": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.1.tgz", + "integrity": "sha512-534m2WhVTddrcKVepwmVEVnUAmtrx9bfIjNoQHRqfnvdaHQiFytEhJoTgpWJvDEXCO5gLTQh3wYC1PgOJA4NSQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/next": { + "version": "14.2.18", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.18.tgz", + "integrity": "sha512-H9qbjDuGivUDEnK6wa+p2XKO+iMzgVgyr9Zp/4Iv29lKa+DYaxJGjOeEA+5VOvJh/M7HLiskehInSa0cWxVXUw==", + "dependencies": { + "@next/env": "14.2.18", + "@swc/helpers": "0.5.5", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "graceful-fs": "^4.2.11", + "postcss": "8.4.31", + "styled-jsx": "5.1.1" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=18.17.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "14.2.18", + "@next/swc-darwin-x64": "14.2.18", + "@next/swc-linux-arm64-gnu": "14.2.18", + "@next/swc-linux-arm64-musl": "14.2.18", + "@next/swc-linux-x64-gnu": "14.2.18", + "@next/swc-linux-x64-musl": "14.2.18", + "@next/swc-win32-arm64-msvc": "14.2.18", + "@next/swc-win32-ia32-msvc": "14.2.18", + "@next/swc-win32-x64-msvc": "14.2.18" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-entities": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", + "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "node_modules/react-markdown": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-9.0.1.tgz", + "integrity": "sha512-186Gw/vF1uRkydbsOIkcGXw7aHq0sZOCRFFjGrr7b9+nVZg4UfA4enXCaxm4fUzecU38sWfrNDitGhshuU7rdg==", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "html-url-attributes": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=18", + "react": ">=18" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", + "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", + "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.1.tgz", + "integrity": "sha512-g/osARvjkBXb6Wo0XvAeXQohVta8i84ACbenPpoSsxTOQH/Ae0/RGP4WZgnMH5pMLpsj4FG7OHmcIcXxpza8eQ==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-to-object": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.8.tgz", + "integrity": "sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==", + "dependencies": { + "inline-style-parser": "0.2.4" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sucrase/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.15.tgz", + "integrity": "sha512-r4MeXnfBmSOuKUWmXe6h2CcyfzJCEk4F0pptO5jlnYSIViUkVmsawj80N5h2lO3gwcmSb4n3PuN+e+GC1Guylw==", + "dev": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.6", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/tailwindcss/node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ts-api-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz", + "integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "dev": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/axum/openai/frontend/package.json b/axum/openai/frontend/package.json new file mode 100644 index 00000000..676551c0 --- /dev/null +++ b/axum/openai/frontend/package.json @@ -0,0 +1,29 @@ +{ + "name": "frontend", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "next": "14", + "react": "18.2.0", + "react-dom": "18.2.0", + "react-markdown": "^9.0.1", + "remark-gfm": "^4.0.0" + }, + "devDependencies": { + "@types/node": "^20", + "@types/react": "^18", + "@types/react-dom": "^18", + "eslint": "^8", + "eslint-config-next": "15.0.3", + "postcss": "^8", + "tailwindcss": "^3.4.1", + "typescript": "^5" + } +} diff --git a/axum/openai/frontend/postcss.config.mjs b/axum/openai/frontend/postcss.config.mjs new file mode 100644 index 00000000..1a69fd2a --- /dev/null +++ b/axum/openai/frontend/postcss.config.mjs @@ -0,0 +1,8 @@ +/** @type {import('postcss-load-config').Config} */ +const config = { + plugins: { + tailwindcss: {}, + }, +}; + +export default config; diff --git a/axum/openai/frontend/public/file.svg b/axum/openai/frontend/public/file.svg new file mode 100644 index 00000000..004145cd --- /dev/null +++ b/axum/openai/frontend/public/file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/axum/openai/frontend/public/globe.svg b/axum/openai/frontend/public/globe.svg new file mode 100644 index 00000000..567f17b0 --- /dev/null +++ b/axum/openai/frontend/public/globe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/axum/openai/frontend/public/next.svg b/axum/openai/frontend/public/next.svg new file mode 100644 index 00000000..5174b28c --- /dev/null +++ b/axum/openai/frontend/public/next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/axum/openai/frontend/public/shuttle-logo.webp b/axum/openai/frontend/public/shuttle-logo.webp new file mode 100644 index 0000000000000000000000000000000000000000..e26db693b333ddeb6aed1a354a4abdce73042568 GIT binary patch literal 47880 zcmeEs<8!B7&}MAgwv&l%+qTUKeiPfaZD(TJwryu(ZJu|xYX63<+NyJZ>$~ez^Xlug zvXr!@yoZX#Y$@-BFK4yn2r2Osr z^d0L6ioQ`^lhekv8WuMs>AWRw0#{E)+TNzUn=~Tz{Nl2~o6r1oy^ZR=cfD_-@(cjDy@wB-KDB zl|VmbALz>HOEiI4sny9+`SnL4!BncjPA6|FdC^|;KgAvWMczGsoMDwS;dw-Iq0`LSwmcMkh8t!F?38oPs<*lc z9i0X&fgDzptTF`?$4~|}YuUU#_*60e`R;`qe#ap`b+zjSBHW*0BO;CZ_SOgejMmKX z)D=shf0tx27$)$nQNF)r6y7Zu2f94j-;>C?saauBQqJh55?wXGdo^qHB3b3=6a>zA z(jq$$Fd3g|N!Y~RTl^6ol&2M9xd=>+-KvF!i+G+i{UMe*qd9MZ9}HML814X_IZ+B( z$2fdUZ5Pfuj{L3zWYkgOPxRWVDHOf2jI(yAHARTS|%gmmnO4XOVXi-8Ey-+g+>jX()OIG*$W( zqG{hRgLuC6JY9+1=MLCMFA9Nc)>>LYFcl{f*C-jh5-%#q!@ELg7G%E%&4WgSeu+ZT z!~N#MtJ0fe(ZXl{6NVVAuxnp)uXkbx8(*nXE)ze^cpdz zCTcrj?4o!GGmhM6!0h0L!Kk@V5P=ivD|^p#yaDx_J+X7P!i8hOB!ZL~Ce#SSLZgmH zy=d#!IBRTXPLMlqcK|Ls9Cz^|ApF?<4nr_lLTn`Bbnw9lE$u&_O#n95tJ_vp2{3l# zH||%0?h?M3jV+G#zlT@O?S$CXtTb?{%06Y@MeU<-;<4QHEMz7KR<(gQpVS`E)$l7y ze18at#x?ed@Yta$;Cro1Ra1f8Qj`byM-5Xu5PEROef;72$pfTgw?ai;y{rSl(Di>Zk z(1F`!7Yq)|rN~>xh#9brMC%Cb&Q?BcbWFq2ws7l4=__K$#|#GNQGV`J-}53P{B5Ut zSP-wwJ@@9D(WvQ<{ss5t�tZEH?l&+588!YvHU2`FLq!bYTQMS_c9 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 m{u@th^(;eWh|#)q96V*@@+oty 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 literal 0 HcmV?d00001 diff --git a/axum/openai/frontend/public/vercel.svg b/axum/openai/frontend/public/vercel.svg new file mode 100644 index 00000000..77053960 --- /dev/null +++ b/axum/openai/frontend/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/axum/openai/frontend/public/window.svg b/axum/openai/frontend/public/window.svg new file mode 100644 index 00000000..b2b2a44f --- /dev/null +++ b/axum/openai/frontend/public/window.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/axum/openai/frontend/tailwind.config.ts b/axum/openai/frontend/tailwind.config.ts new file mode 100644 index 00000000..1362b882 --- /dev/null +++ b/axum/openai/frontend/tailwind.config.ts @@ -0,0 +1,18 @@ +import type { Config } from "tailwindcss"; + +export default { + content: [ + "./pages/**/*.{js,ts,jsx,tsx,mdx}", + "./components/**/*.{js,ts,jsx,tsx,mdx}", + "./app/**/*.{js,ts,jsx,tsx,mdx}", + ], + theme: { + extend: { + colors: { + background: "var(--background)", + foreground: "var(--foreground)", + }, + }, + }, + plugins: [], +} satisfies Config; diff --git a/axum/openai/frontend/tsconfig.json b/axum/openai/frontend/tsconfig.json new file mode 100644 index 00000000..d4239c31 --- /dev/null +++ b/axum/openai/frontend/tsconfig.json @@ -0,0 +1,42 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": [ + "./*" + ] + } + }, + "include": [ + "**/*.ts", + "**/*.tsx", + "next-env.d.ts", + "static/types/**/*.ts", + ".next/types/**/*.ts", + "dist/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/axum/openai/hurl/register.hurl b/axum/openai/hurl/register.hurl new file mode 100644 index 00000000..7a3a48f7 --- /dev/null +++ b/axum/openai/hurl/register.hurl @@ -0,0 +1,38 @@ +POST http://localhost:8000/api/auth/register +{ + "username":"josh", + "password":"1234" +} + +HTTP 201 + +POST http://localhost:8000/api/auth/login +{ + "username":"josh", + "password":"1234" +} + +HTTP 200 + +[Captures] +session-id: cookie "token" + +POST http://localhost:8000/api/chat/create +Cookie: token={{session-id}} + +HTTP 200 + +[Captures] +conversation-id: jsonpath "$['conversation_id']" + +POST http://localhost:8000/api/chat/conversations/{{conversation-id}} +Cookie: token={{session-id}} +{ + "prompt":"Tell me about shuttle.dev", + "model":"gpt-4o-mini" +} + +HTTP 200 + +[Captures] +body: body diff --git a/axum/openai/justfile b/axum/openai/justfile new file mode 100644 index 00000000..5cd6bb32 --- /dev/null +++ b/axum/openai/justfile @@ -0,0 +1,19 @@ +up: + shuttle run + +fe: + npm --prefix ./frontend run dev + +build: + npm --prefix ./frontend run build + +deploy: + build + shuttle deploy + +deploy-ad: + build + shuttle deploy --ad + +test: + hurl hurl/register.hurl --verbose diff --git a/axum/openai/migrations/20241115220707_init.down.sql b/axum/openai/migrations/20241115220707_init.down.sql new file mode 100644 index 00000000..d2f607c5 --- /dev/null +++ b/axum/openai/migrations/20241115220707_init.down.sql @@ -0,0 +1 @@ +-- Add down migration script here diff --git a/axum/openai/migrations/20241115220707_init.up.sql b/axum/openai/migrations/20241115220707_init.up.sql new file mode 100644 index 00000000..ee333ece --- /dev/null +++ b/axum/openai/migrations/20241115220707_init.up.sql @@ -0,0 +1,16 @@ +-- Add up migration script here +CREATE TABLE IF NOT EXISTS users ( + id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + username VARCHAR NOT NULL, + password VARCHAR NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE IF NOT EXISTS conversations ( + user_id INT, + id INT GENERATED ALWAYS AS IDENTITY, + conversation JSONB DEFAULT '[]'::JSONB, + created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + last_updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + foreign key (user_id) references users(id) +); diff --git a/axum/openai/src/endpoints/auth.rs b/axum/openai/src/endpoints/auth.rs new file mode 100644 index 00000000..db39d9ce --- /dev/null +++ b/axum/openai/src/endpoints/auth.rs @@ -0,0 +1,190 @@ +use argon2::{ + password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString}, + Argon2, +}; +use axum::{ + extract::{FromRequestParts, State}, + http::StatusCode, + response::IntoResponse, + Json, +}; +use axum_extra::extract::{ + cookie::{Cookie, SameSite}, + PrivateCookieJar, +}; +use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation}; +use serde::{Deserialize, Serialize}; +use std::sync::LazyLock; + +use crate::state::AppState; + +#[derive(Deserialize)] +pub struct AuthRequest { + username: String, + password: String, +} + +#[derive(sqlx::FromRow)] +struct Password(i32, String); + +pub async fn register( + State(state): State, + Json(json): Json, +) -> Result { + let hash = hash_password(&json.password).unwrap(); + + if let Err(e) = sqlx::query("INSERT INTO users (username, password) VALUES ($1, $2)") + .bind(&json.username) + .bind(hash) + .execute(&state.db) + .await + { + return Err(( + StatusCode::INTERNAL_SERVER_ERROR, + format!("Error while registering: {e}"), + )); + } + + Ok(StatusCode::CREATED) +} + +pub async fn login( + jar: PrivateCookieJar, + State(state): State, + Json(json): Json, +) -> Result { + let user: Password = match sqlx::query_as("SELECT id, password FROM users WHERE username = $1") + .bind(&json.username) + .fetch_one(&state.db) + .await + { + Ok(user) => user, + Err(_) => { + return Err(( + StatusCode::INTERNAL_SERVER_ERROR, + "Incorrect password or username.", + )) + } + }; + + let parsed_hash = PasswordHash::new(&user.1).unwrap(); + if Argon2::default() + .verify_password(&json.password.into_bytes(), &parsed_hash) + .is_err() + { + return Err(( + StatusCode::INTERNAL_SERVER_ERROR, + "Incorrect password or username.", + )); + }; + + let cookie = Claims::new(user.0, &json.username).into_cookie(); + + Ok((StatusCode::OK, jar.add(cookie))) +} + +pub fn hash_password(password: &str) -> Result { + let password = password.as_bytes(); + + let salt = SaltString::generate(&mut OsRng); + + // Argon2 with default params (Argon2id v19) + let argon2 = Argon2::default(); + + // Hash password to PHC string ($argon2id$v=19$...) + + let hash = argon2.hash_password(password, &salt)?; + + Ok(hash.to_string()) +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Claims { + user_id: i32, + username: String, + exp: usize, +} + +#[axum::async_trait] +impl FromRequestParts for Claims { + type Rejection = (StatusCode, String); + async fn from_request_parts( + parts: &mut axum::http::request::Parts, + state: &AppState, + ) -> Result { + // error type is Infallible so we can unwrap here + let jar: PrivateCookieJar = PrivateCookieJar::from_request_parts(parts, state) + .await + .unwrap(); + let Some(token) = jar.get("token") else { + return Err((StatusCode::UNAUTHORIZED, "Unauthorized".to_string())); + }; + + let token = match decode::( + token.value_trimmed(), + &KEYS.decoding, + &Validation::default(), + ) { + Ok(token) => token, + Err(e) => { + println!("ERROR: Could not decode token {token}: {e}"); + return Err((StatusCode::UNAUTHORIZED, "Unauthorized".to_string())); + } + }; + + let claims = token.claims; + + Ok(claims) + } +} + +impl Claims { + pub fn new(user_id: i32, username: &str) -> Self { + let exp = 2000000000; + Self { + user_id, + username: username.to_string(), + exp, + } + } + + pub fn username(&self) -> &str { + &self.username + } + + pub fn user_id(&self) -> &i32 { + &self.user_id + } + + // Return a JWT value decoded as a cookie + pub fn into_cookie<'c>(self) -> Cookie<'c> { + let token = encode(&Header::default(), &self, &KEYS.encoding).unwrap(); + + let mut cookie = Cookie::new("token", token); + cookie.set_same_site(SameSite::Strict); + cookie.set_path("/"); + cookie.set_secure(true); + cookie.set_http_only(true); + + cookie + } +} + +static KEYS: LazyLock = LazyLock::new(|| { + let secret = std::env::var("JWT_SECRET").unwrap_or_else(|_| "Hello world!".to_string()); + Keys::new(secret.as_bytes()) +}); + +struct Keys { + decoding: DecodingKey, + encoding: EncodingKey, +} + +impl Keys { + fn new(secret: &[u8]) -> Self { + Self { + encoding: EncodingKey::from_secret(secret), + decoding: DecodingKey::from_secret(secret), + } + } +} diff --git a/axum/openai/src/endpoints/mod.rs b/axum/openai/src/endpoints/mod.rs new file mode 100644 index 00000000..9d315df1 --- /dev/null +++ b/axum/openai/src/endpoints/mod.rs @@ -0,0 +1,6 @@ +pub mod auth; +pub mod openai; + +pub async fn health_check() -> &'static str { + "Hello, world!" +} diff --git a/axum/openai/src/endpoints/openai.rs b/axum/openai/src/endpoints/openai.rs new file mode 100644 index 00000000..6de178ee --- /dev/null +++ b/axum/openai/src/endpoints/openai.rs @@ -0,0 +1,226 @@ +use axum::{ + extract::{Path, State}, + http::StatusCode, + response::IntoResponse, + Json, +}; +use serde::{Deserialize, Serialize}; +use serde_json::json; +use shuttle_openai::async_openai::types::{ + ChatCompletionRequestMessage, ChatCompletionRequestSystemMessageArgs, + ChatCompletionRequestUserMessageArgs, CreateChatCompletionRequestArgs, +}; +use sqlx::postgres::PgRow; +use sqlx::Row; + +use crate::state::AppState; + +use super::auth::Claims; + +#[derive(Deserialize)] +pub struct Request { + prompt: String, + model: String, +} + +#[derive(Serialize)] +struct Response { + conversation_id: i32, + response: String, +} + +impl Response { + fn new(conversation_id: i32, response: String) -> Self { + Self { + conversation_id, + response, + } + } +} + +#[derive(sqlx::FromRow, Serialize)] +struct ConversationId(i32); + +#[derive(Serialize)] +struct Conversation { + messages: Vec, +} + +impl Conversation { + fn new(messages: Vec) -> Self { + Self { messages } + } +} + +impl<'r> sqlx::FromRow<'r, PgRow> for Conversation { + fn from_row(row: &'r PgRow) -> Result { + let val: sqlx::types::JsonValue = row.try_get("conversation")?; + + let messages: Vec = serde_json::from_value(val).unwrap(); + + Ok(Self::new(messages)) + } +} + +#[derive(Deserialize, Serialize)] +struct ChatMessage { + role: String, + message: String, +} + +pub async fn create_chat(State(state): State, claims: Claims) -> impl IntoResponse { + let ConversationId(convo_id) = sqlx::query_as( + r#"INSERT INTO conversations + (user_id) + VALUES + ($1) + RETURNING id"#, + ) + .bind(claims.user_id()) + .fetch_one(&state.db) + .await + .unwrap(); + + Json(Response::new(convo_id, String::new())) +} + +pub async fn get_conversation_list( + State(state): State, + claims: Claims, +) -> impl IntoResponse { + let conversation_ids: Vec = + sqlx::query_as("SELECT ID from conversations WHERE user_id = $1 order by id desc") + .bind(claims.user_id()) + .fetch_all(&state.db) + .await + .unwrap(); + + Json(conversation_ids) +} + +pub async fn fetch_conversation_messages( + State(state): State, + Path(conversation_id): Path, + claims: Claims, +) -> Result { + let conversation: Conversation = match sqlx::query_as( + "SELECT CONVERSATION FROM conversations where id = $1 AND user_id = $2 + ", + ) + .bind(conversation_id) + .bind(claims.user_id()) + .fetch_one(&state.db) + .await + { + Ok(res) => res, + Err(e) => return Err((StatusCode::INTERNAL_SERVER_ERROR, e.to_string())), + }; + + Ok((StatusCode::OK, Json(conversation))) +} + +pub async fn send_message( + State(state): State, + Path(conversation_id): Path, + claims: Claims, + Json(req): Json, +) -> Result { + let conversation: Conversation = sqlx::query_as( + "SELECT CONVERSATION FROM conversations where id = $1 AND user_id = $2 + ", + ) + .bind(conversation_id) + .bind(claims.user_id()) + .fetch_one(&state.db) + .await + .unwrap_or_else(|_| Conversation { + messages: Vec::new(), + }); + + let mut chat_messages = Vec::new(); + + for message in conversation.messages { + let chat_message = match message.role.trim() { + "system" => ChatCompletionRequestMessage::System( + ChatCompletionRequestSystemMessageArgs::default() + .content(message.message) + .build() + .map_err(|_| { + Err::(( + StatusCode::INTERNAL_SERVER_ERROR, + "Invalid chat role".to_string(), + )) + }) + .unwrap(), + ), + + "user" => ChatCompletionRequestMessage::User( + ChatCompletionRequestUserMessageArgs::default() + .content(message.message) + .build() + .map_err(|_| { + Err::(( + StatusCode::INTERNAL_SERVER_ERROR, + "Invalid chat role".to_string(), + )) + }) + .unwrap(), + ), + + _ => { + return Err(( + StatusCode::INTERNAL_SERVER_ERROR, + "Invalid chat role".to_string(), + )) + } + }; + + chat_messages.push(chat_message) + } + + chat_messages.push( + ChatCompletionRequestUserMessageArgs::default() + .content(req.prompt.to_owned()) + .build() + .unwrap() + .into(), + ); + + let chat_req = CreateChatCompletionRequestArgs::default() + .model(&req.model) + .messages(chat_messages) + .n(1) + .build() + .unwrap(); + + let res = state.openai_client.chat().create(chat_req).await.unwrap(); + let reply: String = res + .choices + .first() + .unwrap() + .message + .content + .as_ref() + .unwrap() + .to_owned(); + + sqlx::query( + r#"UPDATE conversations + SET conversation = conversation || $1 + WHERE id = $2"#, + ) + .bind(json!([{ + "role": "user", + "message": &req.prompt, + }, + { + "role":"system", + "message": &reply + }])) + .bind(conversation_id) + .execute(&state.db) + .await + .unwrap(); + + Ok(Json(Response::new(conversation_id, reply))) +} diff --git a/axum/openai/src/main.rs b/axum/openai/src/main.rs index 1d6c794a..3812976b 100644 --- a/axum/openai/src/main.rs +++ b/axum/openai/src/main.rs @@ -1,53 +1,69 @@ -use std::sync::Arc; - -use async_openai::{ - config::OpenAIConfig, - types::{ - ChatCompletionRequestMessage, ChatCompletionRequestUserMessageArgs, - CreateChatCompletionRequestArgs, +use axum::{ + http::{ + header::{ACCEPT, AUTHORIZATION}, + Method, }, - Client, + routing::{get, post}, + Router, }; -use axum::{extract::State, routing::post, Json, Router}; -use serde_json::{json, Value}; -struct AppState { - openai: Client, -} +pub mod endpoints; +pub mod state; -async fn chat(State(state): State>, Json(v): Json) -> Result, ()> { - let user_msg: ChatCompletionRequestMessage = ChatCompletionRequestUserMessageArgs::default() - .content(v["message"].as_str().unwrap()) - .build() - .unwrap() - .into(); - let req = CreateChatCompletionRequestArgs::default() - .model("gpt-4o-mini") - .messages(vec![user_msg]) - .n(1) - .build() - .unwrap(); - let res = state.openai.chat().create(req).await.unwrap(); - let reply = res - .choices - .first() - .unwrap() - .message - .content - .as_ref() - .unwrap() - .to_owned(); - - Ok(Json(json!({ "response": reply }))) -} +use shuttle_openai::async_openai::{config::OpenAIConfig, Client}; +use shuttle_runtime::DeploymentMetadata; +use state::AppState; +use tower_http::{ + cors::CorsLayer, + services::{ServeDir, ServeFile}, +}; #[shuttle_runtime::main] async fn main( + #[shuttle_shared_db::Postgres] conn: String, #[shuttle_openai::OpenAI(api_key = "{secrets.OPENAI_API_KEY}")] openai: Client, + #[shuttle_runtime::Metadata] metadata: DeploymentMetadata, ) -> shuttle_axum::ShuttleAxum { - let state = Arc::new(AppState { openai }); + let state = AppState::new(conn, openai) + .await + .map_err(|e| format!("Could not create application state: {e}")) + .unwrap(); + + state.seed().await; + + let origin = if metadata.env == shuttle_runtime::Environment::Deployment { + format!("{}.shuttle.app", metadata.project_name) + } else { + "127.0.0.1:8000".to_string() + }; + + let cors = CorsLayer::new() + .allow_credentials(true) + .allow_origin(vec![origin.parse().unwrap()]) + .allow_headers(vec![AUTHORIZATION, ACCEPT]) + .allow_methods(vec![Method::GET, Method::POST]); - let router = Router::new().route("/", post(chat)).with_state(state); + let router = Router::new() + .route("/api/health", get(endpoints::health_check)) + .route("/api/auth/register", post(endpoints::auth::register)) + .route("/api/auth/login", post(endpoints::auth::login)) + .route( + "/api/chat/conversations", + get(endpoints::openai::get_conversation_list), + ) + .route( + "/api/chat/conversations/:id", + get(endpoints::openai::fetch_conversation_messages) + .post(endpoints::openai::send_message), + ) + .route("/api/chat/create", post(endpoints::openai::create_chat)) + .layer(cors) + .nest_service( + "/", + ServeDir::new("frontend/dist") + .not_found_service(ServeFile::new("frontend/dist/index.html")), + ) + .with_state(state); Ok(router.into()) } diff --git a/axum/openai/src/state.rs b/axum/openai/src/state.rs new file mode 100644 index 00000000..c37f6805 --- /dev/null +++ b/axum/openai/src/state.rs @@ -0,0 +1,37 @@ +use axum::extract::FromRef; +use axum_extra::extract::cookie::Key; +use shuttle_openai::async_openai::{config::OpenAIConfig, Client}; +use sqlx::PgPool; + +#[derive(Clone)] +pub struct AppState { + pub db: PgPool, + pub openai_client: Client, + key: Key, +} + +impl AppState { + pub async fn new( + conn_string: String, + openai_client: Client, + ) -> Result { + let db = PgPool::connect(&conn_string).await?; + + Ok(Self { + db, + openai_client, + key: Key::generate(), + }) + } + + pub async fn seed(&self) { + sqlx::migrate!().run(&self.db).await.unwrap(); + } +} + +// this impl tells `SignedCookieJar` how to access the key from our state +impl FromRef for Key { + fn from_ref(state: &AppState) -> Self { + state.key.clone() + } +} From e45e918e4d0f9491425f882b3ca37308d5006b9d Mon Sep 17 00:00:00 2001 From: Geoffrey Mureithi <95377562+geofmureithi@users.noreply.github.com> Date: Fri, 6 Dec 2024 17:07:51 +0300 Subject: [PATCH 188/239] chore: update shuttle-cron to latest versions and persist cron jobs (#194) --- shuttle-cron/Cargo.toml | 11 +++++---- shuttle-cron/src/main.rs | 49 +++++++++++++++------------------------- 2 files changed, 24 insertions(+), 36 deletions(-) diff --git a/shuttle-cron/Cargo.toml b/shuttle-cron/Cargo.toml index d6375298..15dad064 100644 --- a/shuttle-cron/Cargo.toml +++ b/shuttle-cron/Cargo.toml @@ -5,11 +5,12 @@ edition = "2021" publish = false [dependencies] -apalis = { version = "0.4.9", features = ["cron", "postgres", "extensions", "retry"] } +apalis = { version = "0.6", features = ["retry"] } +apalis-sql = { version = "0.6", features = ["postgres"] } +apalis-cron = { version = "0.6" } chrono = { version = "0.4.32", features = ["clock", "serde"] } serde = { version = "1.0.195", features = ["derive"] } -shuttle-runtime = "0.46.0" -shuttle-shared-db = { version = "0.46.0", features = ["postgres"] } -sqlx = { version = "0.7.1", features = ["runtime-tokio-native-tls", "postgres"] } +shuttle-runtime = "0.49.0" +shuttle-shared-db = { version = "0.49.0", features = ["postgres"] } +sqlx = { version = "0.8", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1" -tower = { version = "0.4.13" } diff --git a/shuttle-cron/src/main.rs b/shuttle-cron/src/main.rs index 3143a415..075d9dca 100644 --- a/shuttle-cron/src/main.rs +++ b/shuttle-cron/src/main.rs @@ -1,13 +1,13 @@ -use apalis::cron::CronStream; -use apalis::cron::Schedule; -use apalis::layers::{DefaultRetryPolicy, Extension, RetryLayer}; -use apalis::postgres::PostgresStorage; +use apalis::layers::retry::RetryPolicy; use apalis::prelude::*; +use apalis_cron::CronStream; +use apalis_cron::Schedule; +use apalis_sql::postgres::PostgresStorage; +use apalis_sql::Config; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use sqlx::{postgres::PgPoolOptions, PgPool}; use std::str::FromStr; -use tower::ServiceBuilder; #[derive(Clone)] struct CronjobData { @@ -27,14 +27,8 @@ impl From> for Reminder { } } -impl Job for Reminder { - const NAME: &'static str = "reminder::DailyReminder"; -} - -async fn say_hello_world(job: Reminder, ctx: JobContext) { +async fn say_hello_world(job: Reminder, svc: Data) { println!("Hello world from send_reminder()!"); - // this lets you use variables stored in the CronjobData struct - let svc = ctx.data_opt::().unwrap(); // this executes CronjobData::execute() svc.execute(job); } @@ -62,9 +56,13 @@ struct MyService { #[shuttle_runtime::async_trait] impl shuttle_runtime::Service for MyService { async fn bind(self, _addr: std::net::SocketAddr) -> Result<(), shuttle_runtime::Error> { - let storage = PostgresStorage::new(self.db); // set up storage - storage.setup().await.expect("Unable to run migrations :("); + PostgresStorage::setup(&self.db) + .await + .expect("Unable to run migrations :("); + + let config = Config::new("reminder::DailyReminder"); + let storage = PostgresStorage::new_with_config(self.db, config); let schedule = Schedule::from_str("* * * * * *").expect("Couldn't start the scheduler!"); @@ -72,28 +70,17 @@ impl shuttle_runtime::Service for MyService { message: "Hello world".to_string(), }; - // create a servicebuilder for the cronjob - let service = ServiceBuilder::new() - .layer(RetryLayer::new(DefaultRetryPolicy)) - .layer(Extension(cron_service_ext)) - .service(job_fn(say_hello_world)); + let persisted_cron = CronStream::new(schedule).pipe_to_storage(storage); // create a worker that uses the service created from the cronjob let worker = WorkerBuilder::new("morning-cereal") - .with_storage(storage.clone()) - .stream( - CronStream::new(schedule.clone()) - .timer(apalis::prelude::timer::TokioTimer) - .to_stream(), - ) - .build(service.clone()); + .data(cron_service_ext) + .retry(RetryPolicy::retries(5)) + .backend(persisted_cron) + .build_fn(say_hello_world); // start your worker up - Monitor::new() - .register(worker) - .run() - .await - .expect("Unable to start worker"); + worker.run().await; Ok(()) } From b1cdaac5f61bdb0248a78b4a6c8f0b90388ecce4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?On=C3=A8?= <43485962+c-git@users.noreply.github.com> Date: Mon, 16 Dec 2024 05:32:29 -0500 Subject: [PATCH 189/239] docs: add missing word (#195) The word "and" was missing from the sentence. Added it. --- actix-web/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-web/README.md b/actix-web/README.md index 0c2802ba..f810e86c 100644 --- a/actix-web/README.md +++ b/actix-web/README.md @@ -2,4 +2,4 @@ Normally one would configure an application with [Actix Web](https://docs.rs/actix-web/latest/actix_web/index.html) using the [App](https://docs.rs/actix-web/latest/actix_web/struct.App.html) struct. However, shuttle needs to move the users configuration across threads to start the server on our backend, and the `App` struct is `!Send` and `!Sync`. -That means that for shuttle to support Actix Web, we need to use the [ServiceConfig](https://docs.rs/actix-web/latest/actix_web/web/struct.ServiceConfig.html) struct. You should be able to configure your application like you normally would, but some steps may be a bit different. If you do you find something that you would expect to be possible not working, please reach out and let us know. +That means that for shuttle to support Actix Web, we need to use the [ServiceConfig](https://docs.rs/actix-web/latest/actix_web/web/struct.ServiceConfig.html) struct. You should be able to configure your application like you normally would, but some steps may be a bit different. If you do and you find something that you would expect to be possible not working, please reach out and let us know. From b1bea523580b3ac1e32efb667d20d206263d5716 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Tue, 7 Jan 2025 01:14:58 -0800 Subject: [PATCH 190/239] improvement: update libsql to 0.6.0 in Axum Turso example (#197) --- axum/turso/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index eb60f02e..dd90023a 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -8,7 +8,7 @@ axum = "0.7.3" shuttle-axum = "0.49.0" shuttle-runtime = "0.49.0" shuttle-turso = "0.49.0" -libsql = "0.3.1" +libsql = "0.6.0" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } serde_json = "1.0.99" From 3dcb9368b61b34c2d5699cfc110b21baceee038e Mon Sep 17 00:00:00 2001 From: oddgrd <29732646+oddgrd@users.noreply.github.com> Date: Tue, 7 Jan 2025 10:23:58 +0100 Subject: [PATCH 191/239] chore: v0.50.0 --- actix-web/clerk/backend/Cargo.toml | 4 ++-- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/htmx-crud/Cargo.toml | 6 +++--- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 4 ++-- axum/oauth2/Cargo.toml | 6 +++--- axum/openai/Cargo.toml | 8 ++++---- axum/postgres/Cargo.toml | 6 +++--- axum/qdrant/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- bevy/hello-world/server/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 6 +++--- loco/hello-world/Cargo.toml | 4 ++-- other/feature-flags/Cargo.toml | 4 ++-- other/standalone-binary/Cargo.toml | 4 ++-- poem/hello-world/Cargo.toml | 4 ++-- poise/hello-world/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/opendal-memory/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 4 ++-- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- salvo/image-rescaler/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 6 +++--- serenity/weather-forecast/Cargo.toml | 4 ++-- shuttle-cron/Cargo.toml | 4 ++-- thruster/hello-world/Cargo.toml | 4 ++-- tide/hello-world/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 47 files changed, 107 insertions(+), 107 deletions(-) diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml index 01ce5229..bbea1c5a 100644 --- a/actix-web/clerk/backend/Cargo.toml +++ b/actix-web/clerk/backend/Cargo.toml @@ -10,5 +10,5 @@ clerk-rs = "0.2.3" openssl-sys = { version = "0.9.9", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-actix-web = "0.50.0" +shuttle-runtime = "0.50.0" diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index 71f83ea1..4c0334d0 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.7.1" actix-session = { version = "0.9.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-actix-web = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 7838fdf4..3a34717f 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-actix-web = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 2e935ce9..8c5bc3c8 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-actix-web = "0.50.0" +shuttle-runtime = "0.50.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.49.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.50.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index d4ab777a..3c4d0a9d 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-actix-web = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index f2036e76..7326a905 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-actix-web = "0.50.0" +shuttle-runtime = "0.50.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 90108dc9..d2e54c8d 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-axum = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.28.2" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index 700b0348..cf113af4 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -9,9 +9,9 @@ askama_axum = "0.4.0" axum = "0.7.4" serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.49.0" -shuttle-runtime = "0.49.0" -shuttle-shared-db = { version = "0.49.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.50.0" +shuttle-runtime = "0.50.0" +shuttle-shared-db = { version = "0.50.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index 6965aaeb..f68a398f 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-axum = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index edcdec9a..9f416dbc 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-axum = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.28.2" diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index 4f571ba5..2e06fefd 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -11,9 +11,9 @@ chrono = { version = "0.4.35", features = ["clock"] } oauth2 = "4.4.1" reqwest = { version = "0.11.18", features = ["json"] } serde = { version = "1.0.183", features = ["derive"] } -shuttle-axum = "0.49.0" -shuttle-runtime = "0.49.0" -shuttle-shared-db = { version = "0.49.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.50.0" +shuttle-runtime = "0.50.0" +shuttle-shared-db = { version = "0.50.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["macros", "chrono"] } thiserror = "1.0.57" time = "0.3.25" diff --git a/axum/openai/Cargo.toml b/axum/openai/Cargo.toml index 12cc57e7..bd1bec48 100644 --- a/axum/openai/Cargo.toml +++ b/axum/openai/Cargo.toml @@ -20,7 +20,7 @@ sqlx = { version = "0.8.2", features = [ ] } tokio = { version = "1.28.2", features = ["macros", "rt-multi-thread"] } tower-http = { version = "0.6.2", features = ["cors", "fs"] } -shuttle-runtime = "0.49.0" -shuttle-axum = "0.49.0" -shuttle-shared-db = { version = "0.49.0", features = ["postgres"] } -shuttle-openai = "0.49.0" +shuttle-runtime = "0.50.0" +shuttle-axum = "0.50.0" +shuttle-shared-db = { version = "0.50.0", features = ["postgres"] } +shuttle-openai = "0.50.0" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 2796e91f..14ee9c19 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.49.0" -shuttle-runtime = "0.49.0" -shuttle-shared-db = { version = "0.49.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.50.0" +shuttle-runtime = "0.50.0" +shuttle-shared-db = { version = "0.50.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index 62a6b6d6..da4bf94c 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.10.1" -shuttle-axum = "0.49.0" -shuttle-qdrant = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-axum = "0.50.0" +shuttle-qdrant = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 6e057d9f..d6837b4c 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-axum = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index dd90023a..0e2759b2 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.49.0" -shuttle-runtime = "0.49.0" -shuttle-turso = "0.49.0" +shuttle-axum = "0.50.0" +shuttle-runtime = "0.50.0" +shuttle-turso = "0.50.0" libsql = "0.6.0" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index be93e51b..7045afda 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-axum = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/bevy/hello-world/server/Cargo.toml b/bevy/hello-world/server/Cargo.toml index 752a60af..937d3479 100644 --- a/bevy/hello-world/server/Cargo.toml +++ b/bevy/hello-world/server/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-axum = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index fbbdb321..e05216bf 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1", features = ["derive"] } -shuttle-service = "0.49.0" -shuttle-axum = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-service = "0.50.0" +shuttle-axum = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 93fafc26..f1d1aca2 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.49.0" +shuttle-runtime = "0.50.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index 23c730cf..c639c01c 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -10,7 +10,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-persist = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index db794b34..573a2168 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,9 +16,9 @@ lettre = "0.11.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.49.0" -shuttle-runtime = "0.49.0" -shuttle-shared-db = { version = "0.49.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.50.0" +shuttle-runtime = "0.50.0" +shuttle-shared-db = { version = "0.50.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index 5e904458..da874ce8 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -12,8 +12,8 @@ edition = "2021" async-trait = "0.1.74" axum = "0.7.1" loco-rs = { version = "0.9.0", default-features = false, features = ["cli"] } -shuttle-axum = "0.49.0" -shuttle-runtime = { version = "0.49.0", default-features = false } +shuttle-axum = "0.50.0" +shuttle-runtime = { version = "0.50.0", default-features = false } serde = "*" serde_json = "*" tokio = "1.33.0" diff --git a/other/feature-flags/Cargo.toml b/other/feature-flags/Cargo.toml index 48e87df8..c3aa9964 100644 --- a/other/feature-flags/Cargo.toml +++ b/other/feature-flags/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-axum = "0.50.0" +shuttle-runtime = "0.50.0" [features] # Shuttle will disable default features and enable the feature "shuttle" if it exists. diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 5ce98024..bcf16e16 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,6 +15,6 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-axum = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 50491120..ce90682c 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "3.0.0" -shuttle-poem = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-poem = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index a93fdae6..127326d7 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.6.1" -shuttle-runtime = "0.49.0" +shuttle-runtime = "0.50.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity -shuttle-serenity = "0.49.0" +shuttle-serenity = "0.50.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 2ff700ea..21e6706f 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" rocket_dyn_templates = { version = "0.1.0", features = ["handlebars"] } -shuttle-rocket = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-rocket = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 3b063abe..7a158916 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-rocket = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index b10bc8f1..348ed46b 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-rocket = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.26.0" diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index 200832d9..56726837 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -4,10 +4,10 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.49.0" -shuttle-opendal = "0.49.0" +shuttle-runtime = "0.50.0" +shuttle-opendal = "0.50.0" tokio = "1.26.0" -shuttle-rocket = "0.49.0" +shuttle-rocket = "0.50.0" opendal = "0.45" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 9c06843f..7a9698aa 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.49.0" -shuttle-runtime = "0.49.0" -shuttle-shared-db = { version = "0.49.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.50.0" +shuttle-runtime = "0.50.0" +shuttle-shared-db = { version = "0.50.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 875d04b2..5768b350 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-rocket = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index 9555bf25..0a913f5e 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-rocket = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 8e5c49e2..cd78c12f 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" nanoid = "0.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.49.0" -shuttle-runtime = "0.49.0" -shuttle-shared-db = { version = "0.49.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.50.0" +shuttle-runtime = "0.50.0" +shuttle-shared-db = { version = "0.50.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" url = "2.3.1" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index b32ab17c..835511b3 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-rocket = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index b988a186..5642f417 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] salvo = "0.63.0" -shuttle-salvo = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-salvo = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml index d51a68e7..8dfd3ee4 100644 --- a/salvo/image-rescaler/Cargo.toml +++ b/salvo/image-rescaler/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] image = "0.24.8" salvo = "0.63.0" -shuttle-salvo = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-salvo = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 9030b9c2..59c7ea3f 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.49.0" -shuttle-serenity = "0.49.0" +shuttle-runtime = "0.50.0" +shuttle-serenity = "0.50.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 9c3826e4..d4e99ac4 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.49.0" -shuttle-serenity = "0.49.0" -shuttle-shared-db = { version = "0.49.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.50.0" +shuttle-serenity = "0.50.0" +shuttle-shared-db = { version = "0.50.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/weather-forecast/Cargo.toml b/serenity/weather-forecast/Cargo.toml index fa656821..266c1837 100644 --- a/serenity/weather-forecast/Cargo.toml +++ b/serenity/weather-forecast/Cargo.toml @@ -8,7 +8,7 @@ anyhow = "1.0.66" reqwest = { version = "0.11.24", features = ["json"] } serde = "1.0.197" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.49.0" -shuttle-serenity = "0.49.0" +shuttle-runtime = "0.50.0" +shuttle-serenity = "0.50.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/shuttle-cron/Cargo.toml b/shuttle-cron/Cargo.toml index 15dad064..8dffe532 100644 --- a/shuttle-cron/Cargo.toml +++ b/shuttle-cron/Cargo.toml @@ -10,7 +10,7 @@ apalis-sql = { version = "0.6", features = ["postgres"] } apalis-cron = { version = "0.6" } chrono = { version = "0.4.32", features = ["clock", "serde"] } serde = { version = "1.0.195", features = ["derive"] } -shuttle-runtime = "0.49.0" -shuttle-shared-db = { version = "0.49.0", features = ["postgres"] } +shuttle-runtime = "0.50.0" +shuttle-shared-db = { version = "0.50.0", features = ["postgres"] } sqlx = { version = "0.8", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 0d3de3e7..9779c562 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-thruster = "0.50.0" +shuttle-runtime = "0.50.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index ad7e9d00..df764f12 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.49.0" -shuttle-runtime = "0.49.0" +shuttle-tide = "0.50.0" +shuttle-runtime = "0.50.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index feb280c4..4ae51a6e 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.49.0" -shuttle-tower = "0.49.0" +shuttle-runtime = "0.50.0" +shuttle-tower = "0.50.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index c6577f97..dfe20e00 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.49.0" +shuttle-actix-web = "0.50.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.49.0", default-features = false } +shuttle-runtime = { version = "0.50.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 4ccebf21..6ae1c191 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.49.0" -shuttle-warp = "0.49.0" +shuttle-runtime = "0.50.0" +shuttle-warp = "0.50.0" tokio = "1.26.0" warp = "0.3.3" From 5e2e5f2159cb1ee356b2a7e04690e3b9c849f7e6 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 8 Jan 2025 14:45:05 +0100 Subject: [PATCH 192/239] feat: rewrite url shortener with pg opendal --- rocket/url-shortener/Cargo.toml | 6 +- rocket/url-shortener/README.md | 24 ++----- .../migrations/20220324143837_urls.sql | 4 -- rocket/url-shortener/src/main.rs | 65 +++++++------------ templates.toml | 4 +- 5 files changed, 35 insertions(+), 68 deletions(-) delete mode 100644 rocket/url-shortener/migrations/20220324143837_urls.sql diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index cd78c12f..1201c645 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -5,11 +5,11 @@ edition = "2021" [dependencies] nanoid = "0.4.0" +opendal = "0.51" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" shuttle-rocket = "0.50.0" shuttle-runtime = "0.50.0" -shuttle-shared-db = { version = "0.50.0", features = ["postgres", "sqlx"] } -sqlx = "0.8.2" +shuttle-shared-db = { version = "0.50.0", features = ["opendal"] } tokio = "1.26.0" -url = "2.3.1" +url = "2.5.4" diff --git a/rocket/url-shortener/README.md b/rocket/url-shortener/README.md index 708beff5..ef5d1ea4 100644 --- a/rocket/url-shortener/README.md +++ b/rocket/url-shortener/README.md @@ -1,26 +1,14 @@ -# Url Shortener +# URL Shortener -A URL shortener that you can use from your terminal - built with shuttle, rocket and postgres/sqlx. +A URL shortener that you can use from your terminal - built with Shuttle, rocket and postgres with opendal. ## How to use it -You can use this URL shortener directly from your terminal. Just copy and paste this command to your terminal and replace `` with the URL that you want to shorten +POST a URL to like so: ```bash -curl -X POST -d '' https://s.shuttleapp.rs +curl -d 'https://shuttle.dev/' http://localhost:8000/ ``` -like this - -```bash -curl -X POST -d 'https://docs.rs/shuttle-service/latest/shuttle_service/' https://s.shuttleapp.rs -``` - -you will get the shortened URL back (something like this `https://s.shuttleapp.rs/RvpVU_`) - -## Project structure - -The project consists of the following files - -- `migrations` folder is for DB migration files created by [sqlx-cli](https://github.com/launchbadge/sqlx/tree/master/sqlx-cli) -- `src/main.rs` is where all the magic happens - it creates a shuttle service with two endpoints: one for creating new short URLs and one for handling shortened URLs. +You will get the shortened URL back (something like this `http://localhost:8000/0fvAo2`). +Visiting it will redirect you to the original URL. diff --git a/rocket/url-shortener/migrations/20220324143837_urls.sql b/rocket/url-shortener/migrations/20220324143837_urls.sql deleted file mode 100644 index 16144095..00000000 --- a/rocket/url-shortener/migrations/20220324143837_urls.sql +++ /dev/null @@ -1,4 +0,0 @@ -CREATE TABLE urls ( - id VARCHAR(6) PRIMARY KEY, - url VARCHAR NOT NULL -); diff --git a/rocket/url-shortener/src/main.rs b/rocket/url-shortener/src/main.rs index b7ca4d15..feb2b878 100644 --- a/rocket/url-shortener/src/main.rs +++ b/rocket/url-shortener/src/main.rs @@ -6,74 +6,57 @@ use rocket::{ response::{status, Redirect}, routes, State, }; -use serde::Serialize; -use sqlx::{FromRow, PgPool}; use url::Url; struct AppState { - pool: PgPool, -} - -#[derive(Serialize, FromRow)] -struct StoredURL { - pub id: String, - pub url: String, + op: opendal::Operator, } #[get("/")] async fn redirect(id: String, state: &State) -> Result> { - let stored_url: StoredURL = sqlx::query_as("SELECT * FROM urls WHERE id = $1") - .bind(id) - .fetch_one(&state.pool) + let url = state + .op + .read(&id.to_string()) .await - .map_err(|err| match err { - sqlx::Error::RowNotFound => status::Custom( + .map_err(|err| match err.kind() { + opendal::ErrorKind::NotFound => status::Custom( Status::NotFound, "the requested shortened URL does not exist".into(), ), - _ => status::Custom( - Status::InternalServerError, - "something went wrong, sorry 🤷".into(), - ), + _ => status::Custom(Status::InternalServerError, "something went wrong".into()), })?; - Ok(Redirect::to(stored_url.url)) + Ok(Redirect::to(String::from_utf8(url.to_vec()).unwrap())) } #[post("/", data = "")] -async fn shorten(url: String, state: &State) -> Result> { - let id = &nanoid::nanoid!(6); - - let parsed_url = Url::parse(&url).map_err(|err| { +async fn shorten<'r>( + url: String, + state: &State, + host: &'r rocket::http::uri::Host<'r>, +) -> Result> { + let _ = Url::parse(&url).map_err(|err| { status::Custom( Status::UnprocessableEntity, format!("url validation failed: {err}"), ) })?; + let id = &nanoid::nanoid!(6); - sqlx::query("INSERT INTO urls(id, url) VALUES ($1, $2)") - .bind(id) - .bind(parsed_url.as_str()) - .execute(&state.pool) + state + .op + .write(&id.to_string(), url.into_bytes()) .await - .map_err(|_| { - status::Custom( - Status::InternalServerError, - "something went wrong, sorry 🤷".into(), - ) - })?; + .map_err(|_| status::Custom(Status::InternalServerError, "something went wrong".into()))?; - Ok(format!("https://s.shuttleapp.rs/{id}")) + Ok(format!("http://{host}/{id}\n")) } #[shuttle_runtime::main] -async fn main(#[shuttle_shared_db::Postgres] pool: PgPool) -> shuttle_rocket::ShuttleRocket { - sqlx::migrate!() - .run(&pool) - .await - .expect("Failed to run migrations"); - - let state = AppState { pool }; +async fn main( + #[shuttle_shared_db::Postgres] op: opendal::Operator, +) -> shuttle_rocket::ShuttleRocket { + let state = AppState { op }; let rocket = rocket::build() .mount("/", routes![redirect, shorten]) .manage(state); diff --git a/templates.toml b/templates.toml index 1e9af22e..3a78a730 100644 --- a/templates.toml +++ b/templates.toml @@ -293,10 +293,10 @@ tags = ["rocket"] [templates.rocket-url-shortener] title = "URL shortener" -description = "Save long URLs behind a short one, with Postgres storage" +description = "Save long URLs behind a short one, with OpenDAL/Postgres storage" path = "rocket/url-shortener" use_cases = ["Web app", "Storage"] -tags = ["rocket", "database", "postgres"] +tags = ["rocket", "database", "opendal", "postgres"] [templates.salvo-image-rescaler] title = "Image Rescaler" From 8f6075693383931fa56b496042ba22f07cada759 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 8 Jan 2025 15:11:10 +0100 Subject: [PATCH 193/239] fix: feature name --- rocket/url-shortener/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 1201c645..b2d3639a 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -10,6 +10,6 @@ rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" shuttle-rocket = "0.50.0" shuttle-runtime = "0.50.0" -shuttle-shared-db = { version = "0.50.0", features = ["opendal"] } +shuttle-shared-db = { version = "0.50.0", features = ["opendal-postgres"] } tokio = "1.26.0" url = "2.5.4" From 592388f852888ecbbe921a0c94f0a6b7a99ee101 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Thu, 9 Jan 2025 13:49:40 +0100 Subject: [PATCH 194/239] feat: use axum 0.7/0.8 feature flags (#200) --- axum/hello-world/Cargo.toml | 2 +- axum/htmx-crud/Cargo.toml | 2 +- axum/jwt-authentication/Cargo.toml | 2 +- axum/metadata/Cargo.toml | 2 +- axum/oauth2/Cargo.toml | 2 +- axum/openai/Cargo.toml | 2 +- axum/postgres/Cargo.toml | 2 +- axum/qdrant/Cargo.toml | 2 +- axum/static-files/Cargo.toml | 2 +- axum/turso/Cargo.toml | 2 +- axum/websocket/Cargo.toml | 2 +- bevy/hello-world/server/Cargo.toml | 2 +- custom-resource/pdo/Cargo.toml | 2 +- fullstack-templates/saas/backend/Cargo.toml | 2 +- loco/hello-world/Cargo.toml | 2 +- other/feature-flags/Cargo.toml | 2 +- other/standalone-binary/Cargo.toml | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index d2e54c8d..314af37d 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = "0.7.4" +axum = "0.8.1" shuttle-axum = "0.50.0" shuttle-runtime = "0.50.0" tokio = "1.28.2" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index cf113af4..309dd069 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -9,7 +9,7 @@ askama_axum = "0.4.0" axum = "0.7.4" serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.50.0" +shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } shuttle-runtime = "0.50.0" shuttle-shared-db = { version = "0.50.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index f68a398f..b0afb955 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = "0.50.0" +shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } shuttle-runtime = "0.50.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index 9f416dbc..2746fcea 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.50.0" +shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } shuttle-runtime = "0.50.0" tokio = "1.28.2" diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index 2e06fefd..3366858c 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -11,7 +11,7 @@ chrono = { version = "0.4.35", features = ["clock"] } oauth2 = "4.4.1" reqwest = { version = "0.11.18", features = ["json"] } serde = { version = "1.0.183", features = ["derive"] } -shuttle-axum = "0.50.0" +shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } shuttle-runtime = "0.50.0" shuttle-shared-db = { version = "0.50.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["macros", "chrono"] } diff --git a/axum/openai/Cargo.toml b/axum/openai/Cargo.toml index bd1bec48..6c9d0bf8 100644 --- a/axum/openai/Cargo.toml +++ b/axum/openai/Cargo.toml @@ -21,6 +21,6 @@ sqlx = { version = "0.8.2", features = [ tokio = { version = "1.28.2", features = ["macros", "rt-multi-thread"] } tower-http = { version = "0.6.2", features = ["cors", "fs"] } shuttle-runtime = "0.50.0" -shuttle-axum = "0.50.0" +shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } shuttle-shared-db = { version = "0.50.0", features = ["postgres"] } shuttle-openai = "0.50.0" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 14ee9c19..ce5fe512 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = "0.50.0" +shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } shuttle-runtime = "0.50.0" shuttle-shared-db = { version = "0.50.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index da4bf94c..71af347b 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.10.1" -shuttle-axum = "0.50.0" +shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } shuttle-qdrant = "0.50.0" shuttle-runtime = "0.50.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index d6837b4c..94e867c5 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.50.0" +shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } shuttle-runtime = "0.50.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 0e2759b2..6be76322 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = "0.50.0" +shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } shuttle-runtime = "0.50.0" shuttle-turso = "0.50.0" libsql = "0.6.0" diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 7045afda..54f8319e 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = "0.50.0" +shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } shuttle-runtime = "0.50.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/bevy/hello-world/server/Cargo.toml b/bevy/hello-world/server/Cargo.toml index 937d3479..36d7c5f9 100644 --- a/bevy/hello-world/server/Cargo.toml +++ b/bevy/hello-world/server/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = "0.50.0" +shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } shuttle-runtime = "0.50.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index e05216bf..69a82ef3 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -8,6 +8,6 @@ async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1", features = ["derive"] } shuttle-service = "0.50.0" -shuttle-axum = "0.50.0" +shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } shuttle-runtime = "0.50.0" tokio = "1.28.2" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 573a2168..03e2e0d8 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,7 +16,7 @@ lettre = "0.11.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.50.0" +shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } shuttle-runtime = "0.50.0" shuttle-shared-db = { version = "0.50.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["time"] } diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index da874ce8..55a340a9 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -12,7 +12,7 @@ edition = "2021" async-trait = "0.1.74" axum = "0.7.1" loco-rs = { version = "0.9.0", default-features = false, features = ["cli"] } -shuttle-axum = "0.50.0" +shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } shuttle-runtime = { version = "0.50.0", default-features = false } serde = "*" serde_json = "*" diff --git a/other/feature-flags/Cargo.toml b/other/feature-flags/Cargo.toml index c3aa9964..de89805a 100644 --- a/other/feature-flags/Cargo.toml +++ b/other/feature-flags/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = "0.50.0" +shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } shuttle-runtime = "0.50.0" [features] diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index bcf16e16..3e4aa9c1 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,6 +15,6 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = "0.50.0" +shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } shuttle-runtime = "0.50.0" tokio = "1.28.2" From 26bb0b765f446ec1335ed025b68609b3da6c30a6 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Thu, 9 Jan 2025 16:29:59 +0100 Subject: [PATCH 195/239] url shortener use serde json operator --- rocket/url-shortener/src/main.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/rocket/url-shortener/src/main.rs b/rocket/url-shortener/src/main.rs index feb2b878..fd68e819 100644 --- a/rocket/url-shortener/src/main.rs +++ b/rocket/url-shortener/src/main.rs @@ -9,14 +9,20 @@ use rocket::{ use url::Url; struct AppState { - op: opendal::Operator, + op: shuttle_shared_db::SerdeJsonOperator, +} + +// for showcasing SerdeJsonOperator +#[derive(serde::Serialize, serde::Deserialize)] +struct U { + inner: String, } #[get("/")] async fn redirect(id: String, state: &State) -> Result> { - let url = state + let url: U = state .op - .read(&id.to_string()) + .read_serialized(&id) .await .map_err(|err| match err.kind() { opendal::ErrorKind::NotFound => status::Custom( @@ -26,7 +32,7 @@ async fn redirect(id: String, state: &State) -> Result status::Custom(Status::InternalServerError, "something went wrong".into()), })?; - Ok(Redirect::to(String::from_utf8(url.to_vec()).unwrap())) + Ok(Redirect::to(url.inner)) } #[post("/", data = "")] @@ -45,7 +51,7 @@ async fn shorten<'r>( state .op - .write(&id.to_string(), url.into_bytes()) + .write_serialized(&id.to_string(), &U { inner: url }) .await .map_err(|_| status::Custom(Status::InternalServerError, "something went wrong".into()))?; @@ -54,7 +60,7 @@ async fn shorten<'r>( #[shuttle_runtime::main] async fn main( - #[shuttle_shared_db::Postgres] op: opendal::Operator, + #[shuttle_shared_db::Postgres] op: shuttle_shared_db::SerdeJsonOperator, ) -> shuttle_rocket::ShuttleRocket { let state = AppState { op }; let rocket = rocket::build() From d68c4ff00f1dc73de2aa88b2814f34eaa0777c6f Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Thu, 9 Jan 2025 18:38:43 +0100 Subject: [PATCH 196/239] chore: bump salvo examples --- salvo/hello-world/Cargo.toml | 2 +- salvo/image-rescaler/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 5642f417..bd25fcbd 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -salvo = "0.63.0" +salvo = "0.75.0" shuttle-salvo = "0.50.0" shuttle-runtime = "0.50.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml index 8dfd3ee4..de7f4377 100644 --- a/salvo/image-rescaler/Cargo.toml +++ b/salvo/image-rescaler/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] image = "0.24.8" -salvo = "0.63.0" +salvo = "0.75.0" shuttle-salvo = "0.50.0" shuttle-runtime = "0.50.0" tokio = "1.26.0" From 9bf3f60d88d66f7f93e4054b9e2413a17b625e8e Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Thu, 9 Jan 2025 18:58:02 +0100 Subject: [PATCH 197/239] fix: bump opendal-memory example --- rocket/opendal-memory/Cargo.toml | 10 +++++----- rocket/opendal-memory/README.md | 7 ------- rocket/opendal-memory/src/main.rs | 2 +- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index 56726837..68c63e27 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -4,10 +4,10 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.50.0" -shuttle-opendal = "0.50.0" -tokio = "1.26.0" -shuttle-rocket = "0.50.0" -opendal = "0.45" +opendal = "0.51" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } +shuttle-opendal = "0.50.0" +shuttle-rocket = "0.50.0" +shuttle-runtime = "0.50.0" +tokio = "1.26.0" diff --git a/rocket/opendal-memory/README.md b/rocket/opendal-memory/README.md index 06a36220..f19c3c64 100644 --- a/rocket/opendal-memory/README.md +++ b/rocket/opendal-memory/README.md @@ -1,10 +1,3 @@ # OpenDAL Memory Storage This example shows that how to connect to an in-memory storage using OpenDAL. - -## Project structure - -The project consists of the following files - -- `Shuttle.toml` contains the name of the app -- `src/main.rs` is where all the magic happens - it creates a Shuttle service with two endpoints: one for adding new data and one for retrieving it back. diff --git a/rocket/opendal-memory/src/main.rs b/rocket/opendal-memory/src/main.rs index 566846ff..92fcb01c 100644 --- a/rocket/opendal-memory/src/main.rs +++ b/rocket/opendal-memory/src/main.rs @@ -34,7 +34,7 @@ async fn retrieve(path: String, state: &State) -> Result Date: Fri, 10 Jan 2025 10:50:09 +0100 Subject: [PATCH 198/239] chore: v0.51.0 --- actix-web/clerk/backend/Cargo.toml | 4 ++-- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/htmx-crud/Cargo.toml | 6 +++--- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 4 ++-- axum/oauth2/Cargo.toml | 6 +++--- axum/openai/Cargo.toml | 8 ++++---- axum/postgres/Cargo.toml | 6 +++--- axum/qdrant/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- bevy/hello-world/server/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- custom-service/request-scheduler/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 6 +++--- loco/hello-world/Cargo.toml | 4 ++-- other/feature-flags/Cargo.toml | 4 ++-- other/standalone-binary/Cargo.toml | 4 ++-- poem/hello-world/Cargo.toml | 4 ++-- poise/hello-world/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/opendal-memory/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 4 ++-- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- salvo/image-rescaler/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 6 +++--- serenity/weather-forecast/Cargo.toml | 4 ++-- shuttle-cron/Cargo.toml | 4 ++-- thruster/hello-world/Cargo.toml | 4 ++-- tide/hello-world/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 47 files changed, 107 insertions(+), 107 deletions(-) diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml index bbea1c5a..f7db8494 100644 --- a/actix-web/clerk/backend/Cargo.toml +++ b/actix-web/clerk/backend/Cargo.toml @@ -10,5 +10,5 @@ clerk-rs = "0.2.3" openssl-sys = { version = "0.9.9", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-actix-web = "0.51.0" +shuttle-runtime = "0.51.0" diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index 4c0334d0..4d65d016 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.7.1" actix-session = { version = "0.9.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-actix-web = "0.51.0" +shuttle-runtime = "0.51.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 3a34717f..f0465515 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-actix-web = "0.51.0" +shuttle-runtime = "0.51.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 8c5bc3c8..e95ba01c 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-actix-web = "0.51.0" +shuttle-runtime = "0.51.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.50.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.51.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index 3c4d0a9d..6e597139 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-actix-web = "0.51.0" +shuttle-runtime = "0.51.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 7326a905..27352350 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-actix-web = "0.51.0" +shuttle-runtime = "0.51.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 314af37d..d8720e8f 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.8.1" -shuttle-axum = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-axum = "0.51.0" +shuttle-runtime = "0.51.0" tokio = "1.28.2" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index 309dd069..ca14d53f 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -9,9 +9,9 @@ askama_axum = "0.4.0" axum = "0.7.4" serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.50.0" -shuttle-shared-db = { version = "0.50.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.51.0" +shuttle-shared-db = { version = "0.51.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index b0afb955..89a1b97c 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.50.0" +shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.51.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index 2746fcea..1651b0ef 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.50.0" +shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.51.0" tokio = "1.28.2" diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index 3366858c..21aa6409 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -11,9 +11,9 @@ chrono = { version = "0.4.35", features = ["clock"] } oauth2 = "4.4.1" reqwest = { version = "0.11.18", features = ["json"] } serde = { version = "1.0.183", features = ["derive"] } -shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.50.0" -shuttle-shared-db = { version = "0.50.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.51.0" +shuttle-shared-db = { version = "0.51.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["macros", "chrono"] } thiserror = "1.0.57" time = "0.3.25" diff --git a/axum/openai/Cargo.toml b/axum/openai/Cargo.toml index 6c9d0bf8..b59db67d 100644 --- a/axum/openai/Cargo.toml +++ b/axum/openai/Cargo.toml @@ -20,7 +20,7 @@ sqlx = { version = "0.8.2", features = [ ] } tokio = { version = "1.28.2", features = ["macros", "rt-multi-thread"] } tower-http = { version = "0.6.2", features = ["cors", "fs"] } -shuttle-runtime = "0.50.0" -shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } -shuttle-shared-db = { version = "0.50.0", features = ["postgres"] } -shuttle-openai = "0.50.0" +shuttle-runtime = "0.51.0" +shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } +shuttle-shared-db = { version = "0.51.0", features = ["postgres"] } +shuttle-openai = "0.51.0" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index ce5fe512..469fe8c3 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.50.0" -shuttle-shared-db = { version = "0.50.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.51.0" +shuttle-shared-db = { version = "0.51.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index 71af347b..e7eceaaf 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.10.1" -shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } -shuttle-qdrant = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } +shuttle-qdrant = "0.51.0" +shuttle-runtime = "0.51.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 94e867c5..b2527065 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.50.0" +shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.51.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 6be76322..4b7e06ea 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.50.0" -shuttle-turso = "0.50.0" +shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.51.0" +shuttle-turso = "0.51.0" libsql = "0.6.0" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 54f8319e..bfd83f55 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.50.0" +shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.51.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/bevy/hello-world/server/Cargo.toml b/bevy/hello-world/server/Cargo.toml index 36d7c5f9..24b48e1c 100644 --- a/bevy/hello-world/server/Cargo.toml +++ b/bevy/hello-world/server/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.50.0" +shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.51.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 69a82ef3..a39d12d0 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1", features = ["derive"] } -shuttle-service = "0.50.0" -shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.50.0" +shuttle-service = "0.51.0" +shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.51.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index f1d1aca2..707a53e9 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.50.0" +shuttle-runtime = "0.51.0" tokio = "1" diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml index c639c01c..1a56bebe 100644 --- a/custom-service/request-scheduler/Cargo.toml +++ b/custom-service/request-scheduler/Cargo.toml @@ -10,7 +10,7 @@ chrono = "0.4.24" cron = "0.12.0" reqwest = "0.11.17" serde = "1.0.163" -shuttle-persist = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-persist = "0.51.0" +shuttle-runtime = "0.51.0" tokio = "1.28.0" tracing = "0.1.37" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 03e2e0d8..90e3aa36 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,9 +16,9 @@ lettre = "0.11.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.50.0" -shuttle-shared-db = { version = "0.50.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.51.0" +shuttle-shared-db = { version = "0.51.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index 55a340a9..938594dc 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -12,8 +12,8 @@ edition = "2021" async-trait = "0.1.74" axum = "0.7.1" loco-rs = { version = "0.9.0", default-features = false, features = ["cli"] } -shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = { version = "0.50.0", default-features = false } +shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = { version = "0.51.0", default-features = false } serde = "*" serde_json = "*" tokio = "1.33.0" diff --git a/other/feature-flags/Cargo.toml b/other/feature-flags/Cargo.toml index de89805a..22d37b3b 100644 --- a/other/feature-flags/Cargo.toml +++ b/other/feature-flags/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.50.0" +shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.51.0" [features] # Shuttle will disable default features and enable the feature "shuttle" if it exists. diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 3e4aa9c1..42c9f7b7 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,6 +15,6 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = { version = "0.50.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.50.0" +shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.51.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index ce90682c..3e7dc6cf 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "3.0.0" -shuttle-poem = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-poem = "0.51.0" +shuttle-runtime = "0.51.0" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 127326d7..0c49c726 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.6.1" -shuttle-runtime = "0.50.0" +shuttle-runtime = "0.51.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity -shuttle-serenity = "0.50.0" +shuttle-serenity = "0.51.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 21e6706f..481e7b17 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" rocket_dyn_templates = { version = "0.1.0", features = ["handlebars"] } -shuttle-rocket = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-rocket = "0.51.0" +shuttle-runtime = "0.51.0" tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 7a158916..9fb826e1 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-rocket = "0.51.0" +shuttle-runtime = "0.51.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 348ed46b..8aef4cfb 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-rocket = "0.51.0" +shuttle-runtime = "0.51.0" tokio = "1.26.0" diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index 68c63e27..c077515b 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" opendal = "0.51" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-opendal = "0.50.0" -shuttle-rocket = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-opendal = "0.51.0" +shuttle-rocket = "0.51.0" +shuttle-runtime = "0.51.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 7a9698aa..b7161d88 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.50.0" -shuttle-runtime = "0.50.0" -shuttle-shared-db = { version = "0.50.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.51.0" +shuttle-runtime = "0.51.0" +shuttle-shared-db = { version = "0.51.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 5768b350..2420f550 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-rocket = "0.51.0" +shuttle-runtime = "0.51.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index 0a913f5e..e54778ad 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-rocket = "0.51.0" +shuttle-runtime = "0.51.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index b2d3639a..b84ad615 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -8,8 +8,8 @@ nanoid = "0.4.0" opendal = "0.51" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.50.0" -shuttle-runtime = "0.50.0" -shuttle-shared-db = { version = "0.50.0", features = ["opendal-postgres"] } +shuttle-rocket = "0.51.0" +shuttle-runtime = "0.51.0" +shuttle-shared-db = { version = "0.51.0", features = ["opendal-postgres"] } tokio = "1.26.0" url = "2.5.4" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 835511b3..b2ebabeb 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-rocket = "0.51.0" +shuttle-runtime = "0.51.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index bd25fcbd..8d9587cd 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] salvo = "0.75.0" -shuttle-salvo = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-salvo = "0.51.0" +shuttle-runtime = "0.51.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml index de7f4377..12854142 100644 --- a/salvo/image-rescaler/Cargo.toml +++ b/salvo/image-rescaler/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] image = "0.24.8" salvo = "0.75.0" -shuttle-salvo = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-salvo = "0.51.0" +shuttle-runtime = "0.51.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 59c7ea3f..2e31ad6f 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.50.0" -shuttle-serenity = "0.50.0" +shuttle-runtime = "0.51.0" +shuttle-serenity = "0.51.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index d4e99ac4..3f9ae083 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.50.0" -shuttle-serenity = "0.50.0" -shuttle-shared-db = { version = "0.50.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.51.0" +shuttle-serenity = "0.51.0" +shuttle-shared-db = { version = "0.51.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/weather-forecast/Cargo.toml b/serenity/weather-forecast/Cargo.toml index 266c1837..4ec466d3 100644 --- a/serenity/weather-forecast/Cargo.toml +++ b/serenity/weather-forecast/Cargo.toml @@ -8,7 +8,7 @@ anyhow = "1.0.66" reqwest = { version = "0.11.24", features = ["json"] } serde = "1.0.197" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.50.0" -shuttle-serenity = "0.50.0" +shuttle-runtime = "0.51.0" +shuttle-serenity = "0.51.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/shuttle-cron/Cargo.toml b/shuttle-cron/Cargo.toml index 8dffe532..e04caa75 100644 --- a/shuttle-cron/Cargo.toml +++ b/shuttle-cron/Cargo.toml @@ -10,7 +10,7 @@ apalis-sql = { version = "0.6", features = ["postgres"] } apalis-cron = { version = "0.6" } chrono = { version = "0.4.32", features = ["clock", "serde"] } serde = { version = "1.0.195", features = ["derive"] } -shuttle-runtime = "0.50.0" -shuttle-shared-db = { version = "0.50.0", features = ["postgres"] } +shuttle-runtime = "0.51.0" +shuttle-shared-db = { version = "0.51.0", features = ["postgres"] } sqlx = { version = "0.8", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 9779c562..61660527 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-thruster = "0.51.0" +shuttle-runtime = "0.51.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index df764f12..7745b2b8 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.50.0" -shuttle-runtime = "0.50.0" +shuttle-tide = "0.51.0" +shuttle-runtime = "0.51.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 4ae51a6e..807382fc 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.50.0" -shuttle-tower = "0.50.0" +shuttle-runtime = "0.51.0" +shuttle-tower = "0.51.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index dfe20e00..da0e9335 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.50.0" +shuttle-actix-web = "0.51.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.50.0", default-features = false } +shuttle-runtime = { version = "0.51.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 6ae1c191..f144c746 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.50.0" -shuttle-warp = "0.50.0" +shuttle-runtime = "0.51.0" +shuttle-warp = "0.51.0" tokio = "1.26.0" warp = "0.3.3" From 73bf0220b06c1ae62e084d4e49d83b53f8ef6523 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Tue, 14 Jan 2025 13:34:54 +0100 Subject: [PATCH 199/239] chore: bump loco to 0.14.0 (#202) * chore: loco 0.14.0 + shuttle 0.51.0 * fix: package name * update gitignore from shuttle cli --- loco/hello-world/.cargo/config.toml | 3 ++ loco/hello-world/.devcontainer/.env | 0 loco/hello-world/.devcontainer/Dockerfile | 8 ---- .../.devcontainer/devcontainer.json | 9 ----- .../.devcontainer/docker-compose.yml | 12 ------ loco/hello-world/.github/workflows/ci.yaml | 40 ++++++++++++++----- loco/hello-world/.gitignore | 11 +++-- loco/hello-world/.rustfmt.toml | 2 + loco/hello-world/Cargo.toml | 37 +++++++++-------- loco/hello-world/README.md | 25 ++++++------ loco/hello-world/Shuttle.toml | 9 +++++ loco/hello-world/config/development.yaml | 38 ++++++------------ loco/hello-world/config/production.yaml | 38 ++++++------------ loco/hello-world/config/test.yaml | 33 +++++---------- loco/hello-world/src/app.rs | 33 ++++++++++----- loco/hello-world/src/bin/shuttle.rs | 15 +++++-- loco/hello-world/src/controllers/home.rs | 4 +- loco/hello-world/src/initializers/mod.rs | 1 + loco/hello-world/src/lib.rs | 2 + loco/hello-world/src/tasks/mod.rs | 1 + loco/hello-world/tests/mod.rs | 1 + loco/hello-world/tests/requests/home.rs | 23 +++-------- .../snapshots/can_get_home@home_request.snap | 8 ---- loco/hello-world/tests/tasks/mod.rs | 1 + 24 files changed, 171 insertions(+), 183 deletions(-) delete mode 100644 loco/hello-world/.devcontainer/.env delete mode 100644 loco/hello-world/.devcontainer/Dockerfile delete mode 100644 loco/hello-world/.devcontainer/devcontainer.json delete mode 100644 loco/hello-world/.devcontainer/docker-compose.yml create mode 100644 loco/hello-world/.rustfmt.toml create mode 100644 loco/hello-world/Shuttle.toml create mode 100644 loco/hello-world/src/initializers/mod.rs create mode 100644 loco/hello-world/src/tasks/mod.rs delete mode 100644 loco/hello-world/tests/requests/snapshots/can_get_home@home_request.snap create mode 100644 loco/hello-world/tests/tasks/mod.rs diff --git a/loco/hello-world/.cargo/config.toml b/loco/hello-world/.cargo/config.toml index 8b040c15..56012377 100644 --- a/loco/hello-world/.cargo/config.toml +++ b/loco/hello-world/.cargo/config.toml @@ -1,2 +1,5 @@ [alias] loco = "run --bin hello_world-cli --" +loco-tool = "run --" + +playground = "run --example playground" \ No newline at end of file diff --git a/loco/hello-world/.devcontainer/.env b/loco/hello-world/.devcontainer/.env deleted file mode 100644 index e69de29b..00000000 diff --git a/loco/hello-world/.devcontainer/Dockerfile b/loco/hello-world/.devcontainer/Dockerfile deleted file mode 100644 index fd43f09b..00000000 --- a/loco/hello-world/.devcontainer/Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -FROM mcr.microsoft.com/vscode/devcontainers/rust:0-1 - -RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ - && apt-get -y install --no-install-recommends postgresql-client \ - && cargo install cargo-insta \ - && chown -R vscode /usr/local/cargo - -COPY .env /.env diff --git a/loco/hello-world/.devcontainer/devcontainer.json b/loco/hello-world/.devcontainer/devcontainer.json deleted file mode 100644 index 6aecc100..00000000 --- a/loco/hello-world/.devcontainer/devcontainer.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "Loco", - "dockerComposeFile": "docker-compose.yml", - "service": "app", - "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", - "forwardPorts": [ - 8000 - ] -} \ No newline at end of file diff --git a/loco/hello-world/.devcontainer/docker-compose.yml b/loco/hello-world/.devcontainer/docker-compose.yml deleted file mode 100644 index 3985587e..00000000 --- a/loco/hello-world/.devcontainer/docker-compose.yml +++ /dev/null @@ -1,12 +0,0 @@ -version: "3" - -services: - app: - build: - context: . - dockerfile: Dockerfile - command: sleep infinity - volumes: - - ../..:/workspaces:cached - env_file: - - .env diff --git a/loco/hello-world/.github/workflows/ci.yaml b/loco/hello-world/.github/workflows/ci.yaml index 15ee4a6a..75ba8a5e 100644 --- a/loco/hello-world/.github/workflows/ci.yaml +++ b/loco/hello-world/.github/workflows/ci.yaml @@ -21,11 +21,9 @@ jobs: steps: - name: Checkout the code uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@stable with: - profile: ${{ env.TOOLCHAIN_PROFILE }} toolchain: ${{ env.RUST_TOOLCHAIN }} - override: true components: rustfmt - name: Run cargo fmt uses: actions-rs/cargo@v1 @@ -43,11 +41,9 @@ jobs: steps: - name: Checkout the code uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@stable with: - profile: ${{ env.TOOLCHAIN_PROFILE }} toolchain: ${{ env.RUST_TOOLCHAIN }} - override: true - name: Setup Rust cache uses: Swatinem/rust-cache@v2 - name: Run cargo clippy @@ -62,15 +58,37 @@ jobs: permissions: contents: read + + services: + redis: + image: redis + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - "6379:6379" + postgres: + image: postgres + env: + POSTGRES_DB: postgres_test + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + ports: + - "5432:5432" + # Set health checks to wait until postgres has started + options: --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 steps: - name: Checkout the code uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@stable with: - profile: ${{ env.TOOLCHAIN_PROFILE }} toolchain: ${{ env.RUST_TOOLCHAIN }} - override: true - name: Setup Rust cache uses: Swatinem/rust-cache@v2 - name: Run cargo test @@ -78,3 +96,7 @@ jobs: with: command: test args: --all-features --all + env: + REDIS_URL: redis://localhost:${{job.services.redis.ports[6379]}} + DATABASE_URL: postgres://postgres:postgres@localhost:5432/postgres_test + diff --git a/loco/hello-world/.gitignore b/loco/hello-world/.gitignore index 5d5402d5..0af292ce 100644 --- a/loco/hello-world/.gitignore +++ b/loco/hello-world/.gitignore @@ -1,16 +1,19 @@ **/config/local.yaml +**/config/*.local.yaml +**/config/production.yaml # Generated by Cargo # will have compiled files and executables debug/ target/ -# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries -# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html -Cargo.lock - # These are backup files generated by rustfmt **/*.rs.bk # MSVC Windows builds of rustc generate these, which store debugging information *.pdb + +*.sqlite +/target +.shuttle* +Secrets*.toml diff --git a/loco/hello-world/.rustfmt.toml b/loco/hello-world/.rustfmt.toml new file mode 100644 index 00000000..d862e081 --- /dev/null +++ b/loco/hello-world/.rustfmt.toml @@ -0,0 +1,2 @@ +max_width = 100 +use_small_heuristics = "Default" diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index 938594dc..1b825c2d 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -4,21 +4,29 @@ name = "hello_world" version = "0.1.0" edition = "2021" +publish = false +default-run = "hello_world-cli" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[dependencies] +[workspace.dependencies] +loco-rs = { version = "0.14.0", default-features = false } -async-trait = "0.1.74" -axum = "0.7.1" -loco-rs = { version = "0.9.0", default-features = false, features = ["cli"] } -shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } +[dependencies] +shuttle-axum = "0.51.0" shuttle-runtime = { version = "0.51.0", default-features = false } -serde = "*" -serde_json = "*" -tokio = "1.33.0" -tracing = "0.1.40" + +loco-rs = { workspace = true , features = ["cli"] } +serde = { version = "1", features = ["derive"] } +serde_json = { version = "1" } +tokio = { version = "1.33.0", default-features = false, features = [ + "rt-multi-thread", +] } +async-trait = { version = "0.1.74" } +axum = { version = "0.8.1" } +tracing = { version = "0.1.40" } tracing-subscriber = { version = "0.3.17", features = ["env-filter", "json"] } +regex = { version = "1.11.1" } [[bin]] name = "hello_world-cli" @@ -30,10 +38,7 @@ name = "hello_world" path = "src/bin/shuttle.rs" [dev-dependencies] -serial_test = "*" -rstest = "*" -loco-rs = { version = "0.9.0", default-features = false, features = [ - "testing", - "cli", -] } -insta = { version = "*", features = ["redactions", "yaml", "filters"] } +loco-rs = { workspace = true, features = ["testing"] } +serial_test = { version = "3.1.1" } +rstest = { version = "0.21.0" } +insta = { version = "1.34.0", features = ["redactions", "yaml", "filters"] } \ No newline at end of file diff --git a/loco/hello-world/README.md b/loco/hello-world/README.md index 43915f96..3886fa67 100644 --- a/loco/hello-world/README.md +++ b/loco/hello-world/README.md @@ -1,18 +1,9 @@ -# Shuttle Loco template :train: +# Welcome to Loco :train: -Welcome to the [Loco](https://loco.rs) Hello World Shuttle Template, designed with a focus on controllers and views (response schema). This minimalistic template comes with several features to kickstart your project: +[Loco](https://loco.rs) is a web and API framework running on Rust. -## REST API Service without a Database - -* **Controllers:** Handle web requests parameters, body, validation, and render a response that is content-aware. We use Axum for the best performance, simplicity, and extensibility. Controllers also allow you to easily build middlewares, which can be used to add logic such as authentication, logging, or error handling before passing requests to the main controller actions. -* **Views:** Loco can integrate with templating engines to generate dynamic HTML content from templates. -* **Background Jobs:** Perform compute or I/O intensive jobs in the background with a Redis backed queue, or with threads. Implementing a worker is as simple as implementing a perform function for the Worker trait. -* **Scheduler:** Simplifies the traditional, often cumbersome crontab system, making it easier and more elegant to schedule tasks or shell scripts. -* **Mailers:** A mailer will deliver emails in the background using the existing loco background worker infrastructure. It will all be seamless for you. -* **Storage:** In Loco Storage, we facilitate working with files through multiple operations. Storage can be in-memory, on disk, or use cloud services such as AWS S3, GCP, and Azure. -* **Cache:** Loco provides an cache layer to improve application performance by storing frequently accessed data. - -So see more Loco features, check out our [documentation website](https://loco.rs/docs/getting-started/tour/). +This is the **SaaS starter** which includes a `User` model and authentication based on JWT. +It also include configuration sections that help you pick either a frontend or a server-side template set up for your fullstack server. ## Quick Start @@ -21,3 +12,11 @@ To launch your app, simply use the following command: ```sh shuttle run ``` + +## Full Stack Serving + +You can check your [configuration](config/development.yaml) to pick either frontend setup or server-side rendered template, and activate the relevant configuration sections. + +## Getting help + +Check out [a quick tour](https://loco.rs/docs/getting-started/tour/) or [the complete guide](https://loco.rs/docs/getting-started/guide/). diff --git a/loco/hello-world/Shuttle.toml b/loco/hello-world/Shuttle.toml new file mode 100644 index 00000000..6af3620b --- /dev/null +++ b/loco/hello-world/Shuttle.toml @@ -0,0 +1,9 @@ +[deploy] +include = [ + "config/production.yaml" +] + +[build] +assets = [ + "config/production.yaml" +] diff --git a/loco/hello-world/config/development.yaml b/loco/hello-world/config/development.yaml index 4f513991..d3b57319 100644 --- a/loco/hello-world/config/development.yaml +++ b/loco/hello-world/config/development.yaml @@ -4,9 +4,11 @@ logger: # Enable or disable logging. enable: true + # Enable pretty backtrace (sets RUST_BACKTRACE=1) + pretty_backtrace: true # Log level, options: trace, debug, info, warn or error. level: debug - # Define the logging format. options: compact, pretty or Json + # Define the logging format. options: compact, pretty or json format: compact # By default the logger has filtering only logs that came from your code or logs that came from `loco` framework. to see all third party libraries # Uncomment the line below to override to see all third party libraries you can enable this config and override the logger filters. @@ -15,31 +17,17 @@ logger: # Web server configuration server: # Port on which the server will listen. the server binding is 0.0.0.0:{PORT} - port: 8000 + port: 5150 + # Binding for the server (which interface to bind to) + binding: localhost # The UI hostname or IP address that mailers will point to. host: http://localhost # Out of the box middleware configuration. to disable middleware you can changed the `enable` field to `false` of comment the middleware block middlewares: - # Enable Etag cache header middleware - etag: - enable: true - # Allows to limit the payload size request. payload that bigger than this file will blocked the request. - limit_payload: - # Enable/Disable the middleware. - enable: true - # the limit size. can be b,kb,kib,mb,mib,gb,gib - body_limit: 5mb - # Generating a unique request ID and enhancing logging with additional information such as the start and completion of request processing, latency, status code, and other request details. - logger: - # Enable/Disable the middleware. - enable: true - # when your code is panicked, the request still returns 500 status code. - catch_panic: - # Enable/Disable the middleware. - enable: true - # Timeout for incoming requests middleware. requests that take more time from the configuration will cute and 408 status code will returned. - timeout_request: - # Enable/Disable the middleware. - enable: false - # Duration time in milliseconds. - timeout: 5000 + +# Initializers Configuration +# initializers: +# oauth2: +# authorization_code: # Authorization code grant type +# - client_identifier: google # Identifier for the OAuth2 provider. Replace 'google' with your provider's name if different, must be unique within the oauth2 config. +# ... other fields diff --git a/loco/hello-world/config/production.yaml b/loco/hello-world/config/production.yaml index 4f513991..d3b57319 100644 --- a/loco/hello-world/config/production.yaml +++ b/loco/hello-world/config/production.yaml @@ -4,9 +4,11 @@ logger: # Enable or disable logging. enable: true + # Enable pretty backtrace (sets RUST_BACKTRACE=1) + pretty_backtrace: true # Log level, options: trace, debug, info, warn or error. level: debug - # Define the logging format. options: compact, pretty or Json + # Define the logging format. options: compact, pretty or json format: compact # By default the logger has filtering only logs that came from your code or logs that came from `loco` framework. to see all third party libraries # Uncomment the line below to override to see all third party libraries you can enable this config and override the logger filters. @@ -15,31 +17,17 @@ logger: # Web server configuration server: # Port on which the server will listen. the server binding is 0.0.0.0:{PORT} - port: 8000 + port: 5150 + # Binding for the server (which interface to bind to) + binding: localhost # The UI hostname or IP address that mailers will point to. host: http://localhost # Out of the box middleware configuration. to disable middleware you can changed the `enable` field to `false` of comment the middleware block middlewares: - # Enable Etag cache header middleware - etag: - enable: true - # Allows to limit the payload size request. payload that bigger than this file will blocked the request. - limit_payload: - # Enable/Disable the middleware. - enable: true - # the limit size. can be b,kb,kib,mb,mib,gb,gib - body_limit: 5mb - # Generating a unique request ID and enhancing logging with additional information such as the start and completion of request processing, latency, status code, and other request details. - logger: - # Enable/Disable the middleware. - enable: true - # when your code is panicked, the request still returns 500 status code. - catch_panic: - # Enable/Disable the middleware. - enable: true - # Timeout for incoming requests middleware. requests that take more time from the configuration will cute and 408 status code will returned. - timeout_request: - # Enable/Disable the middleware. - enable: false - # Duration time in milliseconds. - timeout: 5000 + +# Initializers Configuration +# initializers: +# oauth2: +# authorization_code: # Authorization code grant type +# - client_identifier: google # Identifier for the OAuth2 provider. Replace 'google' with your provider's name if different, must be unique within the oauth2 config. +# ... other fields diff --git a/loco/hello-world/config/test.yaml b/loco/hello-world/config/test.yaml index 67603bba..863ff0ca 100644 --- a/loco/hello-world/config/test.yaml +++ b/loco/hello-world/config/test.yaml @@ -4,9 +4,11 @@ logger: # Enable or disable logging. enable: false + # Enable pretty backtrace (sets RUST_BACKTRACE=1) + pretty_backtrace: true # Log level, options: trace, debug, info, warn or error. level: debug - # Define the logging format. options: compact, pretty or Json + # Define the logging format. options: compact, pretty or json format: compact # By default the logger has filtering only logs that came from your code or logs that came from `loco` framework. to see all third party libraries # Uncomment the line below to override to see all third party libraries you can enable this config and override the logger filters. @@ -15,28 +17,15 @@ logger: # Web server configuration server: # Port on which the server will listen. the server binding is 0.0.0.0:{PORT} - port: 8000 + port: 5150 # The UI hostname or IP address that mailers will point to. host: http://localhost # Out of the box middleware configuration. to disable middleware you can changed the `enable` field to `false` of comment the middleware block middlewares: - # Allows to limit the payload size request. payload that bigger than this file will blocked the request. - limit_payload: - # Enable/Disable the middleware. - enable: true - # the limit size. can be b,kb,kib,mb,mib,gb,gib - body_limit: 5mb - # Generating a unique request ID and enhancing logging with additional information such as the start and completion of request processing, latency, status code, and other request details. - logger: - # Enable/Disable the middleware. - enable: true - # when your code is panicked, the request still returns 500 status code. - catch_panic: - # Enable/Disable the middleware. - enable: true - # Timeout for incoming requests middleware. requests that take more time from the configuration will cute and 408 status code will returned. - timeout_request: - # Enable/Disable the middleware. - enable: false - # Duration time in milliseconds. - timeout: 5000 + +# Initializers Configuration +# initializers: +# oauth2: +# authorization_code: # Authorization code grant type +# - client_identifier: google # Identifier for the OAuth2 provider. Replace 'google' with your provider's name if different, must be unique within the oauth2 config. +# ... other fields diff --git a/loco/hello-world/src/app.rs b/loco/hello-world/src/app.rs index 5068ff94..f20bd31b 100644 --- a/loco/hello-world/src/app.rs +++ b/loco/hello-world/src/app.rs @@ -1,15 +1,17 @@ use async_trait::async_trait; use loco_rs::{ - app::{AppContext, Hooks}, + app::{AppContext, Hooks, Initializer}, + bgworker::Queue, boot::{create_app, BootResult, StartMode}, + config::Config, controller::AppRoutes, environment::Environment, task::Tasks, - worker::Processor, Result, }; -use crate::controllers; +#[allow(unused_imports)] +use crate::{controllers, tasks}; pub struct App; #[async_trait] @@ -28,17 +30,28 @@ impl Hooks for App { ) } - async fn boot(mode: StartMode, environment: &Environment) -> Result { - create_app::(mode, environment).await + async fn boot( + mode: StartMode, + environment: &Environment, + config: Config, + ) -> Result { + create_app::(mode, environment, config).await + } + + async fn initializers(_ctx: &AppContext) -> Result>> { + Ok(vec![]) } fn routes(_ctx: &AppContext) -> AppRoutes { - AppRoutes::empty() - // .prefix("/api") + AppRoutes::with_default_routes() // controller routes below .add_route(controllers::home::routes()) } + async fn connect_workers(_ctx: &AppContext, _queue: &Queue) -> Result<()> { + Ok(()) + } - fn connect_workers<'a>(_p: &'a mut Processor, _ctx: &'a AppContext) {} - - fn register_tasks(_tasks: &mut Tasks) {} + #[allow(unused_variables)] + fn register_tasks(tasks: &mut Tasks) { + // tasks-inject (do not remove) + } } diff --git a/loco/hello-world/src/bin/shuttle.rs b/loco/hello-world/src/bin/shuttle.rs index c68f027e..42987fe7 100644 --- a/loco/hello-world/src/bin/shuttle.rs +++ b/loco/hello-world/src/bin/shuttle.rs @@ -1,16 +1,25 @@ -use hello_world::app::App; use loco_rs::boot::{create_app, StartMode}; use loco_rs::environment::Environment; +use hello_world::app::App; + +use shuttle_runtime::DeploymentMetadata; #[shuttle_runtime::main] async fn main( - #[shuttle_runtime::Metadata] meta: shuttle_runtime::DeploymentMetadata, + + #[shuttle_runtime::Metadata] meta: DeploymentMetadata, ) -> shuttle_axum::ShuttleAxum { + let environment = match meta.env { shuttle_runtime::Environment::Local => Environment::Development, shuttle_runtime::Environment::Deployment => Environment::Production, }; - let boot_result = create_app::(StartMode::ServerOnly, &environment) + + let config = environment + .load() + .expect("Failed to load configuration from the environment"); + + let boot_result = create_app::(StartMode::ServerOnly, &environment, config) .await .unwrap(); diff --git a/loco/hello-world/src/controllers/home.rs b/loco/hello-world/src/controllers/home.rs index 863b4b9b..0d6430f6 100644 --- a/loco/hello-world/src/controllers/home.rs +++ b/loco/hello-world/src/controllers/home.rs @@ -1,11 +1,13 @@ +use axum::debug_handler; use loco_rs::prelude::*; use crate::views::home::HomeResponse; +#[debug_handler] async fn current() -> Result { format::json(HomeResponse::new("loco")) } pub fn routes() -> Routes { - Routes::new().add("/", get(current)) + Routes::new().prefix("/api").add("/", get(current)) } diff --git a/loco/hello-world/src/initializers/mod.rs b/loco/hello-world/src/initializers/mod.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/loco/hello-world/src/initializers/mod.rs @@ -0,0 +1 @@ + diff --git a/loco/hello-world/src/lib.rs b/loco/hello-world/src/lib.rs index 0827f2da..6389c422 100644 --- a/loco/hello-world/src/lib.rs +++ b/loco/hello-world/src/lib.rs @@ -1,3 +1,5 @@ pub mod app; pub mod controllers; +pub mod initializers; +pub mod tasks; pub mod views; diff --git a/loco/hello-world/src/tasks/mod.rs b/loco/hello-world/src/tasks/mod.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/loco/hello-world/src/tasks/mod.rs @@ -0,0 +1 @@ + diff --git a/loco/hello-world/tests/mod.rs b/loco/hello-world/tests/mod.rs index c2e46cdd..c788ab7c 100644 --- a/loco/hello-world/tests/mod.rs +++ b/loco/hello-world/tests/mod.rs @@ -1 +1,2 @@ mod requests; +mod tasks; diff --git a/loco/hello-world/tests/requests/home.rs b/loco/hello-world/tests/requests/home.rs index 6a9246ad..4a843209 100644 --- a/loco/hello-world/tests/requests/home.rs +++ b/loco/hello-world/tests/requests/home.rs @@ -1,28 +1,15 @@ use hello_world::app::App; -use insta::assert_debug_snapshot; -use loco_rs::testing; +use loco_rs::testing::prelude::*; use serial_test::serial; -// TODO: see how to dedup / extract this to app-local test utils -// not to framework, because that would require a runtime dep on insta -macro_rules! configure_insta { - ($($expr:expr),*) => { - let mut settings = insta::Settings::clone_current(); - settings.set_prepend_module_to_snapshot(false); - settings.set_snapshot_suffix("home_request"); - let _guard = settings.bind_to_scope(); - }; -} - #[tokio::test] #[serial] async fn can_get_home() { - configure_insta!(); - - testing::request::(|request, _ctx| async move { - let notes = request.get("/").await; + request::(|request, _ctx| async move { + let res = request.get("/api").await; - assert_debug_snapshot!((notes.status_code(), notes.text())); + assert_eq!(res.status_code(), 200); + res.assert_json(&serde_json::json!({"app_name":"loco"})); }) .await; } diff --git a/loco/hello-world/tests/requests/snapshots/can_get_home@home_request.snap b/loco/hello-world/tests/requests/snapshots/can_get_home@home_request.snap deleted file mode 100644 index a686e3f4..00000000 --- a/loco/hello-world/tests/requests/snapshots/can_get_home@home_request.snap +++ /dev/null @@ -1,8 +0,0 @@ ---- -source: tests/requests/home.rs -expression: "(notes.status_code(), notes.text())" ---- -( - 200, - "{\"app_name\":\"loco\"}", -) diff --git a/loco/hello-world/tests/tasks/mod.rs b/loco/hello-world/tests/tasks/mod.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/loco/hello-world/tests/tasks/mod.rs @@ -0,0 +1 @@ + From 17959f64d92eda5976953f572e4a98d3694ddf06 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 15 Jan 2025 20:47:02 +0100 Subject: [PATCH 200/239] chore: remove custom service that depends on shuttle-persist --- custom-service/request-scheduler/Cargo.toml | 16 -- custom-service/request-scheduler/README.md | 25 --- custom-service/request-scheduler/request.sh | 6 - custom-service/request-scheduler/src/error.rs | 13 -- custom-service/request-scheduler/src/lib.rs | 173 ------------------ custom-service/request-scheduler/src/main.rs | 25 --- .../request-scheduler/src/router.rs | 28 --- templates.toml | 7 - 8 files changed, 293 deletions(-) delete mode 100644 custom-service/request-scheduler/Cargo.toml delete mode 100644 custom-service/request-scheduler/README.md delete mode 100644 custom-service/request-scheduler/request.sh delete mode 100644 custom-service/request-scheduler/src/error.rs delete mode 100644 custom-service/request-scheduler/src/lib.rs delete mode 100644 custom-service/request-scheduler/src/main.rs delete mode 100644 custom-service/request-scheduler/src/router.rs diff --git a/custom-service/request-scheduler/Cargo.toml b/custom-service/request-scheduler/Cargo.toml deleted file mode 100644 index 1a56bebe..00000000 --- a/custom-service/request-scheduler/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "request-scheduler" -version = "0.1.0" -edition = "2021" -publish = false - -[dependencies] -axum = "0.7.3" -chrono = "0.4.24" -cron = "0.12.0" -reqwest = "0.11.17" -serde = "1.0.163" -shuttle-persist = "0.51.0" -shuttle-runtime = "0.51.0" -tokio = "1.28.0" -tracing = "0.1.37" diff --git a/custom-service/request-scheduler/README.md b/custom-service/request-scheduler/README.md deleted file mode 100644 index 5f90e955..00000000 --- a/custom-service/request-scheduler/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# request-scheduler - -A service that calls URLs at specified cron-style intervals. - -The service exposes a `/crontab/set` endpoint that accepts a schedule and a URL -as form data and persists jobs with `shuttle_persist` between runs, e.g. it will -pick up existing jobs after being restarted. - -Internally, `CrontabService` implements a custom service with -[`shuttle_runtime::Service`](https://docs.shuttle.rs/examples/custom-service), -uses [`shuttle_persist`](https://docs.shuttle.rs/resources/shuttle-persist), -and sets up an [`axum::Server`](https://github.com/tokio-rs/axum) that sends -jobs to a `CronRunner`. - -# Usage -Run `shuttle run` to spin up the service locally. - -Fire a POST request to the `set-schedule` URL to create a new cron job. Use -the provided `request.sh` for a quick example or the below snippet: - -``` -curl -v http://localhost:8000/crontab/set\ - -H "Content-Type: application/x-www-form-urlencoded"\ - -d "schedule='*/2 * * * * *'&url='http://localhost:8000/trigger-me'" -``` diff --git a/custom-service/request-scheduler/request.sh b/custom-service/request-scheduler/request.sh deleted file mode 100644 index 9b045d66..00000000 --- a/custom-service/request-scheduler/request.sh +++ /dev/null @@ -1,6 +0,0 @@ -SCHEDULE="*/2 * * * * *" -URL="http://localhost:8000/trigger-me" - -curl -v http://localhost:8000/crontab/set\ - -H "Content-Type: application/x-www-form-urlencoded"\ - -d "schedule=$SCHEDULE&url=$URL" diff --git a/custom-service/request-scheduler/src/error.rs b/custom-service/request-scheduler/src/error.rs deleted file mode 100644 index 586462a6..00000000 --- a/custom-service/request-scheduler/src/error.rs +++ /dev/null @@ -1,13 +0,0 @@ -use axum::{ - http::StatusCode, - response::{IntoResponse, Response}, -}; - -#[derive(Debug)] -pub(crate) struct CrontabServiceError; - -impl IntoResponse for CrontabServiceError { - fn into_response(self) -> Response { - (StatusCode::INTERNAL_SERVER_ERROR).into_response() - } -} diff --git a/custom-service/request-scheduler/src/lib.rs b/custom-service/request-scheduler/src/lib.rs deleted file mode 100644 index 3b049285..00000000 --- a/custom-service/request-scheduler/src/lib.rs +++ /dev/null @@ -1,173 +0,0 @@ -use std::str::FromStr; -use std::sync::Arc; - -use axum::Router; -use chrono::Utc; -use cron::Schedule; -use router::make_router; -use serde::{Deserialize, Serialize}; -use shuttle_persist::PersistInstance; -use tokio::{ - sync::mpsc::{self, Receiver, Sender}, - sync::oneshot, - time::sleep, -}; -use tracing::{debug, info}; - -mod error; -use error::CrontabServiceError; - -mod router; - -pub type ShuttleCrontab = Result; - -type Responder = oneshot::Sender>; - -#[derive(Debug, Serialize, Deserialize)] -pub struct RawJob { - schedule: String, - url: String, -} - -#[derive(Debug)] -enum Msg { - NewJob(RawJob, Responder<()>), -} - -#[derive(Debug, Serialize, Deserialize)] -struct Crontab { - jobs: Vec, -} - -#[derive(Debug)] -struct CronJob { - schedule: Schedule, - url: String, -} - -impl CronJob { - async fn run(&self) { - debug!("Running job for: {}", self.url); - while let Some(next_run) = self.schedule.upcoming(Utc).next() { - let next_run_in = next_run - .signed_duration_since(chrono::offset::Utc::now()) - .to_std() - .unwrap(); - sleep(next_run_in).await; - - let res = reqwest::get(self.url.clone()).await.unwrap(); - info!("Called {} with response {}", self.url, res.status()); - } - } -} - -impl From<&RawJob> for CronJob { - fn from(raw: &RawJob) -> Self { - let schedule = Schedule::from_str(&raw.schedule).expect("Failed to parse schedule"); - Self { - schedule, - url: raw.url.clone(), - } - } -} - -struct CronRunner { - persist: PersistInstance, - receiver: Receiver, -} - -impl CronRunner { - async fn run_jobs(&mut self) { - if let Ok(tab) = self.persist.load::("crontab") { - debug!("Found {} jobs", tab.jobs.len()); - for raw in tab.jobs { - debug!("Starting job: {:?}", raw); - let job = CronJob::from(&raw); - - tokio::spawn(async move { - job.run().await; - }); - } - } else { - info!("Didn't find any jobs. POST to /crontab/set to create one."); - } - - while let Some(msg) = self.receiver.recv().await { - let (raw, resp) = match msg { - Msg::NewJob(raw, resp) => (raw, resp), - }; - debug!("Channel received: {:?}", raw); - - let mut crontab = match self.persist.load::("crontab") { - Ok(tab) => tab, - Err(_) => Crontab { jobs: vec![] }, - }; - - let job = CronJob::from(&raw); - - crontab.jobs.push(raw); - - debug!("Persisting {:?} jobs", crontab.jobs.len()); - let res = self - .persist - .save("crontab", crontab) - .map_err(|_| CrontabServiceError); - let _ = resp.send(res); - - tokio::spawn(async move { - job.run().await; - }); - } - } -} - -pub struct CrontabService { - router: Router, - runner: CronRunner, -} - -struct CrontabServiceState { - sender: Sender, -} - -impl CrontabService { - pub fn new( - persist: PersistInstance, - user_router: Router, - ) -> Result { - let (sender, receiver) = mpsc::channel(32); - - let cron_runner = CronRunner { persist, receiver }; - let cron_state = Arc::new(CrontabServiceState { sender }); - let cron_router = make_router(cron_state); - - let router = user_router.nest("/crontab", cron_router); - - Ok(Self { - router, - runner: cron_runner, - }) - } -} - -#[shuttle_runtime::async_trait] -impl shuttle_runtime::Service for CrontabService { - async fn bind(mut self, addr: std::net::SocketAddr) -> Result<(), shuttle_runtime::Error> { - let router = self.router; - let mut runner = self.runner; - - let server = async move { - axum::serve( - shuttle_runtime::tokio::net::TcpListener::bind(addr) - .await - .unwrap(), - router, - ) - .await - }; - - let (_runner_hdl, _axum_hdl) = tokio::join!(runner.run_jobs(), server); - - Ok(()) - } -} diff --git a/custom-service/request-scheduler/src/main.rs b/custom-service/request-scheduler/src/main.rs deleted file mode 100644 index 7ff2893c..00000000 --- a/custom-service/request-scheduler/src/main.rs +++ /dev/null @@ -1,25 +0,0 @@ -use axum::{response::IntoResponse, routing::get, Router}; -use shuttle_persist::{Persist, PersistInstance}; - -use request_scheduler::{CrontabService, ShuttleCrontab}; - -async fn hello_crontab() -> impl IntoResponse { - "Hello there, try making a POST request to '/crontab/set' to create a new job.".to_string() -} - -async fn trigger_me() -> impl IntoResponse { - "Triggered by the crontab service".to_string() -} - -#[shuttle_runtime::main] -async fn crontab(#[Persist] persist: PersistInstance) -> ShuttleCrontab { - // A userland router, so to speak. Will be the primary router mounted at "/", - // while the `CrontabService` has its own router mounted at "/crontab", as - // defined in `router.rs`. - // See lib.rs for more documentation. - let user_router = Router::new() - .route("/", get(hello_crontab)) - .route("/trigger-me", get(trigger_me)); - - CrontabService::new(persist, user_router) -} diff --git a/custom-service/request-scheduler/src/router.rs b/custom-service/request-scheduler/src/router.rs deleted file mode 100644 index 727b2282..00000000 --- a/custom-service/request-scheduler/src/router.rs +++ /dev/null @@ -1,28 +0,0 @@ -use std::sync::Arc; - -use axum::extract::State; -use axum::response::IntoResponse; -use axum::routing::post; -use axum::{extract::Form, Router}; -use tokio::sync::oneshot; -use tracing::debug; - -use crate::{CrontabServiceState, Msg, RawJob}; - -pub(crate) fn make_router(cron_state: Arc) -> Router { - Router::new() - .route("/set", post(set_schedule)) - .with_state(cron_state) -} - -async fn set_schedule( - State(state): State>, - Form(job): Form, -) -> impl IntoResponse { - debug!("Accepted new job: {:?}", job); - let (tx, rx) = oneshot::channel(); - - state.sender.send(Msg::NewJob(job, tx)).await.unwrap(); - - rx.await.expect("Channel transmission failed") -} diff --git a/templates.toml b/templates.toml index 3a78a730..fb696fcb 100644 --- a/templates.toml +++ b/templates.toml @@ -242,13 +242,6 @@ path = "axum/websocket" use_cases = ["Web app", "Monitoring"] tags = ["axum", "websocket"] -[templates.request-scheduler] -title = "Request Scheduler" -description = "Schedule requests with a cron schedule" -path = "custom-service/request-scheduler" -use_cases = ["Web app", "Cron jobs", "Storage"] -tags = ["axum"] - [templates.axum-next-fullstack-saas] title = "Fullstack SaaS" description = "Opinionated fullstack web app with pre-made routes and assets" From 82ead5546e0b4e761cfc746875f66825d5cb1438 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 15 Jan 2025 20:47:14 +0100 Subject: [PATCH 201/239] links --- axum/static-files/assets/index.html | 2 +- fullstack-templates/saas/README.md | 6 +++--- serenity/weather-forecast/README.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/axum/static-files/assets/index.html b/axum/static-files/assets/index.html index 42f4d4e4..2ee2eb56 100644 --- a/axum/static-files/assets/index.html +++ b/axum/static-files/assets/index.html @@ -7,7 +7,7 @@
-

Axum static file server on Shuttle

+

Axum static file server on Shuttle

This is an example of serving static HTML, CSS, and JS files with Axum and running it with Shuttle.

diff --git a/fullstack-templates/saas/README.md b/fullstack-templates/saas/README.md index be6310d5..c41072f6 100644 --- a/fullstack-templates/saas/README.md +++ b/fullstack-templates/saas/README.md @@ -17,9 +17,9 @@ users will be able to view their customers, sales records as well as some analyt ## Pre-requisites - Rust -- Node.js/NPM. -- Typescript. -- [cargo-shuttle](https://www.shuttle.rs) +- Node.js/NPM +- Typescript +- Shuttle CLI ## Instructions for Usage diff --git a/serenity/weather-forecast/README.md b/serenity/weather-forecast/README.md index 34b9de58..ef477545 100644 --- a/serenity/weather-forecast/README.md +++ b/serenity/weather-forecast/README.md @@ -1,3 +1,3 @@ # Serenity Weather Forecast Bot with Shuttle -For a full tutorial on how to build and set up this bot, please refer to [Shuttle docs](https://docs.shuttle.rs/templates/tutorials/discord-weather-forecast) +For a full tutorial on how to build and set up this bot, please refer to [Shuttle docs](https://docs.shuttle.dev/templates/tutorials/discord-weather-forecast) From ce1653bf442975cb4e5f56ada841aa06fdbe9f6a Mon Sep 17 00:00:00 2001 From: kikniknik Date: Mon, 27 Jan 2025 00:20:33 +0200 Subject: [PATCH 202/239] rocket: Include Rocket.toml in build assets (#204) --- rocket/dyn-templates/Shuttle.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/rocket/dyn-templates/Shuttle.toml b/rocket/dyn-templates/Shuttle.toml index dd80627d..fbf90b77 100644 --- a/rocket/dyn-templates/Shuttle.toml +++ b/rocket/dyn-templates/Shuttle.toml @@ -1,4 +1,5 @@ [build] assets = [ + "Rocket.toml", "templates", ] From e91535a2c071e5d2810f281b01cd509a60ed7f24 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Tue, 4 Feb 2025 14:28:42 +0100 Subject: [PATCH 203/239] chore: v0.52.0 --- actix-web/clerk/backend/Cargo.toml | 4 ++-- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/htmx-crud/Cargo.toml | 6 +++--- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 4 ++-- axum/oauth2/Cargo.toml | 6 +++--- axum/openai/Cargo.toml | 8 ++++---- axum/postgres/Cargo.toml | 6 +++--- axum/qdrant/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- bevy/hello-world/server/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- fullstack-templates/saas/backend/Cargo.toml | 6 +++--- loco/hello-world/Cargo.toml | 4 ++-- other/feature-flags/Cargo.toml | 4 ++-- other/standalone-binary/Cargo.toml | 4 ++-- poem/hello-world/Cargo.toml | 4 ++-- poise/hello-world/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/opendal-memory/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 4 ++-- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- salvo/image-rescaler/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 6 +++--- serenity/weather-forecast/Cargo.toml | 4 ++-- shuttle-cron/Cargo.toml | 4 ++-- thruster/hello-world/Cargo.toml | 4 ++-- tide/hello-world/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 46 files changed, 105 insertions(+), 105 deletions(-) diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml index f7db8494..5e9839df 100644 --- a/actix-web/clerk/backend/Cargo.toml +++ b/actix-web/clerk/backend/Cargo.toml @@ -10,5 +10,5 @@ clerk-rs = "0.2.3" openssl-sys = { version = "0.9.9", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.51.0" -shuttle-runtime = "0.51.0" +shuttle-actix-web = "0.52.0" +shuttle-runtime = "0.52.0" diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index 4d65d016..4908534d 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.7.1" actix-session = { version = "0.9.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.51.0" -shuttle-runtime = "0.51.0" +shuttle-actix-web = "0.52.0" +shuttle-runtime = "0.52.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index f0465515..d0f7ee2e 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.51.0" -shuttle-runtime = "0.51.0" +shuttle-actix-web = "0.52.0" +shuttle-runtime = "0.52.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index e95ba01c..3d986861 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.51.0" -shuttle-runtime = "0.51.0" +shuttle-actix-web = "0.52.0" +shuttle-runtime = "0.52.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.51.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.52.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index 6e597139..01f91196 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.51.0" -shuttle-runtime = "0.51.0" +shuttle-actix-web = "0.52.0" +shuttle-runtime = "0.52.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 27352350..b9378df8 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.51.0" -shuttle-runtime = "0.51.0" +shuttle-actix-web = "0.52.0" +shuttle-runtime = "0.52.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index d8720e8f..ec5f08b7 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.8.1" -shuttle-axum = "0.51.0" -shuttle-runtime = "0.51.0" +shuttle-axum = "0.52.0" +shuttle-runtime = "0.52.0" tokio = "1.28.2" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index ca14d53f..1317c5e4 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -9,9 +9,9 @@ askama_axum = "0.4.0" axum = "0.7.4" serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.51.0" -shuttle-shared-db = { version = "0.51.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.52.0" +shuttle-shared-db = { version = "0.52.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index 89a1b97c..8f8226bc 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.51.0" +shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.52.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index 1651b0ef..f78002e3 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.51.0" +shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.52.0" tokio = "1.28.2" diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index 21aa6409..6ea5eec7 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -11,9 +11,9 @@ chrono = { version = "0.4.35", features = ["clock"] } oauth2 = "4.4.1" reqwest = { version = "0.11.18", features = ["json"] } serde = { version = "1.0.183", features = ["derive"] } -shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.51.0" -shuttle-shared-db = { version = "0.51.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.52.0" +shuttle-shared-db = { version = "0.52.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["macros", "chrono"] } thiserror = "1.0.57" time = "0.3.25" diff --git a/axum/openai/Cargo.toml b/axum/openai/Cargo.toml index b59db67d..bc4fbe7b 100644 --- a/axum/openai/Cargo.toml +++ b/axum/openai/Cargo.toml @@ -20,7 +20,7 @@ sqlx = { version = "0.8.2", features = [ ] } tokio = { version = "1.28.2", features = ["macros", "rt-multi-thread"] } tower-http = { version = "0.6.2", features = ["cors", "fs"] } -shuttle-runtime = "0.51.0" -shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } -shuttle-shared-db = { version = "0.51.0", features = ["postgres"] } -shuttle-openai = "0.51.0" +shuttle-runtime = "0.52.0" +shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } +shuttle-shared-db = { version = "0.52.0", features = ["postgres"] } +shuttle-openai = "0.52.0" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 469fe8c3..ee4eec20 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.51.0" -shuttle-shared-db = { version = "0.51.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.52.0" +shuttle-shared-db = { version = "0.52.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index e7eceaaf..52f3e054 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.10.1" -shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } -shuttle-qdrant = "0.51.0" -shuttle-runtime = "0.51.0" +shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } +shuttle-qdrant = "0.52.0" +shuttle-runtime = "0.52.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index b2527065..79ba0993 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.51.0" +shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.52.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 4b7e06ea..ae5c5df4 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.51.0" -shuttle-turso = "0.51.0" +shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.52.0" +shuttle-turso = "0.52.0" libsql = "0.6.0" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index bfd83f55..46b57c81 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.51.0" +shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.52.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/bevy/hello-world/server/Cargo.toml b/bevy/hello-world/server/Cargo.toml index 24b48e1c..75f8cc9a 100644 --- a/bevy/hello-world/server/Cargo.toml +++ b/bevy/hello-world/server/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.51.0" +shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.52.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index a39d12d0..966612d8 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1", features = ["derive"] } -shuttle-service = "0.51.0" -shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.51.0" +shuttle-service = "0.52.0" +shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.52.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 707a53e9..0361c68e 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.51.0" +shuttle-runtime = "0.52.0" tokio = "1" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 90e3aa36..0eb494d0 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,9 +16,9 @@ lettre = "0.11.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.51.0" -shuttle-shared-db = { version = "0.51.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.52.0" +shuttle-shared-db = { version = "0.52.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index 1b825c2d..56e56c98 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -13,8 +13,8 @@ default-run = "hello_world-cli" loco-rs = { version = "0.14.0", default-features = false } [dependencies] -shuttle-axum = "0.51.0" -shuttle-runtime = { version = "0.51.0", default-features = false } +shuttle-axum = "0.52.0" +shuttle-runtime = { version = "0.52.0", default-features = false } loco-rs = { workspace = true , features = ["cli"] } serde = { version = "1", features = ["derive"] } diff --git a/other/feature-flags/Cargo.toml b/other/feature-flags/Cargo.toml index 22d37b3b..bf934add 100644 --- a/other/feature-flags/Cargo.toml +++ b/other/feature-flags/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.51.0" +shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.52.0" [features] # Shuttle will disable default features and enable the feature "shuttle" if it exists. diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 42c9f7b7..2cd2693c 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,6 +15,6 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = { version = "0.51.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.51.0" +shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.52.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 3e7dc6cf..07644e3e 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "3.0.0" -shuttle-poem = "0.51.0" -shuttle-runtime = "0.51.0" +shuttle-poem = "0.52.0" +shuttle-runtime = "0.52.0" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 0c49c726..89022b11 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.6.1" -shuttle-runtime = "0.51.0" +shuttle-runtime = "0.52.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity -shuttle-serenity = "0.51.0" +shuttle-serenity = "0.52.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 481e7b17..8859c956 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" rocket_dyn_templates = { version = "0.1.0", features = ["handlebars"] } -shuttle-rocket = "0.51.0" -shuttle-runtime = "0.51.0" +shuttle-rocket = "0.52.0" +shuttle-runtime = "0.52.0" tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 9fb826e1..f526fa5c 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.51.0" -shuttle-runtime = "0.51.0" +shuttle-rocket = "0.52.0" +shuttle-runtime = "0.52.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 8aef4cfb..ec4156ab 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.51.0" -shuttle-runtime = "0.51.0" +shuttle-rocket = "0.52.0" +shuttle-runtime = "0.52.0" tokio = "1.26.0" diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index c077515b..f421daf2 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" opendal = "0.51" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-opendal = "0.51.0" -shuttle-rocket = "0.51.0" -shuttle-runtime = "0.51.0" +shuttle-opendal = "0.52.0" +shuttle-rocket = "0.52.0" +shuttle-runtime = "0.52.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index b7161d88..b6a3ba84 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.51.0" -shuttle-runtime = "0.51.0" -shuttle-shared-db = { version = "0.51.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.52.0" +shuttle-runtime = "0.52.0" +shuttle-shared-db = { version = "0.52.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 2420f550..ae4a6385 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.51.0" -shuttle-runtime = "0.51.0" +shuttle-rocket = "0.52.0" +shuttle-runtime = "0.52.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index e54778ad..8558c3aa 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.51.0" -shuttle-runtime = "0.51.0" +shuttle-rocket = "0.52.0" +shuttle-runtime = "0.52.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index b84ad615..31721791 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -8,8 +8,8 @@ nanoid = "0.4.0" opendal = "0.51" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.51.0" -shuttle-runtime = "0.51.0" -shuttle-shared-db = { version = "0.51.0", features = ["opendal-postgres"] } +shuttle-rocket = "0.52.0" +shuttle-runtime = "0.52.0" +shuttle-shared-db = { version = "0.52.0", features = ["opendal-postgres"] } tokio = "1.26.0" url = "2.5.4" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index b2ebabeb..fa536008 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.51.0" -shuttle-runtime = "0.51.0" +shuttle-rocket = "0.52.0" +shuttle-runtime = "0.52.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 8d9587cd..f8d841d9 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] salvo = "0.75.0" -shuttle-salvo = "0.51.0" -shuttle-runtime = "0.51.0" +shuttle-salvo = "0.52.0" +shuttle-runtime = "0.52.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml index 12854142..46977282 100644 --- a/salvo/image-rescaler/Cargo.toml +++ b/salvo/image-rescaler/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] image = "0.24.8" salvo = "0.75.0" -shuttle-salvo = "0.51.0" -shuttle-runtime = "0.51.0" +shuttle-salvo = "0.52.0" +shuttle-runtime = "0.52.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index 2e31ad6f..e088c490 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.51.0" -shuttle-serenity = "0.51.0" +shuttle-runtime = "0.52.0" +shuttle-serenity = "0.52.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 3f9ae083..c48b4f82 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.51.0" -shuttle-serenity = "0.51.0" -shuttle-shared-db = { version = "0.51.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.52.0" +shuttle-serenity = "0.52.0" +shuttle-shared-db = { version = "0.52.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/weather-forecast/Cargo.toml b/serenity/weather-forecast/Cargo.toml index 4ec466d3..d0734eea 100644 --- a/serenity/weather-forecast/Cargo.toml +++ b/serenity/weather-forecast/Cargo.toml @@ -8,7 +8,7 @@ anyhow = "1.0.66" reqwest = { version = "0.11.24", features = ["json"] } serde = "1.0.197" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.51.0" -shuttle-serenity = "0.51.0" +shuttle-runtime = "0.52.0" +shuttle-serenity = "0.52.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/shuttle-cron/Cargo.toml b/shuttle-cron/Cargo.toml index e04caa75..00b2c86a 100644 --- a/shuttle-cron/Cargo.toml +++ b/shuttle-cron/Cargo.toml @@ -10,7 +10,7 @@ apalis-sql = { version = "0.6", features = ["postgres"] } apalis-cron = { version = "0.6" } chrono = { version = "0.4.32", features = ["clock", "serde"] } serde = { version = "1.0.195", features = ["derive"] } -shuttle-runtime = "0.51.0" -shuttle-shared-db = { version = "0.51.0", features = ["postgres"] } +shuttle-runtime = "0.52.0" +shuttle-shared-db = { version = "0.52.0", features = ["postgres"] } sqlx = { version = "0.8", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 61660527..6042f898 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.51.0" -shuttle-runtime = "0.51.0" +shuttle-thruster = "0.52.0" +shuttle-runtime = "0.52.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 7745b2b8..55a5ae37 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.51.0" -shuttle-runtime = "0.51.0" +shuttle-tide = "0.52.0" +shuttle-runtime = "0.52.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 807382fc..3dce851c 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.51.0" -shuttle-tower = "0.51.0" +shuttle-runtime = "0.52.0" +shuttle-tower = "0.52.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index da0e9335..cbc8591a 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.51.0" +shuttle-actix-web = "0.52.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.51.0", default-features = false } +shuttle-runtime = { version = "0.52.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index f144c746..f73c3803 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.51.0" -shuttle-warp = "0.51.0" +shuttle-runtime = "0.52.0" +shuttle-warp = "0.52.0" tokio = "1.26.0" warp = "0.3.3" From 25ebe6d0ec6d1be78adb1c25155acebf2cc69122 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 12 Mar 2025 16:50:43 +0100 Subject: [PATCH 204/239] chore: v0.35.0 --- actix-web/clerk/backend/Cargo.toml | 4 ++-- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/htmx-crud/Cargo.toml | 6 +++--- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 4 ++-- axum/oauth2/Cargo.toml | 6 +++--- axum/openai/Cargo.toml | 8 ++++---- axum/postgres/Cargo.toml | 6 +++--- axum/qdrant/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- bevy/hello-world/server/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- fullstack-templates/saas/backend/Cargo.toml | 6 +++--- loco/hello-world/Cargo.toml | 4 ++-- other/feature-flags/Cargo.toml | 4 ++-- other/standalone-binary/Cargo.toml | 4 ++-- poem/hello-world/Cargo.toml | 4 ++-- poise/hello-world/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/opendal-memory/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 4 ++-- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- salvo/image-rescaler/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 6 +++--- serenity/weather-forecast/Cargo.toml | 4 ++-- shuttle-cron/Cargo.toml | 4 ++-- thruster/hello-world/Cargo.toml | 4 ++-- tide/hello-world/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 46 files changed, 105 insertions(+), 105 deletions(-) diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml index 5e9839df..c18804b3 100644 --- a/actix-web/clerk/backend/Cargo.toml +++ b/actix-web/clerk/backend/Cargo.toml @@ -10,5 +10,5 @@ clerk-rs = "0.2.3" openssl-sys = { version = "0.9.9", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.52.0" -shuttle-runtime = "0.52.0" +shuttle-actix-web = "0.53.0" +shuttle-runtime = "0.53.0" diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index 4908534d..21f2b8fa 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.7.1" actix-session = { version = "0.9.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.52.0" -shuttle-runtime = "0.52.0" +shuttle-actix-web = "0.53.0" +shuttle-runtime = "0.53.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index d0f7ee2e..0394cb2a 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.52.0" -shuttle-runtime = "0.52.0" +shuttle-actix-web = "0.53.0" +shuttle-runtime = "0.53.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 3d986861..9a3d8c77 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.52.0" -shuttle-runtime = "0.52.0" +shuttle-actix-web = "0.53.0" +shuttle-runtime = "0.53.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.52.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.53.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index 01f91196..89797784 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.52.0" -shuttle-runtime = "0.52.0" +shuttle-actix-web = "0.53.0" +shuttle-runtime = "0.53.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index b9378df8..4816c1c7 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.52.0" -shuttle-runtime = "0.52.0" +shuttle-actix-web = "0.53.0" +shuttle-runtime = "0.53.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index ec5f08b7..c527af73 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.8.1" -shuttle-axum = "0.52.0" -shuttle-runtime = "0.52.0" +shuttle-axum = "0.53.0" +shuttle-runtime = "0.53.0" tokio = "1.28.2" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index 1317c5e4..0732ef97 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -9,9 +9,9 @@ askama_axum = "0.4.0" axum = "0.7.4" serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.52.0" -shuttle-shared-db = { version = "0.52.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.53.0" +shuttle-shared-db = { version = "0.53.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index 8f8226bc..11ce2919 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.52.0" +shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.53.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index f78002e3..f035ae3a 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.52.0" +shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.53.0" tokio = "1.28.2" diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index 6ea5eec7..d5730bf6 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -11,9 +11,9 @@ chrono = { version = "0.4.35", features = ["clock"] } oauth2 = "4.4.1" reqwest = { version = "0.11.18", features = ["json"] } serde = { version = "1.0.183", features = ["derive"] } -shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.52.0" -shuttle-shared-db = { version = "0.52.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.53.0" +shuttle-shared-db = { version = "0.53.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["macros", "chrono"] } thiserror = "1.0.57" time = "0.3.25" diff --git a/axum/openai/Cargo.toml b/axum/openai/Cargo.toml index bc4fbe7b..a9fdfe79 100644 --- a/axum/openai/Cargo.toml +++ b/axum/openai/Cargo.toml @@ -20,7 +20,7 @@ sqlx = { version = "0.8.2", features = [ ] } tokio = { version = "1.28.2", features = ["macros", "rt-multi-thread"] } tower-http = { version = "0.6.2", features = ["cors", "fs"] } -shuttle-runtime = "0.52.0" -shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } -shuttle-shared-db = { version = "0.52.0", features = ["postgres"] } -shuttle-openai = "0.52.0" +shuttle-runtime = "0.53.0" +shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } +shuttle-shared-db = { version = "0.53.0", features = ["postgres"] } +shuttle-openai = "0.53.0" diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index ee4eec20..f706f6aa 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.52.0" -shuttle-shared-db = { version = "0.52.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.53.0" +shuttle-shared-db = { version = "0.53.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index 52f3e054..762844c4 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.10.1" -shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } -shuttle-qdrant = "0.52.0" -shuttle-runtime = "0.52.0" +shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } +shuttle-qdrant = "0.53.0" +shuttle-runtime = "0.53.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 79ba0993..c491c168 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.52.0" +shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.53.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index ae5c5df4..20826f65 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.52.0" -shuttle-turso = "0.52.0" +shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.53.0" +shuttle-turso = "0.53.0" libsql = "0.6.0" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 46b57c81..93745df8 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.52.0" +shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.53.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/bevy/hello-world/server/Cargo.toml b/bevy/hello-world/server/Cargo.toml index 75f8cc9a..a7d8c2cb 100644 --- a/bevy/hello-world/server/Cargo.toml +++ b/bevy/hello-world/server/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.52.0" +shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.53.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 966612d8..658800ee 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1", features = ["derive"] } -shuttle-service = "0.52.0" -shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.52.0" +shuttle-service = "0.53.0" +shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.53.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 0361c68e..53b386c7 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.52.0" +shuttle-runtime = "0.53.0" tokio = "1" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 0eb494d0..532d2936 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,9 +16,9 @@ lettre = "0.11.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.52.0" -shuttle-shared-db = { version = "0.52.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.53.0" +shuttle-shared-db = { version = "0.53.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index 56e56c98..d7c3635f 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -13,8 +13,8 @@ default-run = "hello_world-cli" loco-rs = { version = "0.14.0", default-features = false } [dependencies] -shuttle-axum = "0.52.0" -shuttle-runtime = { version = "0.52.0", default-features = false } +shuttle-axum = "0.53.0" +shuttle-runtime = { version = "0.53.0", default-features = false } loco-rs = { workspace = true , features = ["cli"] } serde = { version = "1", features = ["derive"] } diff --git a/other/feature-flags/Cargo.toml b/other/feature-flags/Cargo.toml index bf934add..e385ee7a 100644 --- a/other/feature-flags/Cargo.toml +++ b/other/feature-flags/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.52.0" +shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.53.0" [features] # Shuttle will disable default features and enable the feature "shuttle" if it exists. diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 2cd2693c..2007157a 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,6 +15,6 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = { version = "0.52.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.52.0" +shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.53.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 07644e3e..4ccdc292 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "3.0.0" -shuttle-poem = "0.52.0" -shuttle-runtime = "0.52.0" +shuttle-poem = "0.53.0" +shuttle-runtime = "0.53.0" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 89022b11..9fe8530d 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.6.1" -shuttle-runtime = "0.52.0" +shuttle-runtime = "0.53.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity -shuttle-serenity = "0.52.0" +shuttle-serenity = "0.53.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 8859c956..759b9c7a 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" rocket_dyn_templates = { version = "0.1.0", features = ["handlebars"] } -shuttle-rocket = "0.52.0" -shuttle-runtime = "0.52.0" +shuttle-rocket = "0.53.0" +shuttle-runtime = "0.53.0" tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index f526fa5c..05e0eb36 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.52.0" -shuttle-runtime = "0.52.0" +shuttle-rocket = "0.53.0" +shuttle-runtime = "0.53.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index ec4156ab..b714aa9e 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.52.0" -shuttle-runtime = "0.52.0" +shuttle-rocket = "0.53.0" +shuttle-runtime = "0.53.0" tokio = "1.26.0" diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index f421daf2..9b607412 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" opendal = "0.51" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-opendal = "0.52.0" -shuttle-rocket = "0.52.0" -shuttle-runtime = "0.52.0" +shuttle-opendal = "0.53.0" +shuttle-rocket = "0.53.0" +shuttle-runtime = "0.53.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index b6a3ba84..cd18ba80 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.52.0" -shuttle-runtime = "0.52.0" -shuttle-shared-db = { version = "0.52.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.53.0" +shuttle-runtime = "0.53.0" +shuttle-shared-db = { version = "0.53.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index ae4a6385..9c3a8aff 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.52.0" -shuttle-runtime = "0.52.0" +shuttle-rocket = "0.53.0" +shuttle-runtime = "0.53.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index 8558c3aa..3a241367 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.52.0" -shuttle-runtime = "0.52.0" +shuttle-rocket = "0.53.0" +shuttle-runtime = "0.53.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 31721791..9c64b68c 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -8,8 +8,8 @@ nanoid = "0.4.0" opendal = "0.51" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.52.0" -shuttle-runtime = "0.52.0" -shuttle-shared-db = { version = "0.52.0", features = ["opendal-postgres"] } +shuttle-rocket = "0.53.0" +shuttle-runtime = "0.53.0" +shuttle-shared-db = { version = "0.53.0", features = ["opendal-postgres"] } tokio = "1.26.0" url = "2.5.4" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index fa536008..4c3b531f 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.52.0" -shuttle-runtime = "0.52.0" +shuttle-rocket = "0.53.0" +shuttle-runtime = "0.53.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index f8d841d9..52e10ef2 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] salvo = "0.75.0" -shuttle-salvo = "0.52.0" -shuttle-runtime = "0.52.0" +shuttle-salvo = "0.53.0" +shuttle-runtime = "0.53.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml index 46977282..71769cb7 100644 --- a/salvo/image-rescaler/Cargo.toml +++ b/salvo/image-rescaler/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] image = "0.24.8" salvo = "0.75.0" -shuttle-salvo = "0.52.0" -shuttle-runtime = "0.52.0" +shuttle-salvo = "0.53.0" +shuttle-runtime = "0.53.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index e088c490..c4ed364d 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.52.0" -shuttle-serenity = "0.52.0" +shuttle-runtime = "0.53.0" +shuttle-serenity = "0.53.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index c48b4f82..4413a566 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.52.0" -shuttle-serenity = "0.52.0" -shuttle-shared-db = { version = "0.52.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.53.0" +shuttle-serenity = "0.53.0" +shuttle-shared-db = { version = "0.53.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/weather-forecast/Cargo.toml b/serenity/weather-forecast/Cargo.toml index d0734eea..840a1f17 100644 --- a/serenity/weather-forecast/Cargo.toml +++ b/serenity/weather-forecast/Cargo.toml @@ -8,7 +8,7 @@ anyhow = "1.0.66" reqwest = { version = "0.11.24", features = ["json"] } serde = "1.0.197" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.52.0" -shuttle-serenity = "0.52.0" +shuttle-runtime = "0.53.0" +shuttle-serenity = "0.53.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/shuttle-cron/Cargo.toml b/shuttle-cron/Cargo.toml index 00b2c86a..c96e688b 100644 --- a/shuttle-cron/Cargo.toml +++ b/shuttle-cron/Cargo.toml @@ -10,7 +10,7 @@ apalis-sql = { version = "0.6", features = ["postgres"] } apalis-cron = { version = "0.6" } chrono = { version = "0.4.32", features = ["clock", "serde"] } serde = { version = "1.0.195", features = ["derive"] } -shuttle-runtime = "0.52.0" -shuttle-shared-db = { version = "0.52.0", features = ["postgres"] } +shuttle-runtime = "0.53.0" +shuttle-shared-db = { version = "0.53.0", features = ["postgres"] } sqlx = { version = "0.8", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 6042f898..f1c6af9b 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.52.0" -shuttle-runtime = "0.52.0" +shuttle-thruster = "0.53.0" +shuttle-runtime = "0.53.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 55a5ae37..18dcacbd 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.52.0" -shuttle-runtime = "0.52.0" +shuttle-tide = "0.53.0" +shuttle-runtime = "0.53.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 3dce851c..ebe4c49f 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.52.0" -shuttle-tower = "0.52.0" +shuttle-runtime = "0.53.0" +shuttle-tower = "0.53.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index cbc8591a..5bf82a43 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.52.0" +shuttle-actix-web = "0.53.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.52.0", default-features = false } +shuttle-runtime = { version = "0.53.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index f73c3803..2cc7d12f 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.52.0" -shuttle-warp = "0.52.0" +shuttle-runtime = "0.53.0" +shuttle-warp = "0.53.0" tokio = "1.26.0" warp = "0.3.3" From 937b42c66f42c7b14d6eb75d50711cd9432b4d93 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 12 Mar 2025 16:52:04 +0100 Subject: [PATCH 205/239] bump async-openai example --- axum/openai/Cargo.toml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/axum/openai/Cargo.toml b/axum/openai/Cargo.toml index a9fdfe79..3dc6fe45 100644 --- a/axum/openai/Cargo.toml +++ b/axum/openai/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -async-openai = "0.23.0" +async-openai = "0.28.0" argon2 = "0.5.3" axum = "0.7.4" axum-extra = { version = "0.9.4", features = ["cookie", "cookie-private"] } @@ -12,7 +12,10 @@ derive_more = { version = "1.0.0", features = ["full"] } jsonwebtoken = "9.3.0" serde = { version = "1.0.215", features = ["derive"] } serde_json = "1.0.133" - +shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } +shuttle-openai = "0.53.0" +shuttle-runtime = "0.53.0" +shuttle-shared-db = { version = "0.53.0", features = ["postgres"] } sqlx = { version = "0.8.2", features = [ "runtime-tokio-rustls", "postgres", @@ -20,7 +23,3 @@ sqlx = { version = "0.8.2", features = [ ] } tokio = { version = "1.28.2", features = ["macros", "rt-multi-thread"] } tower-http = { version = "0.6.2", features = ["cors", "fs"] } -shuttle-runtime = "0.53.0" -shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } -shuttle-shared-db = { version = "0.53.0", features = ["postgres"] } -shuttle-openai = "0.53.0" From 6408406535b1dc783a14dcf88ef00aa2f0bbc6db Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Thu, 8 May 2025 01:03:57 +0200 Subject: [PATCH 206/239] chore: v0.54.0 --- actix-web/clerk/backend/Cargo.toml | 4 ++-- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/htmx-crud/Cargo.toml | 6 +++--- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 4 ++-- axum/oauth2/Cargo.toml | 6 +++--- axum/openai/Cargo.toml | 8 ++++---- axum/postgres/Cargo.toml | 6 +++--- axum/qdrant/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- bevy/hello-world/server/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- fullstack-templates/saas/backend/Cargo.toml | 6 +++--- loco/hello-world/Cargo.toml | 4 ++-- other/feature-flags/Cargo.toml | 4 ++-- other/standalone-binary/Cargo.toml | 4 ++-- poem/hello-world/Cargo.toml | 4 ++-- poise/hello-world/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/opendal-memory/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 4 ++-- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- salvo/image-rescaler/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 6 +++--- serenity/weather-forecast/Cargo.toml | 4 ++-- shuttle-cron/Cargo.toml | 4 ++-- thruster/hello-world/Cargo.toml | 4 ++-- tide/hello-world/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 46 files changed, 105 insertions(+), 105 deletions(-) diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml index c18804b3..5b2d06a5 100644 --- a/actix-web/clerk/backend/Cargo.toml +++ b/actix-web/clerk/backend/Cargo.toml @@ -10,5 +10,5 @@ clerk-rs = "0.2.3" openssl-sys = { version = "0.9.9", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.53.0" -shuttle-runtime = "0.53.0" +shuttle-actix-web = "0.54.0" +shuttle-runtime = "0.54.0" diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index 21f2b8fa..5f1ff1b4 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.7.1" actix-session = { version = "0.9.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.53.0" -shuttle-runtime = "0.53.0" +shuttle-actix-web = "0.54.0" +shuttle-runtime = "0.54.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 0394cb2a..7f25149f 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.53.0" -shuttle-runtime = "0.53.0" +shuttle-actix-web = "0.54.0" +shuttle-runtime = "0.54.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 9a3d8c77..a64bb9e6 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.53.0" -shuttle-runtime = "0.53.0" +shuttle-actix-web = "0.54.0" +shuttle-runtime = "0.54.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.53.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.54.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index 89797784..514c11fa 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.53.0" -shuttle-runtime = "0.53.0" +shuttle-actix-web = "0.54.0" +shuttle-runtime = "0.54.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 4816c1c7..0bf19ac5 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.53.0" -shuttle-runtime = "0.53.0" +shuttle-actix-web = "0.54.0" +shuttle-runtime = "0.54.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index c527af73..a9c0f770 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.8.1" -shuttle-axum = "0.53.0" -shuttle-runtime = "0.53.0" +shuttle-axum = "0.54.0" +shuttle-runtime = "0.54.0" tokio = "1.28.2" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index 0732ef97..3ca95311 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -9,9 +9,9 @@ askama_axum = "0.4.0" axum = "0.7.4" serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.53.0" -shuttle-shared-db = { version = "0.53.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.54.0" +shuttle-shared-db = { version = "0.54.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index 11ce2919..6492c42f 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.53.0" +shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.54.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index f035ae3a..a568ec90 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.53.0" +shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.54.0" tokio = "1.28.2" diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index d5730bf6..c56d3d2c 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -11,9 +11,9 @@ chrono = { version = "0.4.35", features = ["clock"] } oauth2 = "4.4.1" reqwest = { version = "0.11.18", features = ["json"] } serde = { version = "1.0.183", features = ["derive"] } -shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.53.0" -shuttle-shared-db = { version = "0.53.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.54.0" +shuttle-shared-db = { version = "0.54.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["macros", "chrono"] } thiserror = "1.0.57" time = "0.3.25" diff --git a/axum/openai/Cargo.toml b/axum/openai/Cargo.toml index 3dc6fe45..6ab90e28 100644 --- a/axum/openai/Cargo.toml +++ b/axum/openai/Cargo.toml @@ -12,10 +12,10 @@ derive_more = { version = "1.0.0", features = ["full"] } jsonwebtoken = "9.3.0" serde = { version = "1.0.215", features = ["derive"] } serde_json = "1.0.133" -shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } -shuttle-openai = "0.53.0" -shuttle-runtime = "0.53.0" -shuttle-shared-db = { version = "0.53.0", features = ["postgres"] } +shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } +shuttle-openai = "0.54.0" +shuttle-runtime = "0.54.0" +shuttle-shared-db = { version = "0.54.0", features = ["postgres"] } sqlx = { version = "0.8.2", features = [ "runtime-tokio-rustls", "postgres", diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index f706f6aa..6d66392f 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.53.0" -shuttle-shared-db = { version = "0.53.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.54.0" +shuttle-shared-db = { version = "0.54.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index 762844c4..8a0ab962 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.10.1" -shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } -shuttle-qdrant = "0.53.0" -shuttle-runtime = "0.53.0" +shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } +shuttle-qdrant = "0.54.0" +shuttle-runtime = "0.54.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index c491c168..daa0df18 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.53.0" +shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.54.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 20826f65..797302f3 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.53.0" -shuttle-turso = "0.53.0" +shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.54.0" +shuttle-turso = "0.54.0" libsql = "0.6.0" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 93745df8..f0fa4300 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.53.0" +shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.54.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/bevy/hello-world/server/Cargo.toml b/bevy/hello-world/server/Cargo.toml index a7d8c2cb..1cd20d97 100644 --- a/bevy/hello-world/server/Cargo.toml +++ b/bevy/hello-world/server/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.53.0" +shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.54.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 658800ee..c086475a 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1", features = ["derive"] } -shuttle-service = "0.53.0" -shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.53.0" +shuttle-service = "0.54.0" +shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.54.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 53b386c7..7775e955 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.53.0" +shuttle-runtime = "0.54.0" tokio = "1" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 532d2936..be1a6b0c 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,9 +16,9 @@ lettre = "0.11.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.53.0" -shuttle-shared-db = { version = "0.53.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.54.0" +shuttle-shared-db = { version = "0.54.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index d7c3635f..b944c5ac 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -13,8 +13,8 @@ default-run = "hello_world-cli" loco-rs = { version = "0.14.0", default-features = false } [dependencies] -shuttle-axum = "0.53.0" -shuttle-runtime = { version = "0.53.0", default-features = false } +shuttle-axum = "0.54.0" +shuttle-runtime = { version = "0.54.0", default-features = false } loco-rs = { workspace = true , features = ["cli"] } serde = { version = "1", features = ["derive"] } diff --git a/other/feature-flags/Cargo.toml b/other/feature-flags/Cargo.toml index e385ee7a..a8e4c151 100644 --- a/other/feature-flags/Cargo.toml +++ b/other/feature-flags/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.53.0" +shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.54.0" [features] # Shuttle will disable default features and enable the feature "shuttle" if it exists. diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 2007157a..cac0e8fb 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,6 +15,6 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = { version = "0.53.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.53.0" +shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.54.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 4ccdc292..3ca27ef1 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "3.0.0" -shuttle-poem = "0.53.0" -shuttle-runtime = "0.53.0" +shuttle-poem = "0.54.0" +shuttle-runtime = "0.54.0" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 9fe8530d..2bc1a9c9 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.6.1" -shuttle-runtime = "0.53.0" +shuttle-runtime = "0.54.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity -shuttle-serenity = "0.53.0" +shuttle-serenity = "0.54.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 759b9c7a..8eadd0ca 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" rocket_dyn_templates = { version = "0.1.0", features = ["handlebars"] } -shuttle-rocket = "0.53.0" -shuttle-runtime = "0.53.0" +shuttle-rocket = "0.54.0" +shuttle-runtime = "0.54.0" tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 05e0eb36..78c0a94b 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.53.0" -shuttle-runtime = "0.53.0" +shuttle-rocket = "0.54.0" +shuttle-runtime = "0.54.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index b714aa9e..3f694c80 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.53.0" -shuttle-runtime = "0.53.0" +shuttle-rocket = "0.54.0" +shuttle-runtime = "0.54.0" tokio = "1.26.0" diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index 9b607412..d7c8bb8b 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" opendal = "0.51" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-opendal = "0.53.0" -shuttle-rocket = "0.53.0" -shuttle-runtime = "0.53.0" +shuttle-opendal = "0.54.0" +shuttle-rocket = "0.54.0" +shuttle-runtime = "0.54.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index cd18ba80..a71bce21 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.53.0" -shuttle-runtime = "0.53.0" -shuttle-shared-db = { version = "0.53.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.54.0" +shuttle-runtime = "0.54.0" +shuttle-shared-db = { version = "0.54.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 9c3a8aff..fe143229 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.53.0" -shuttle-runtime = "0.53.0" +shuttle-rocket = "0.54.0" +shuttle-runtime = "0.54.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index 3a241367..91d155d0 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.53.0" -shuttle-runtime = "0.53.0" +shuttle-rocket = "0.54.0" +shuttle-runtime = "0.54.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 9c64b68c..f4582094 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -8,8 +8,8 @@ nanoid = "0.4.0" opendal = "0.51" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.53.0" -shuttle-runtime = "0.53.0" -shuttle-shared-db = { version = "0.53.0", features = ["opendal-postgres"] } +shuttle-rocket = "0.54.0" +shuttle-runtime = "0.54.0" +shuttle-shared-db = { version = "0.54.0", features = ["opendal-postgres"] } tokio = "1.26.0" url = "2.5.4" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 4c3b531f..78d1b33a 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.53.0" -shuttle-runtime = "0.53.0" +shuttle-rocket = "0.54.0" +shuttle-runtime = "0.54.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 52e10ef2..af37cbae 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] salvo = "0.75.0" -shuttle-salvo = "0.53.0" -shuttle-runtime = "0.53.0" +shuttle-salvo = "0.54.0" +shuttle-runtime = "0.54.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml index 71769cb7..6e68dfd1 100644 --- a/salvo/image-rescaler/Cargo.toml +++ b/salvo/image-rescaler/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] image = "0.24.8" salvo = "0.75.0" -shuttle-salvo = "0.53.0" -shuttle-runtime = "0.53.0" +shuttle-salvo = "0.54.0" +shuttle-runtime = "0.54.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index c4ed364d..a8ed5d33 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.53.0" -shuttle-serenity = "0.53.0" +shuttle-runtime = "0.54.0" +shuttle-serenity = "0.54.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 4413a566..f6e58e02 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.53.0" -shuttle-serenity = "0.53.0" -shuttle-shared-db = { version = "0.53.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.54.0" +shuttle-serenity = "0.54.0" +shuttle-shared-db = { version = "0.54.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/weather-forecast/Cargo.toml b/serenity/weather-forecast/Cargo.toml index 840a1f17..e85f5338 100644 --- a/serenity/weather-forecast/Cargo.toml +++ b/serenity/weather-forecast/Cargo.toml @@ -8,7 +8,7 @@ anyhow = "1.0.66" reqwest = { version = "0.11.24", features = ["json"] } serde = "1.0.197" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.53.0" -shuttle-serenity = "0.53.0" +shuttle-runtime = "0.54.0" +shuttle-serenity = "0.54.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/shuttle-cron/Cargo.toml b/shuttle-cron/Cargo.toml index c96e688b..723cf750 100644 --- a/shuttle-cron/Cargo.toml +++ b/shuttle-cron/Cargo.toml @@ -10,7 +10,7 @@ apalis-sql = { version = "0.6", features = ["postgres"] } apalis-cron = { version = "0.6" } chrono = { version = "0.4.32", features = ["clock", "serde"] } serde = { version = "1.0.195", features = ["derive"] } -shuttle-runtime = "0.53.0" -shuttle-shared-db = { version = "0.53.0", features = ["postgres"] } +shuttle-runtime = "0.54.0" +shuttle-shared-db = { version = "0.54.0", features = ["postgres"] } sqlx = { version = "0.8", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index f1c6af9b..7eabcf5d 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.53.0" -shuttle-runtime = "0.53.0" +shuttle-thruster = "0.54.0" +shuttle-runtime = "0.54.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 18dcacbd..39cacdd6 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.53.0" -shuttle-runtime = "0.53.0" +shuttle-tide = "0.54.0" +shuttle-runtime = "0.54.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index ebe4c49f..d9fd5a91 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.53.0" -shuttle-tower = "0.53.0" +shuttle-runtime = "0.54.0" +shuttle-tower = "0.54.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 5bf82a43..b225b383 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.53.0" +shuttle-actix-web = "0.54.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.53.0", default-features = false } +shuttle-runtime = { version = "0.54.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 2cc7d12f..17a13fb3 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.53.0" -shuttle-warp = "0.53.0" +shuttle-runtime = "0.54.0" +shuttle-warp = "0.54.0" tokio = "1.26.0" warp = "0.3.3" From 09ba0affc30d7f0542e998190f04116b8d6a716c Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Thu, 8 May 2025 01:04:46 +0200 Subject: [PATCH 207/239] fix: tag order on postgres examples --- templates.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates.toml b/templates.toml index fb696fcb..eec87ba9 100644 --- a/templates.toml +++ b/templates.toml @@ -149,7 +149,7 @@ title = "Postgres" description = "Todo list with a Postgres database" path = "actix-web/postgres" use_cases = ["Web app", "Storage"] -tags = ["postgres", "actix-web", "database"] +tags = ["actix-web", "postgres", "database"] [templates.actix-web-clerk-react] title = "Clerk authentication" @@ -212,7 +212,7 @@ title = "Postgres" description = "Todo list with a Postgres database" path = "axum/postgres" use_cases = ["Web app", "Storage"] -tags = ["postgres", "axum", "database"] +tags = ["axum", "postgres", "database"] [templates.axum-qdrant] title = "Qdrant" @@ -275,7 +275,7 @@ title = "Postgres" description = "Todo list with a Postgres database" path = "rocket/postgres" use_cases = ["Web app", "Storage"] -tags = ["postgres", "rocket", "database"] +tags = ["rocket", "postgres", "database"] [templates.rocket-static-files] title = "File server" From 77078253562c2e2aad7e2505711815e591b1b489 Mon Sep 17 00:00:00 2001 From: Glen De Cauwsemaecker Date: Tue, 20 May 2025 17:01:04 +0200 Subject: [PATCH 208/239] feat: add initial rama examples (#205) --- rama/hello-world-tcp/Cargo.toml | 10 ++++++++ rama/hello-world-tcp/README.md | 6 +++++ rama/hello-world-tcp/src/main.rs | 34 ++++++++++++++++++++++++++ rama/hello-world/Cargo.toml | 10 ++++++++ rama/hello-world/src/main.rs | 38 +++++++++++++++++++++++++++++ rama/static-files/Cargo.toml | 10 ++++++++ rama/static-files/README.md | 9 +++++++ rama/static-files/Shuttle.toml | 4 +++ rama/static-files/assets/index.html | 20 +++++++++++++++ rama/static-files/assets/script.js | 1 + rama/static-files/assets/style.css | 13 ++++++++++ rama/static-files/src/main.rs | 8 ++++++ 12 files changed, 163 insertions(+) create mode 100644 rama/hello-world-tcp/Cargo.toml create mode 100644 rama/hello-world-tcp/README.md create mode 100644 rama/hello-world-tcp/src/main.rs create mode 100644 rama/hello-world/Cargo.toml create mode 100644 rama/hello-world/src/main.rs create mode 100644 rama/static-files/Cargo.toml create mode 100644 rama/static-files/README.md create mode 100644 rama/static-files/Shuttle.toml create mode 100644 rama/static-files/assets/index.html create mode 100644 rama/static-files/assets/script.js create mode 100644 rama/static-files/assets/style.css create mode 100644 rama/static-files/src/main.rs diff --git a/rama/hello-world-tcp/Cargo.toml b/rama/hello-world-tcp/Cargo.toml new file mode 100644 index 00000000..e6df199a --- /dev/null +++ b/rama/hello-world-tcp/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "hello-world-tcp" +version = "0.1.0" +edition = "2024" + +[dependencies] +rama = "0.2" +shuttle-rama = "0.54" +shuttle-runtime = "0.54" +tokio = "1.45" diff --git a/rama/hello-world-tcp/README.md b/rama/hello-world-tcp/README.md new file mode 100644 index 00000000..31804421 --- /dev/null +++ b/rama/hello-world-tcp/README.md @@ -0,0 +1,6 @@ +# Transport Layer Service + +This example shows how to start a rama-driven application +which operates directly on the Transport Layer instead of the the http layer. + +NOTE: due to limitations in Shuttle, TLS if used, is still terminated by shuttle runtime. diff --git a/rama/hello-world-tcp/src/main.rs b/rama/hello-world-tcp/src/main.rs new file mode 100644 index 00000000..fa25da34 --- /dev/null +++ b/rama/hello-world-tcp/src/main.rs @@ -0,0 +1,34 @@ +use rama::{net, service::service_fn}; +use std::convert::Infallible; +use tokio::io::AsyncWriteExt; + +async fn hello_world(mut stream: S) -> Result<(), Infallible> +where + S: net::stream::Stream + Unpin, +{ + const TEXT: &str = "Hello, Shuttle!"; + + let resp = [ + "HTTP/1.1 200 OK", + "Content-Type: text/plain", + format!("Content-Length: {}", TEXT.len()).as_str(), + "", + TEXT, + "", + ] + .join("\r\n"); + + stream + .write_all(resp.as_bytes()) + .await + .expect("write to stream"); + + Ok::<_, std::convert::Infallible>(()) +} + +#[shuttle_runtime::main] +async fn main() -> Result { + Ok(shuttle_rama::RamaService::transport(service_fn( + hello_world, + ))) +} diff --git a/rama/hello-world/Cargo.toml b/rama/hello-world/Cargo.toml new file mode 100644 index 00000000..c9fcb385 --- /dev/null +++ b/rama/hello-world/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "hello-world" +version = "0.1.0" +edition = "2024" + +[dependencies] +rama = { version = "0.2", features = ["http"] } +shuttle-rama = "0.54" +shuttle-runtime = "0.54" +tokio = "1.45" diff --git a/rama/hello-world/src/main.rs b/rama/hello-world/src/main.rs new file mode 100644 index 00000000..b06b23b7 --- /dev/null +++ b/rama/hello-world/src/main.rs @@ -0,0 +1,38 @@ +use rama::{ + Context, Layer, + error::ErrorContext, + http::{ + StatusCode, + layer::forwarded::GetForwardedHeaderLayer, + service::web::{Router, response::Result}, + }, + net::forwarded::Forwarded, +}; + +async fn hello_world(ctx: Context<()>) -> Result { + Ok(match ctx.get::() { + Some(forwarded) => format!( + "Hello cloud user @ {}!", + forwarded + .client_ip() + .context("missing IP information from user") + .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()))? + ), + None => "Hello local user! Are you developing?".to_owned(), + }) +} + +#[shuttle_runtime::main] +async fn main() -> Result { + let router = Router::new().get("/", hello_world); + + let app = + // Shuttle sits behind a load-balancer, + // so in case you want the real IP of the user, + // you need to ensure this headers is handled. + // + // Learn more at + GetForwardedHeaderLayer::x_forwarded_for().into_layer(router); + + Ok(shuttle_rama::RamaService::application(app)) +} diff --git a/rama/static-files/Cargo.toml b/rama/static-files/Cargo.toml new file mode 100644 index 00000000..6693dcca --- /dev/null +++ b/rama/static-files/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "static-files" +version = "0.1.0" +edition = "2024" + +[dependencies] +rama = "0.2" +shuttle-rama = "0.54" +shuttle-runtime = "0.54" +tokio = "1.45" diff --git a/rama/static-files/README.md b/rama/static-files/README.md new file mode 100644 index 00000000..1f72a802 --- /dev/null +++ b/rama/static-files/README.md @@ -0,0 +1,9 @@ +# Serving Static Assets with Rama + +This example shows how to serve static assets using [rama](https://github.com/plabayo/rama) and Shuttle. + +The official rama repository comes with a web service example +that also includes serving static content among other functionality. + +You can find that example at: +. diff --git a/rama/static-files/Shuttle.toml b/rama/static-files/Shuttle.toml new file mode 100644 index 00000000..a783bac5 --- /dev/null +++ b/rama/static-files/Shuttle.toml @@ -0,0 +1,4 @@ +[build] +assets = [ + "assets", +] diff --git a/rama/static-files/assets/index.html b/rama/static-files/assets/index.html new file mode 100644 index 00000000..916f8cd6 --- /dev/null +++ b/rama/static-files/assets/index.html @@ -0,0 +1,20 @@ + + + + Rama static file server on Shuttle + + + + +
+

+ Rama static file server on + Shuttle +

+

+ This is an example of serving static HTML, CSS, and JS files + with Rama and running it with Shuttle. +

+
+ + diff --git a/rama/static-files/assets/script.js b/rama/static-files/assets/script.js new file mode 100644 index 00000000..eb065f93 --- /dev/null +++ b/rama/static-files/assets/script.js @@ -0,0 +1 @@ +console.log('Hello, World!'); diff --git a/rama/static-files/assets/style.css b/rama/static-files/assets/style.css new file mode 100644 index 00000000..13c6f985 --- /dev/null +++ b/rama/static-files/assets/style.css @@ -0,0 +1,13 @@ +body { + background-color: #334; + color: #ffc; + font-family: Arial, Helvetica, sans-serif; +} + +main { + text-align: center; +} + +a { + color: orange; +} diff --git a/rama/static-files/src/main.rs b/rama/static-files/src/main.rs new file mode 100644 index 00000000..5049baf0 --- /dev/null +++ b/rama/static-files/src/main.rs @@ -0,0 +1,8 @@ +use rama::http::service::fs::ServeDir; + +#[shuttle_runtime::main] +async fn main() -> Result { + Ok(shuttle_rama::RamaService::application(ServeDir::new( + "assets", + ))) +} From a1a59fdfb43e91a47ca672d4f9bb95579f92a073 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 21 May 2025 02:50:02 +0200 Subject: [PATCH 209/239] fix: add rama templates entries --- templates.toml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/templates.toml b/templates.toml index eec87ba9..8b55af77 100644 --- a/templates.toml +++ b/templates.toml @@ -13,6 +13,7 @@ bevy = "https://avatars.githubusercontent.com/u/60047606?v=4" loco = "https://avatars.githubusercontent.com/u/151030972?v=4" poem = "https://avatars.githubusercontent.com/u/88869778?v=4" poise = "https://avatars.githubusercontent.com/u/32077193?v=4" +rama = "https://avatars.githubusercontent.com/u/87996217?v=4" serenity = "https://avatars.githubusercontent.com/u/32077193?v=4" salvo = "https://avatars.githubusercontent.com/u/77909452?v=4" tide = "https://avatars.githubusercontent.com/u/56456261?v=4" @@ -77,6 +78,14 @@ use_cases = ["Discord bot"] tags = ["poise", "serenity"] template = "poise" +[starters.rama-hello-world] +title = "Rama" +description = "Modular service framework to move and transform network packets" +path = "rama/hello-world" +use_cases = ["Web app"] +tags = ["rama"] +template = "rama" + [starters.rocket-hello-world] title = "Rocket" description = "Simple and easy-to-use web framework" @@ -249,6 +258,20 @@ path = "fullstack-templates/saas" use_cases = ["Web app", "Authentication", "Storage", "Monetization"] tags = ["nextjs", "axum", "database", "postgres", "typescript", "tailwind"] +[templates.rama-hello-world-tcp] +title = "Rama TCP" +description = "HTTP Hello world with Rama using raw TCP" +path = "rama/hello-world-tcp" +use_cases = ["Web app"] +tags = ["rama"] + +[templates.rama-static-files] +title = "File server" +description = "Hello World static file server with Rama" +path = "rama/static-files" +use_cases = ["Web app"] +tags = ["rama"] + [templates.rocket-dyn-templates] title = "Handlebars dynamic templates" description = "HTML templating with Handlebars" From 82baf9c93ee1fb64e3f04b3331130613244997e7 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 21 May 2025 02:51:46 +0200 Subject: [PATCH 210/239] chore: v0.55.0 --- actix-web/clerk/backend/Cargo.toml | 4 ++-- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/htmx-crud/Cargo.toml | 6 +++--- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 4 ++-- axum/oauth2/Cargo.toml | 6 +++--- axum/openai/Cargo.toml | 8 ++++---- axum/postgres/Cargo.toml | 6 +++--- axum/qdrant/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- bevy/hello-world/server/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- fullstack-templates/saas/backend/Cargo.toml | 6 +++--- loco/hello-world/Cargo.toml | 4 ++-- other/feature-flags/Cargo.toml | 4 ++-- other/standalone-binary/Cargo.toml | 4 ++-- poem/hello-world/Cargo.toml | 4 ++-- poise/hello-world/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/opendal-memory/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 4 ++-- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- salvo/image-rescaler/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 6 +++--- serenity/weather-forecast/Cargo.toml | 4 ++-- shuttle-cron/Cargo.toml | 4 ++-- thruster/hello-world/Cargo.toml | 4 ++-- tide/hello-world/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 46 files changed, 105 insertions(+), 105 deletions(-) diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml index 5b2d06a5..65ceb136 100644 --- a/actix-web/clerk/backend/Cargo.toml +++ b/actix-web/clerk/backend/Cargo.toml @@ -10,5 +10,5 @@ clerk-rs = "0.2.3" openssl-sys = { version = "0.9.9", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.54.0" -shuttle-runtime = "0.54.0" +shuttle-actix-web = "0.55.0" +shuttle-runtime = "0.55.0" diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index 5f1ff1b4..2969c077 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.7.1" actix-session = { version = "0.9.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.54.0" -shuttle-runtime = "0.54.0" +shuttle-actix-web = "0.55.0" +shuttle-runtime = "0.55.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 7f25149f..d99ebcb8 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.54.0" -shuttle-runtime = "0.54.0" +shuttle-actix-web = "0.55.0" +shuttle-runtime = "0.55.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index a64bb9e6..2db05963 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.54.0" -shuttle-runtime = "0.54.0" +shuttle-actix-web = "0.55.0" +shuttle-runtime = "0.55.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.54.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.55.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index 514c11fa..c91db9cf 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.54.0" -shuttle-runtime = "0.54.0" +shuttle-actix-web = "0.55.0" +shuttle-runtime = "0.55.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 0bf19ac5..377e2ef0 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.54.0" -shuttle-runtime = "0.54.0" +shuttle-actix-web = "0.55.0" +shuttle-runtime = "0.55.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index a9c0f770..8f16dc7c 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.8.1" -shuttle-axum = "0.54.0" -shuttle-runtime = "0.54.0" +shuttle-axum = "0.55.0" +shuttle-runtime = "0.55.0" tokio = "1.28.2" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index 3ca95311..2930cfe8 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -9,9 +9,9 @@ askama_axum = "0.4.0" axum = "0.7.4" serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.54.0" -shuttle-shared-db = { version = "0.54.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.55.0" +shuttle-shared-db = { version = "0.55.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index 6492c42f..d89250fa 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.54.0" +shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.55.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index a568ec90..000e9549 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.54.0" +shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.55.0" tokio = "1.28.2" diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index c56d3d2c..d6d2322d 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -11,9 +11,9 @@ chrono = { version = "0.4.35", features = ["clock"] } oauth2 = "4.4.1" reqwest = { version = "0.11.18", features = ["json"] } serde = { version = "1.0.183", features = ["derive"] } -shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.54.0" -shuttle-shared-db = { version = "0.54.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.55.0" +shuttle-shared-db = { version = "0.55.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["macros", "chrono"] } thiserror = "1.0.57" time = "0.3.25" diff --git a/axum/openai/Cargo.toml b/axum/openai/Cargo.toml index 6ab90e28..21a82a9a 100644 --- a/axum/openai/Cargo.toml +++ b/axum/openai/Cargo.toml @@ -12,10 +12,10 @@ derive_more = { version = "1.0.0", features = ["full"] } jsonwebtoken = "9.3.0" serde = { version = "1.0.215", features = ["derive"] } serde_json = "1.0.133" -shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } -shuttle-openai = "0.54.0" -shuttle-runtime = "0.54.0" -shuttle-shared-db = { version = "0.54.0", features = ["postgres"] } +shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } +shuttle-openai = "0.55.0" +shuttle-runtime = "0.55.0" +shuttle-shared-db = { version = "0.55.0", features = ["postgres"] } sqlx = { version = "0.8.2", features = [ "runtime-tokio-rustls", "postgres", diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 6d66392f..8fa007d2 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.54.0" -shuttle-shared-db = { version = "0.54.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.55.0" +shuttle-shared-db = { version = "0.55.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index 8a0ab962..998b367a 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.10.1" -shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } -shuttle-qdrant = "0.54.0" -shuttle-runtime = "0.54.0" +shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } +shuttle-qdrant = "0.55.0" +shuttle-runtime = "0.55.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index daa0df18..9dbbe1a9 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.54.0" +shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.55.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 797302f3..fb03fbf5 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.54.0" -shuttle-turso = "0.54.0" +shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.55.0" +shuttle-turso = "0.55.0" libsql = "0.6.0" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index f0fa4300..9d75dd8e 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.54.0" +shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.55.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/bevy/hello-world/server/Cargo.toml b/bevy/hello-world/server/Cargo.toml index 1cd20d97..881699ee 100644 --- a/bevy/hello-world/server/Cargo.toml +++ b/bevy/hello-world/server/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.54.0" +shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.55.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index c086475a..5394744c 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1", features = ["derive"] } -shuttle-service = "0.54.0" -shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.54.0" +shuttle-service = "0.55.0" +shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.55.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index 7775e955..d912a8aa 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.54.0" +shuttle-runtime = "0.55.0" tokio = "1" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index be1a6b0c..89bdfadd 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,9 +16,9 @@ lettre = "0.11.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.54.0" -shuttle-shared-db = { version = "0.54.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.55.0" +shuttle-shared-db = { version = "0.55.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index b944c5ac..e6d070c7 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -13,8 +13,8 @@ default-run = "hello_world-cli" loco-rs = { version = "0.14.0", default-features = false } [dependencies] -shuttle-axum = "0.54.0" -shuttle-runtime = { version = "0.54.0", default-features = false } +shuttle-axum = "0.55.0" +shuttle-runtime = { version = "0.55.0", default-features = false } loco-rs = { workspace = true , features = ["cli"] } serde = { version = "1", features = ["derive"] } diff --git a/other/feature-flags/Cargo.toml b/other/feature-flags/Cargo.toml index a8e4c151..3f69a4c2 100644 --- a/other/feature-flags/Cargo.toml +++ b/other/feature-flags/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.54.0" +shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.55.0" [features] # Shuttle will disable default features and enable the feature "shuttle" if it exists. diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index cac0e8fb..29d1587f 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,6 +15,6 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = { version = "0.54.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.54.0" +shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.55.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index 3ca27ef1..e808feaa 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "3.0.0" -shuttle-poem = "0.54.0" -shuttle-runtime = "0.54.0" +shuttle-poem = "0.55.0" +shuttle-runtime = "0.55.0" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 2bc1a9c9..b2677698 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.6.1" -shuttle-runtime = "0.54.0" +shuttle-runtime = "0.55.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity -shuttle-serenity = "0.54.0" +shuttle-serenity = "0.55.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 8eadd0ca..4e7af13d 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" rocket_dyn_templates = { version = "0.1.0", features = ["handlebars"] } -shuttle-rocket = "0.54.0" -shuttle-runtime = "0.54.0" +shuttle-rocket = "0.55.0" +shuttle-runtime = "0.55.0" tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 78c0a94b..aa622b15 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.54.0" -shuttle-runtime = "0.54.0" +shuttle-rocket = "0.55.0" +shuttle-runtime = "0.55.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 3f694c80..584283b4 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.54.0" -shuttle-runtime = "0.54.0" +shuttle-rocket = "0.55.0" +shuttle-runtime = "0.55.0" tokio = "1.26.0" diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index d7c8bb8b..6930c91c 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" opendal = "0.51" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-opendal = "0.54.0" -shuttle-rocket = "0.54.0" -shuttle-runtime = "0.54.0" +shuttle-opendal = "0.55.0" +shuttle-rocket = "0.55.0" +shuttle-runtime = "0.55.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index a71bce21..3f473335 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.54.0" -shuttle-runtime = "0.54.0" -shuttle-shared-db = { version = "0.54.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.55.0" +shuttle-runtime = "0.55.0" +shuttle-shared-db = { version = "0.55.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index fe143229..79252a1a 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.54.0" -shuttle-runtime = "0.54.0" +shuttle-rocket = "0.55.0" +shuttle-runtime = "0.55.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index 91d155d0..db137c16 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.54.0" -shuttle-runtime = "0.54.0" +shuttle-rocket = "0.55.0" +shuttle-runtime = "0.55.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index f4582094..2689f9bb 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -8,8 +8,8 @@ nanoid = "0.4.0" opendal = "0.51" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.54.0" -shuttle-runtime = "0.54.0" -shuttle-shared-db = { version = "0.54.0", features = ["opendal-postgres"] } +shuttle-rocket = "0.55.0" +shuttle-runtime = "0.55.0" +shuttle-shared-db = { version = "0.55.0", features = ["opendal-postgres"] } tokio = "1.26.0" url = "2.5.4" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 78d1b33a..626320b9 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.54.0" -shuttle-runtime = "0.54.0" +shuttle-rocket = "0.55.0" +shuttle-runtime = "0.55.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index af37cbae..7d326797 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] salvo = "0.75.0" -shuttle-salvo = "0.54.0" -shuttle-runtime = "0.54.0" +shuttle-salvo = "0.55.0" +shuttle-runtime = "0.55.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml index 6e68dfd1..a43684b9 100644 --- a/salvo/image-rescaler/Cargo.toml +++ b/salvo/image-rescaler/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] image = "0.24.8" salvo = "0.75.0" -shuttle-salvo = "0.54.0" -shuttle-runtime = "0.54.0" +shuttle-salvo = "0.55.0" +shuttle-runtime = "0.55.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index a8ed5d33..c7bac413 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.54.0" -shuttle-serenity = "0.54.0" +shuttle-runtime = "0.55.0" +shuttle-serenity = "0.55.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index f6e58e02..9b6d0c4d 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.54.0" -shuttle-serenity = "0.54.0" -shuttle-shared-db = { version = "0.54.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.55.0" +shuttle-serenity = "0.55.0" +shuttle-shared-db = { version = "0.55.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/weather-forecast/Cargo.toml b/serenity/weather-forecast/Cargo.toml index e85f5338..38f8ef5e 100644 --- a/serenity/weather-forecast/Cargo.toml +++ b/serenity/weather-forecast/Cargo.toml @@ -8,7 +8,7 @@ anyhow = "1.0.66" reqwest = { version = "0.11.24", features = ["json"] } serde = "1.0.197" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.54.0" -shuttle-serenity = "0.54.0" +shuttle-runtime = "0.55.0" +shuttle-serenity = "0.55.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/shuttle-cron/Cargo.toml b/shuttle-cron/Cargo.toml index 723cf750..1bac6c42 100644 --- a/shuttle-cron/Cargo.toml +++ b/shuttle-cron/Cargo.toml @@ -10,7 +10,7 @@ apalis-sql = { version = "0.6", features = ["postgres"] } apalis-cron = { version = "0.6" } chrono = { version = "0.4.32", features = ["clock", "serde"] } serde = { version = "1.0.195", features = ["derive"] } -shuttle-runtime = "0.54.0" -shuttle-shared-db = { version = "0.54.0", features = ["postgres"] } +shuttle-runtime = "0.55.0" +shuttle-shared-db = { version = "0.55.0", features = ["postgres"] } sqlx = { version = "0.8", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index 7eabcf5d..fe738329 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.54.0" -shuttle-runtime = "0.54.0" +shuttle-thruster = "0.55.0" +shuttle-runtime = "0.55.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index 39cacdd6..e913f0a9 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.54.0" -shuttle-runtime = "0.54.0" +shuttle-tide = "0.55.0" +shuttle-runtime = "0.55.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index d9fd5a91..a9aef10e 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.54.0" -shuttle-tower = "0.54.0" +shuttle-runtime = "0.55.0" +shuttle-tower = "0.55.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index b225b383..34bbcecb 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.54.0" +shuttle-actix-web = "0.55.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.54.0", default-features = false } +shuttle-runtime = { version = "0.55.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 17a13fb3..a3b29a5f 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.54.0" -shuttle-warp = "0.54.0" +shuttle-runtime = "0.55.0" +shuttle-warp = "0.55.0" tokio = "1.26.0" warp = "0.3.3" From 637c01030037d00a52b9d0b02a37860a42b95d0c Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 21 May 2025 02:53:28 +0200 Subject: [PATCH 211/239] fix versions --- rama/hello-world-tcp/Cargo.toml | 4 ++-- rama/hello-world/Cargo.toml | 4 ++-- rama/static-files/Cargo.toml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/rama/hello-world-tcp/Cargo.toml b/rama/hello-world-tcp/Cargo.toml index e6df199a..a02a5f60 100644 --- a/rama/hello-world-tcp/Cargo.toml +++ b/rama/hello-world-tcp/Cargo.toml @@ -5,6 +5,6 @@ edition = "2024" [dependencies] rama = "0.2" -shuttle-rama = "0.54" -shuttle-runtime = "0.54" +shuttle-rama = "0.55.0" +shuttle-runtime = "0.55.0" tokio = "1.45" diff --git a/rama/hello-world/Cargo.toml b/rama/hello-world/Cargo.toml index c9fcb385..b02a6783 100644 --- a/rama/hello-world/Cargo.toml +++ b/rama/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2024" [dependencies] rama = { version = "0.2", features = ["http"] } -shuttle-rama = "0.54" -shuttle-runtime = "0.54" +shuttle-rama = "0.55.0" +shuttle-runtime = "0.55.0" tokio = "1.45" diff --git a/rama/static-files/Cargo.toml b/rama/static-files/Cargo.toml index 6693dcca..37604792 100644 --- a/rama/static-files/Cargo.toml +++ b/rama/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2024" [dependencies] rama = "0.2" -shuttle-rama = "0.54" -shuttle-runtime = "0.54" +shuttle-rama = "0.55.0" +shuttle-runtime = "0.55.0" tokio = "1.45" From 1f4943be248f4e718ec6a46c2d761cf409385d8f Mon Sep 17 00:00:00 2001 From: Shaaz Date: Fri, 6 Jun 2025 14:44:58 +0100 Subject: [PATCH 212/239] Add BetterStack resource metrics dashboard --- .../default-resource-metrics-dashboard.json | 288 ++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100644 telemetry-betterstack/default-resource-metrics-dashboard.json diff --git a/telemetry-betterstack/default-resource-metrics-dashboard.json b/telemetry-betterstack/default-resource-metrics-dashboard.json new file mode 100644 index 00000000..14850ce9 --- /dev/null +++ b/telemetry-betterstack/default-resource-metrics-dashboard.json @@ -0,0 +1,288 @@ +{ + "refresh_interval": 15, + "date_range_from": "now-3h", + "date_range_to": "now", + "preset": { + "id": 538311, + "name": null, + "preset_type": "implicit", + "preset_variables": [ + { + "name": "source", + "variable_type": "source", + "values": [ + "" + ] + }, + { + "name": "end_time", + "variable_type": "datetime", + "values": [ + "now" + ] + }, + { + "name": "start_time", + "variable_type": "datetime", + "values": [ + "now-3h" + ] + } + ] + }, + "charts": [ + { + "chart_type": "line_chart", + "name": "Memory allocated", + "description": null, + "x": 7, + "y": 0, + "w": 5, + "h": 7, + "transform_with": "// Transform chart data before rendering.\n// Following function is called when new data arrives, and again with `completed = true` after all data arrives.\n// You can transform the data here arbitrarily.\n// Most chart types expect columns 'time', 'value' and optionally 'series' by default.\nasync (existingDataByQuery, newDataByQuery, completed) => {\n return Object.keys(newDataByQuery).reduce((result, queryIndex) => {\n result[queryIndex] = result[queryIndex].concat(newDataByQuery[queryIndex]);\n return result;\n }, existingDataByQuery);\n}\n", + "finalize_with": null, + "fake_with": "async (fromString, toString) => {\n const from = new Date(fromString)\n const to = new Date(toString)\n\n function addSeconds(date, seconds) {\n return new Date(date.getTime() + seconds*1000)\n }\n\n function randomIntFromInterval(min, max) { // min and max included\n return Math.floor(Math.random() * (max - min + 1) + min)\n }\n\nfunction randomFloatFromInterval(min, max) {\n let cal = (Math.random() * (max - min) + min);\n return parseFloat(cal);\n}\n\n let data = []\n\n let time = from\n\n do {\n data.push({ time: time.toISOString(), value: randomFloatFromInterval(235,262), series: 'Memory obtained from the OS' })\n data.push({ time: time.toISOString(), value: randomFloatFromInterval(145,158), series: 'Size of allocated heap objects' })\n data.push({ time: time.toISOString(), value: randomFloatFromInterval(512,546), series: 'Total physical memory' })\n\n time = addSeconds(time, 3600)\n } while (time.getTime() <= to.getTime())\n\n return { 0: data }\n}", + "settings": { + "unit": "B_iec", + "label": "shown_below", + "legend": "shown_right", + "ttl_cache": "auto", + "lat_column": "lat", + "lng_column": "lng", + "time_column": "time", + "x_axis_type": "time", + "y_axis_scale": "linear", + "series_colors": { + "RSS memory": "#55bfc1", + "Heap allocated": "#009fe3", + "Total obtained from system": "#00af79" + }, + "series_column": "series", + "value_columns": [ + "value" + ], + "decimal_places": 2, + "point_size_column": "size", + "aggregation_period": 0, + "treat_missing_values": "connected", + "guessed_series_colors": { + "instance = 0.0.0.0:8888, job = otel-collector, service_instance_id = 7ed3f017-de26-4c9d-af43-77e6fa6d932f, service_name = otelcol, service_version = 0.90.1 - RSS memory": "#00af79", + "instance = 0.0.0.0:8888, job = otel-collector, service_instance_id = 7ed3f017-de26-4c9d-af43-77e6fa6d932f, service_name = otelcol, service_version = 0.90.1 - Heap allocated": "#55bfc1", + "instance = 0.0.0.0:8888, job = otel-collector, service_instance_id = 7ed3f017-de26-4c9d-af43-77e6fa6d932f, service_name = otelcol, service_version = 0.90.1 - Total obtained from system": "#009fe3" + }, + "manual_aggregation_period": false + }, + "chart_queries": [ + { + "query_type": "query_builder", + "sql_query": "WITH grouped_rate AS (\n \n SELECT\n {{time}} AS time,\n name,\n avgMerge(value_avg) AS inner_value,\n 'instance = ' || COALESCE(metricTag('instance'), 'null') || ', ' || 'job = ' || COALESCE(metricTag('job'), 'null') || ', ' || 'service_instance_id = ' || COALESCE(metricTag('service_instance_id'), 'null') || ', ' || 'service_name = ' || COALESCE(metricTag('service_name'), 'null') || ', ' || 'service_version = ' || COALESCE(metricTag('service_version'), 'null') AS inner_series\n FROM {{source}}\n WHERE\n name IN ('otelcol_process_runtime_total_sys_memory_bytes', 'otelcol_process_runtime_heap_alloc_bytes', 'otelcol_process_memory_rss')\n AND time BETWEEN {{start_time}} AND {{end_time}}\n GROUP BY time, name, inner_series, series_id\n \n),\narrayJoin([\n (inner_series || ' - ' || 'Total obtained from system', maxIf(inner_value, name = 'otelcol_process_runtime_total_sys_memory_bytes')),\n (inner_series || ' - ' || 'Heap allocated', maxIf(inner_value, name = 'otelcol_process_runtime_heap_alloc_bytes')),\n (inner_series || ' - ' || 'RSS memory', maxIf(inner_value, name = 'otelcol_process_memory_rss'))\n]) AS arrayJoinValues\nSELECT\n time,\n arrayJoinValues.1 AS series,\n arrayJoinValues.2 AS value\nFROM grouped_rate\nGROUP BY time, inner_series", + "group_by": [], + "where_condition": null, + "y_axis": [ + { + "type": "float", + "value": "otelcol_process_runtime_total_sys_memory_bytes", + "measure": "max", + "value_type": "value", + "series_name": "Total obtained from system" + }, + { + "type": "float", + "value": "otelcol_process_runtime_heap_alloc_bytes", + "measure": "max", + "value_type": "value", + "series_name": "Heap allocated" + }, + { + "type": "float", + "value": "otelcol_process_memory_rss", + "measure": "max", + "value_type": "value", + "series_name": "RSS memory" + } + ], + "filters": [], + "static_text": null, + "default_group_by": "nothing" + } + ], + "chart_alerts": [] + }, + { + "chart_type": "number_chart", + "name": "Status", + "description": null, + "x": 0, + "y": 0, + "w": 2, + "h": 7, + "transform_with": "// Transform chart data before rendering.\n// Following function is called when new data arrives, and again with `completed = true` after all data arrives.\n// You can transform the data here arbitrarily.\n// Most chart types expect columns 'time', 'value' and optionally 'series' by default.\nasync (existingDataByQuery, newDataByQuery, completed) => {\n return Object.keys(newDataByQuery).reduce((result, queryIndex) => {\n result[queryIndex] = result[queryIndex].concat(newDataByQuery[queryIndex]);\n return result;\n }, existingDataByQuery);\n}\n", + "finalize_with": null, + "fake_with": "async (fromString, toString) => {\n const from = new Date(fromString)\n const to = new Date(toString)\n\n function addSeconds(date, seconds) {\n return new Date(date.getTime() + seconds*1000)\n }\n\n function randomIntFromInterval(min, max) { // min and max included\n return Math.floor(Math.random() * (max - min + 1) + min)\n }\n\nfunction randomFloatFromInterval(min, max) {\n let cal = (Math.random() * (max - min) + min);\n return parseFloat(cal);\n}\n\n let data = []\n\n let time = from\n\n do {\n data.push({ time: time.toISOString(), value: randomFloatFromInterval(0,16), series: '1xx' })\n data.push({ time: time.toISOString(), value: randomFloatFromInterval(24312,27890), series: '2xx' })\n data.push({ time: time.toISOString(), value: randomFloatFromInterval(89,187), series: '3xx' })\n data.push({ time: time.toISOString(), value: randomFloatFromInterval(235,432), series: '4xx' })\n data.push({ time: time.toISOString(), value: randomFloatFromInterval(89,161), series: '5xx' })\n\n time = addSeconds(time, 3600)\n } while (time.getTime() <= to.getTime())\n\n return [ {value: 'Up'} ]\n}", + "settings": { + "unit": "auto", + "legend": "shown_below", + "ttl_cache": "auto", + "time_column": "time", + "y_axis_scale": "linear", + "series_column": "series", + "value_columns": [ + "value" + ], + "decimal_places": 2, + "point_size_column": "size", + "aggregation_period": 0, + "treat_missing_values": "connected", + "manual_aggregation_period": false + }, + "chart_queries": [ + { + "query_type": "sql_expression", + "sql_query": "SELECT\n {{time}} AS time,\n CASE\n WHEN maxMerge(value_max) = 1 THEN 'Up'\n ELSE 'Down'\n END AS value\nFROM {{source}}\nWHERE\n time BETWEEN {{start_time}} AND {{end_time}}\n AND name = 'up'\nGROUP BY time", + "group_by": [], + "where_condition": "AND", + "y_axis": null, + "filters": null, + "static_text": null, + "default_group_by": "everything" + } + ], + "chart_alerts": [] + }, + { + "chart_type": "line_chart", + "name": "Drag & drop query: avg(cpu.usage.vcpu) by level", + "description": null, + "x": 0, + "y": 7, + "w": 6, + "h": 8, + "transform_with": "// Transform chart data before rendering.\n// Following function is called when new data arrives, and again with `completed = true` after all data arrives.\n// You can transform the data here arbitrarily.\n// Most chart types expect columns 'time', 'value' and optionally 'series' by default.\nasync (existingDataByQuery, newDataByQuery, completed) => {\n return Object.keys(newDataByQuery).reduce((result, queryIndex) => {\n result[queryIndex] = result[queryIndex].concat(newDataByQuery[queryIndex]);\n return result;\n }, existingDataByQuery);\n}\n", + "finalize_with": null, + "fake_with": null, + "settings": { + "unit": "shortened", + "fresh": true, + "label": "shown_below", + "legend": "shown_below", + "stacking": "dont_stack", + "lat_column": "latitude", + "lng_column": "longitude", + "time_column": "time", + "x_axis_type": "time", + "y_axis_scale": "linear", + "series_colors": { + "level = INFO": "#009fe3", + "level = WARN": "#00af79", + "level = null": "#55bfc1" + }, + "series_column": "series", + "value_columns": [ + "value" + ], + "decimal_places": 2, + "point_size_column": "size", + "treat_missing_values": "connected", + "guessed_series_colors": { + "instance.id = 07dbdc7d23ef406cb2d56ccd3d059a08-1153448235, build.id = bld_01JW91EYYT792JTVM0PRJ0789K, deployment.version = 2, shuttle.project.id = proj_01JW911KDGA1QXENA3PXZYWAEX, service.name = test-2, shuttle.project.name = test-2, shuttle.deployment.env = null, telemetry.sdk.version = null, telemetry.sdk.language = null, telemetry.sdk.name = null, service.version = null, shuttle.project.crate.name = null, message = null": "#009fe3", + "instance.id = f00f584b752e4fec9157f46e8d543ba5-1153448235, build.id = bld_01JW923JJPSW6ZQAY6AHHGCMXN, deployment.version = 3, shuttle.project.id = proj_01JW911KDGA1QXENA3PXZYWAEX, service.name = test-2, shuttle.project.name = test-2, shuttle.deployment.env = null, telemetry.sdk.version = null, telemetry.sdk.language = null, telemetry.sdk.name = null, service.version = null, shuttle.project.crate.name = null, message = null": "#007bb1", + "instance.id = 04786d96bc3347a3a022df715ae13464-1153448235, build.id = bld_01JEMEBT857HXGSAV4JR5RJD0S, deployment.version = 8, shuttle.project.id = proj_01JE3HDXYJCEANBZB1V6M8F291, service.name = shuttlings-cch24-new, shuttle.project.name = shuttlings-cch24-new, shuttle.deployment.env = null, telemetry.sdk.version = null, telemetry.sdk.language = null, telemetry.sdk.name = null, service.version = null, shuttle.project.crate.name = null, message = null": "#005e88" + } + }, + "chart_queries": [ + { + "query_type": "query_builder", + "sql_query": "WITH grouped_rate AS (\n \n SELECT\n {{time}} AS time,\n name,\n avgMerge(value_avg) AS inner_value,\n 'instance.id = ' || COALESCE(metricTag('instance.id'), 'null') || ', ' || 'build.id = ' || COALESCE(metricTag('build.id'), 'null') || ', ' || 'deployment.version = ' || COALESCE(metricTag('deployment.version'), 'null') || ', ' || 'shuttle.project.id = ' || COALESCE(metricTag('shuttle.project.id'), 'null') || ', ' || 'service.name = ' || COALESCE(metricTag('service.name'), 'null') || ', ' || 'shuttle.project.name = ' || COALESCE(metricTag('shuttle.project.name'), 'null') || ', ' || 'shuttle.deployment.env = ' || COALESCE(metricTag('shuttle.deployment.env'), 'null') || ', ' || 'telemetry.sdk.version = ' || COALESCE(metricTag('telemetry.sdk.version'), 'null') || ', ' || 'telemetry.sdk.language = ' || COALESCE(metricTag('telemetry.sdk.language'), 'null') || ', ' || 'telemetry.sdk.name = ' || COALESCE(metricTag('telemetry.sdk.name'), 'null') || ', ' || 'service.version = ' || COALESCE(metricTag('service.version'), 'null') || ', ' || 'shuttle.project.crate.name = ' || COALESCE(metricTag('shuttle.project.crate.name'), 'null') || ', ' || 'message = ' || COALESCE(metricTag('message'), 'null') AS inner_series\n FROM {{source}}\n WHERE\n name IN ('cpu.usage.vcpu')\n AND time BETWEEN {{start_time}} AND {{end_time}}\n GROUP BY time, name, inner_series, series_id\n \n),\narrayJoin([\n (inner_series, avgIf(inner_value, name = 'cpu.usage.vcpu'))\n]) AS arrayJoinValues\nSELECT\n time,\n arrayJoinValues.1 AS series,\n arrayJoinValues.2 AS value\nFROM grouped_rate\nGROUP BY time, inner_series", + "group_by": [ + { + "name": "level", + "type": "string", + "value": "level" + } + ], + "where_condition": null, + "y_axis": [ + { + "type": "float", + "value": "cpu.usage.vcpu", + "measure": "avg", + "value_type": "value" + } + ], + "filters": [], + "static_text": null, + "default_group_by": "everything" + } + ], + "chart_alerts": [] + }, + { + "chart_type": "line_chart", + "name": "Drag & drop query: avg(memory.usage) by level", + "description": null, + "x": 6, + "y": 7, + "w": 6, + "h": 8, + "transform_with": "// Transform chart data before rendering.\n// Following function is called when new data arrives, and again with `completed = true` after all data arrives.\n// You can transform the data here arbitrarily.\n// Most chart types expect columns 'time', 'value' and optionally 'series' by default.\nasync (existingDataByQuery, newDataByQuery, completed) => {\n return Object.keys(newDataByQuery).reduce((result, queryIndex) => {\n result[queryIndex] = result[queryIndex].concat(newDataByQuery[queryIndex]);\n return result;\n }, existingDataByQuery);\n}\n", + "finalize_with": null, + "fake_with": null, + "settings": { + "unit": "shortened", + "fresh": true, + "label": "shown_below", + "legend": "shown_below", + "stacking": "dont_stack", + "lat_column": "latitude", + "lng_column": "longitude", + "time_column": "time", + "x_axis_type": "time", + "y_axis_scale": "linear", + "series_colors": { + "instance.id = 07dbdc7d23ef406cb2d56ccd3d059a08-1153448235, build.id = bld_01JW91EYYT792JTVM0PRJ0789K, deployment.version = 2, shuttle.project.id = proj_01JW911KDGA1QXENA3PXZYWAEX, service.name = test-2, shuttle.project.name = test-2, shuttle.deployment.env = null, telemetry.sdk.version = null, telemetry.sdk.language = null, telemetry.sdk.name = null, service.version = null, shuttle.project.crate.name = null, message = null": "#009fe3", + "instance.id = f00f584b752e4fec9157f46e8d543ba5-1153448235, build.id = bld_01JW923JJPSW6ZQAY6AHHGCMXN, deployment.version = 3, shuttle.project.id = proj_01JW911KDGA1QXENA3PXZYWAEX, service.name = test-2, shuttle.project.name = test-2, shuttle.deployment.env = null, telemetry.sdk.version = null, telemetry.sdk.language = null, telemetry.sdk.name = null, service.version = null, shuttle.project.crate.name = null, message = null": "#00af79", + "instance.id = 04786d96bc3347a3a022df715ae13464-1153448235, build.id = bld_01JEMEBT857HXGSAV4JR5RJD0S, deployment.version = 8, shuttle.project.id = proj_01JE3HDXYJCEANBZB1V6M8F291, service.name = shuttlings-cch24-new, shuttle.project.name = shuttlings-cch24-new, shuttle.deployment.env = null, telemetry.sdk.version = null, telemetry.sdk.language = null, telemetry.sdk.name = null, service.version = null, shuttle.project.crate.name = null, message = null": "#55bfc1" + }, + "series_column": "series", + "value_columns": [ + "value" + ], + "decimal_places": 2, + "point_size_column": "size", + "treat_missing_values": "connected", + "guessed_series_colors": { + "instance.id = 07dbdc7d23ef406cb2d56ccd3d059a08-1153448235, build.id = bld_01JW91EYYT792JTVM0PRJ0789K, deployment.version = 2, shuttle.project.id = proj_01JW911KDGA1QXENA3PXZYWAEX, service.name = test-2, shuttle.project.name = test-2, shuttle.deployment.env = null, telemetry.sdk.version = null, telemetry.sdk.language = null, telemetry.sdk.name = null, service.version = null, shuttle.project.crate.name = null, message = null": "#009fe3", + "instance.id = f00f584b752e4fec9157f46e8d543ba5-1153448235, build.id = bld_01JW923JJPSW6ZQAY6AHHGCMXN, deployment.version = 3, shuttle.project.id = proj_01JW911KDGA1QXENA3PXZYWAEX, service.name = test-2, shuttle.project.name = test-2, shuttle.deployment.env = null, telemetry.sdk.version = null, telemetry.sdk.language = null, telemetry.sdk.name = null, service.version = null, shuttle.project.crate.name = null, message = null": "#007bb1", + "instance.id = 04786d96bc3347a3a022df715ae13464-1153448235, build.id = bld_01JEMEBT857HXGSAV4JR5RJD0S, deployment.version = 8, shuttle.project.id = proj_01JE3HDXYJCEANBZB1V6M8F291, service.name = shuttlings-cch24-new, shuttle.project.name = shuttlings-cch24-new, shuttle.deployment.env = null, telemetry.sdk.version = null, telemetry.sdk.language = null, telemetry.sdk.name = null, service.version = null, shuttle.project.crate.name = null, message = null": "#005e88" + } + }, + "chart_queries": [ + { + "query_type": "query_builder", + "sql_query": "WITH grouped_rate AS (\n \n SELECT\n {{time}} AS time,\n name,\n avgMerge(value_avg) AS inner_value,\n 'instance.id = ' || COALESCE(metricTag('instance.id'), 'null') || ', ' || 'build.id = ' || COALESCE(metricTag('build.id'), 'null') || ', ' || 'deployment.version = ' || COALESCE(metricTag('deployment.version'), 'null') || ', ' || 'shuttle.project.id = ' || COALESCE(metricTag('shuttle.project.id'), 'null') || ', ' || 'service.name = ' || COALESCE(metricTag('service.name'), 'null') || ', ' || 'shuttle.project.name = ' || COALESCE(metricTag('shuttle.project.name'), 'null') || ', ' || 'shuttle.deployment.env = ' || COALESCE(metricTag('shuttle.deployment.env'), 'null') || ', ' || 'telemetry.sdk.version = ' || COALESCE(metricTag('telemetry.sdk.version'), 'null') || ', ' || 'telemetry.sdk.language = ' || COALESCE(metricTag('telemetry.sdk.language'), 'null') || ', ' || 'telemetry.sdk.name = ' || COALESCE(metricTag('telemetry.sdk.name'), 'null') || ', ' || 'service.version = ' || COALESCE(metricTag('service.version'), 'null') || ', ' || 'shuttle.project.crate.name = ' || COALESCE(metricTag('shuttle.project.crate.name'), 'null') || ', ' || 'message = ' || COALESCE(metricTag('message'), 'null') AS inner_series\n FROM {{source}}\n WHERE\n name IN ('memory.usage')\n AND time BETWEEN {{start_time}} AND {{end_time}}\n GROUP BY time, name, inner_series, series_id\n \n),\narrayJoin([\n (inner_series, avgIf(inner_value, name = 'memory.usage'))\n]) AS arrayJoinValues\nSELECT\n time,\n arrayJoinValues.1 AS series,\n arrayJoinValues.2 AS value\nFROM grouped_rate\nGROUP BY time, inner_series", + "group_by": [ + { + "name": "level", + "type": "string", + "value": "level" + } + ], + "where_condition": null, + "y_axis": [ + { + "type": "float", + "value": "memory.usage", + "measure": "avg", + "value_type": "value" + } + ], + "filters": [], + "static_text": null, + "default_group_by": "everything" + } + ], + "chart_alerts": [] + } + ], + "sections": [] +} From 470d74533efe14aaf6b20a2c22ad7e4b039f47cd Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 11 Jun 2025 18:45:28 +0200 Subject: [PATCH 213/239] nit: delete unused secrets file --- rocket/postgres/Secrets.toml | 1 - 1 file changed, 1 deletion(-) delete mode 100644 rocket/postgres/Secrets.toml diff --git a/rocket/postgres/Secrets.toml b/rocket/postgres/Secrets.toml deleted file mode 100644 index fd76ede3..00000000 --- a/rocket/postgres/Secrets.toml +++ /dev/null @@ -1 +0,0 @@ -PASSWORD = "test" From 20d8cd041582cc61dafa68cd0a5db632fd46a71d Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Tue, 1 Jul 2025 15:19:01 +0200 Subject: [PATCH 214/239] chore: v0.56.0 --- actix-web/clerk/backend/Cargo.toml | 4 ++-- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/htmx-crud/Cargo.toml | 6 +++--- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 4 ++-- axum/oauth2/Cargo.toml | 6 +++--- axum/openai/Cargo.toml | 8 ++++---- axum/postgres/Cargo.toml | 6 +++--- axum/qdrant/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- bevy/hello-world/server/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- fullstack-templates/saas/backend/Cargo.toml | 6 +++--- loco/hello-world/Cargo.toml | 4 ++-- other/feature-flags/Cargo.toml | 4 ++-- other/standalone-binary/Cargo.toml | 4 ++-- poem/hello-world/Cargo.toml | 4 ++-- poise/hello-world/Cargo.toml | 4 ++-- rama/hello-world-tcp/Cargo.toml | 4 ++-- rama/hello-world/Cargo.toml | 4 ++-- rama/static-files/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/opendal-memory/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 4 ++-- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- salvo/image-rescaler/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 6 +++--- serenity/weather-forecast/Cargo.toml | 4 ++-- shuttle-cron/Cargo.toml | 4 ++-- thruster/hello-world/Cargo.toml | 4 ++-- tide/hello-world/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 49 files changed, 111 insertions(+), 111 deletions(-) diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml index 65ceb136..18fbc21a 100644 --- a/actix-web/clerk/backend/Cargo.toml +++ b/actix-web/clerk/backend/Cargo.toml @@ -10,5 +10,5 @@ clerk-rs = "0.2.3" openssl-sys = { version = "0.9.9", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-actix-web = "0.56.0" +shuttle-runtime = "0.56.0" diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index 2969c077..298143b8 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.7.1" actix-session = { version = "0.9.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-actix-web = "0.56.0" +shuttle-runtime = "0.56.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index d99ebcb8..0deef4be 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-actix-web = "0.56.0" +shuttle-runtime = "0.56.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 2db05963..1d77e68e 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-actix-web = "0.56.0" +shuttle-runtime = "0.56.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.55.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index c91db9cf..87c9c678 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-actix-web = "0.56.0" +shuttle-runtime = "0.56.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 377e2ef0..9a2b4992 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-actix-web = "0.56.0" +shuttle-runtime = "0.56.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 8f16dc7c..7f88f5c1 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.8.1" -shuttle-axum = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-axum = "0.56.0" +shuttle-runtime = "0.56.0" tokio = "1.28.2" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index 2930cfe8..9ddfbb13 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -9,9 +9,9 @@ askama_axum = "0.4.0" axum = "0.7.4" serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.55.0" -shuttle-shared-db = { version = "0.55.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.56.0" +shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index d89250fa..e50e38e0 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,7 +10,7 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" -shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.55.0" +shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.56.0" tokio = "1.28.2" tracing-subscriber = "0.3.17" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index 000e9549..7e49e951 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.55.0" +shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.56.0" tokio = "1.28.2" diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index d6d2322d..817b46e3 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -11,9 +11,9 @@ chrono = { version = "0.4.35", features = ["clock"] } oauth2 = "4.4.1" reqwest = { version = "0.11.18", features = ["json"] } serde = { version = "1.0.183", features = ["derive"] } -shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.55.0" -shuttle-shared-db = { version = "0.55.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.56.0" +shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["macros", "chrono"] } thiserror = "1.0.57" time = "0.3.25" diff --git a/axum/openai/Cargo.toml b/axum/openai/Cargo.toml index 21a82a9a..fd6a92ae 100644 --- a/axum/openai/Cargo.toml +++ b/axum/openai/Cargo.toml @@ -12,10 +12,10 @@ derive_more = { version = "1.0.0", features = ["full"] } jsonwebtoken = "9.3.0" serde = { version = "1.0.215", features = ["derive"] } serde_json = "1.0.133" -shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } -shuttle-openai = "0.55.0" -shuttle-runtime = "0.55.0" -shuttle-shared-db = { version = "0.55.0", features = ["postgres"] } +shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +shuttle-openai = "0.56.0" +shuttle-runtime = "0.56.0" +shuttle-shared-db = { version = "0.56.0", features = ["postgres"] } sqlx = { version = "0.8.2", features = [ "runtime-tokio-rustls", "postgres", diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 8fa007d2..79f4e859 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.7.3" serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.55.0" -shuttle-shared-db = { version = "0.55.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.56.0" +shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index 998b367a..45c1332f 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.7.3" qdrant-client = "1.10.1" -shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } -shuttle-qdrant = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +shuttle-qdrant = "0.56.0" +shuttle-runtime = "0.56.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 9dbbe1a9..4bd0620f 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.55.0" +shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.56.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index fb03fbf5..543f496a 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.55.0" -shuttle-turso = "0.55.0" +shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.56.0" +shuttle-turso = "0.56.0" libsql = "0.6.0" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 9d75dd8e..77696cb0 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.11.23" serde = { version = "1.0.163", features = ["derive"] } serde_json = "1.0.96" -shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.55.0" +shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.56.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/bevy/hello-world/server/Cargo.toml b/bevy/hello-world/server/Cargo.toml index 881699ee..89041337 100644 --- a/bevy/hello-world/server/Cargo.toml +++ b/bevy/hello-world/server/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.7.4" -shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.55.0" +shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.56.0" tokio = "1.28.2" tower-http = { version = "0.5.0", features = ["fs"] } diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index 5394744c..d87b7011 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.7.3" serde = { version = "1", features = ["derive"] } -shuttle-service = "0.55.0" -shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.55.0" +shuttle-service = "0.56.0" +shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.56.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index d912a8aa..d303c5fb 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.55.0" +shuttle-runtime = "0.56.0" tokio = "1" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 89bdfadd..96eb8f82 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,9 +16,9 @@ lettre = "0.11.4" rand = "0.8.5" reqwest = "0.11.16" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.55.0" -shuttle-shared-db = { version = "0.55.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.56.0" +shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index e6d070c7..2d4ecf2c 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -13,8 +13,8 @@ default-run = "hello_world-cli" loco-rs = { version = "0.14.0", default-features = false } [dependencies] -shuttle-axum = "0.55.0" -shuttle-runtime = { version = "0.55.0", default-features = false } +shuttle-axum = "0.56.0" +shuttle-runtime = { version = "0.56.0", default-features = false } loco-rs = { workspace = true , features = ["cli"] } serde = { version = "1", features = ["derive"] } diff --git a/other/feature-flags/Cargo.toml b/other/feature-flags/Cargo.toml index 3f69a4c2..c7b73a5f 100644 --- a/other/feature-flags/Cargo.toml +++ b/other/feature-flags/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.7.3" -shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.55.0" +shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.56.0" [features] # Shuttle will disable default features and enable the feature "shuttle" if it exists. diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 29d1587f..1aeb613c 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,6 +15,6 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.7.3" dotenvy = "0.15.7" -shuttle-axum = { version = "0.55.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.55.0" +shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.56.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index e808feaa..c6e21cab 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "3.0.0" -shuttle-poem = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-poem = "0.56.0" +shuttle-runtime = "0.56.0" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index b2677698..12454b2d 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.6.1" -shuttle-runtime = "0.55.0" +shuttle-runtime = "0.56.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity -shuttle-serenity = "0.55.0" +shuttle-serenity = "0.56.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rama/hello-world-tcp/Cargo.toml b/rama/hello-world-tcp/Cargo.toml index a02a5f60..bbafab91 100644 --- a/rama/hello-world-tcp/Cargo.toml +++ b/rama/hello-world-tcp/Cargo.toml @@ -5,6 +5,6 @@ edition = "2024" [dependencies] rama = "0.2" -shuttle-rama = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-rama = "0.56.0" +shuttle-runtime = "0.56.0" tokio = "1.45" diff --git a/rama/hello-world/Cargo.toml b/rama/hello-world/Cargo.toml index b02a6783..d366ecb8 100644 --- a/rama/hello-world/Cargo.toml +++ b/rama/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2024" [dependencies] rama = { version = "0.2", features = ["http"] } -shuttle-rama = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-rama = "0.56.0" +shuttle-runtime = "0.56.0" tokio = "1.45" diff --git a/rama/static-files/Cargo.toml b/rama/static-files/Cargo.toml index 37604792..202894b0 100644 --- a/rama/static-files/Cargo.toml +++ b/rama/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2024" [dependencies] rama = "0.2" -shuttle-rama = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-rama = "0.56.0" +shuttle-runtime = "0.56.0" tokio = "1.45" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 4e7af13d..9dcd6b32 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" rocket_dyn_templates = { version = "0.1.0", features = ["handlebars"] } -shuttle-rocket = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-rocket = "0.56.0" +shuttle-runtime = "0.56.0" tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index aa622b15..75a532dd 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-rocket = "0.56.0" +shuttle-runtime = "0.56.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 584283b4..83970d22 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-rocket = "0.56.0" +shuttle-runtime = "0.56.0" tokio = "1.26.0" diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index 6930c91c..0900662b 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" opendal = "0.51" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-opendal = "0.55.0" -shuttle-rocket = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-opendal = "0.56.0" +shuttle-rocket = "0.56.0" +shuttle-runtime = "0.56.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 3f473335..36c6c8cd 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.55.0" -shuttle-runtime = "0.55.0" -shuttle-shared-db = { version = "0.55.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.56.0" +shuttle-runtime = "0.56.0" +shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 79252a1a..1e82b25b 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-rocket = "0.56.0" +shuttle-runtime = "0.56.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index db137c16..5ef197a4 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-rocket = "0.56.0" +shuttle-runtime = "0.56.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 2689f9bb..3d22f9f0 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -8,8 +8,8 @@ nanoid = "0.4.0" opendal = "0.51" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.55.0" -shuttle-runtime = "0.55.0" -shuttle-shared-db = { version = "0.55.0", features = ["opendal-postgres"] } +shuttle-rocket = "0.56.0" +shuttle-runtime = "0.56.0" +shuttle-shared-db = { version = "0.56.0", features = ["opendal-postgres"] } tokio = "1.26.0" url = "2.5.4" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index 626320b9..aa0ef458 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-rocket = "0.56.0" +shuttle-runtime = "0.56.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index 7d326797..b4c4393d 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] salvo = "0.75.0" -shuttle-salvo = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-salvo = "0.56.0" +shuttle-runtime = "0.56.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml index a43684b9..93633757 100644 --- a/salvo/image-rescaler/Cargo.toml +++ b/salvo/image-rescaler/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] image = "0.24.8" salvo = "0.75.0" -shuttle-salvo = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-salvo = "0.56.0" +shuttle-runtime = "0.56.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index c7bac413..b6367810 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.55.0" -shuttle-serenity = "0.55.0" +shuttle-runtime = "0.56.0" +shuttle-serenity = "0.56.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 9b6d0c4d..80bc410c 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.55.0" -shuttle-serenity = "0.55.0" -shuttle-shared-db = { version = "0.55.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.56.0" +shuttle-serenity = "0.56.0" +shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/weather-forecast/Cargo.toml b/serenity/weather-forecast/Cargo.toml index 38f8ef5e..187e6464 100644 --- a/serenity/weather-forecast/Cargo.toml +++ b/serenity/weather-forecast/Cargo.toml @@ -8,7 +8,7 @@ anyhow = "1.0.66" reqwest = { version = "0.11.24", features = ["json"] } serde = "1.0.197" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.55.0" -shuttle-serenity = "0.55.0" +shuttle-runtime = "0.56.0" +shuttle-serenity = "0.56.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/shuttle-cron/Cargo.toml b/shuttle-cron/Cargo.toml index 1bac6c42..dd8d4135 100644 --- a/shuttle-cron/Cargo.toml +++ b/shuttle-cron/Cargo.toml @@ -10,7 +10,7 @@ apalis-sql = { version = "0.6", features = ["postgres"] } apalis-cron = { version = "0.6" } chrono = { version = "0.4.32", features = ["clock", "serde"] } serde = { version = "1.0.195", features = ["derive"] } -shuttle-runtime = "0.55.0" -shuttle-shared-db = { version = "0.55.0", features = ["postgres"] } +shuttle-runtime = "0.56.0" +shuttle-shared-db = { version = "0.56.0", features = ["postgres"] } sqlx = { version = "0.8", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml index fe738329..0e6f1c7d 100644 --- a/thruster/hello-world/Cargo.toml +++ b/thruster/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-thruster = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-thruster = "0.56.0" +shuttle-runtime = "0.56.0" thruster = { version = "1.3.0", features = ["hyper_server"] } tokio = "1.26.0" diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml index e913f0a9..9dd2fef3 100644 --- a/tide/hello-world/Cargo.toml +++ b/tide/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-tide = "0.55.0" -shuttle-runtime = "0.55.0" +shuttle-tide = "0.56.0" +shuttle-runtime = "0.56.0" tokio = "1.26.0" tide = "0.16.0" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index a9aef10e..515a2f3e 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.55.0" -shuttle-tower = "0.55.0" +shuttle-runtime = "0.56.0" +shuttle-tower = "0.56.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 34bbcecb..7417858f 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.55.0" +shuttle-actix-web = "0.56.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.55.0", default-features = false } +shuttle-runtime = { version = "0.56.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index a3b29a5f..28018fca 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.55.0" -shuttle-warp = "0.55.0" +shuttle-runtime = "0.56.0" +shuttle-warp = "0.56.0" tokio = "1.26.0" warp = "0.3.3" From 283d9a40482b56fc63b1789670e8bee3a765021f Mon Sep 17 00:00:00 2001 From: dcodes <101001810+dcodesdev@users.noreply.github.com> Date: Thu, 3 Jul 2025 19:41:28 +0300 Subject: [PATCH 215/239] New Template: Axum AI Assisted (#221) --- axum/ai-assisted/.cursor/mcp.json | 8 ++++++++ axum/ai-assisted/.cursor/rules/general.mdc | 12 ++++++++++++ axum/ai-assisted/.cursor/rules/rust.mdc | 12 ++++++++++++ axum/ai-assisted/Cargo.toml | 10 ++++++++++ axum/ai-assisted/src/main.rs | 12 ++++++++++++ templates.toml | 7 +++++++ 6 files changed, 61 insertions(+) create mode 100644 axum/ai-assisted/.cursor/mcp.json create mode 100644 axum/ai-assisted/.cursor/rules/general.mdc create mode 100644 axum/ai-assisted/.cursor/rules/rust.mdc create mode 100644 axum/ai-assisted/Cargo.toml create mode 100644 axum/ai-assisted/src/main.rs diff --git a/axum/ai-assisted/.cursor/mcp.json b/axum/ai-assisted/.cursor/mcp.json new file mode 100644 index 00000000..de4dadf8 --- /dev/null +++ b/axum/ai-assisted/.cursor/mcp.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "Shuttle": { + "command": "shuttle", + "args": ["mcp", "start"] + } + } +} diff --git a/axum/ai-assisted/.cursor/rules/general.mdc b/axum/ai-assisted/.cursor/rules/general.mdc new file mode 100644 index 00000000..b444b52b --- /dev/null +++ b/axum/ai-assisted/.cursor/rules/general.mdc @@ -0,0 +1,12 @@ +--- +description: +globs: +alwaysApply: true +--- +- Always use the `search_docs` MCP tool to search through the Shuttle documentation. +- Keep code simple, readable, and follow established patterns in the codebase. +- Write self-documenting code with clear variable and function names. +- Handle errors gracefully and provide meaningful error messages. +- Prefer composition over inheritance and favor immutability when possible. +- Write tests for critical functionality and edge cases. +- Avoid premature optimization - write clear code first, optimize later if needed. \ No newline at end of file diff --git a/axum/ai-assisted/.cursor/rules/rust.mdc b/axum/ai-assisted/.cursor/rules/rust.mdc new file mode 100644 index 00000000..b03345d5 --- /dev/null +++ b/axum/ai-assisted/.cursor/rules/rust.mdc @@ -0,0 +1,12 @@ +--- +description: +globs: *.rs +alwaysApply: false +--- + +- Use explicit error handling with `Result` and avoid unwrap() in production code. +- Prefer borrowing (&T) over owned values (T) in function parameters when possible. +- Use pattern matching exhaustively and handle all enum variants explicitly. +- Keep functions small and focused on a single responsibility. +- Use `derive` macros for common traits like Debug, Clone, PartialEq when appropriate. +- Leverage the type system to prevent invalid states at compile time. diff --git a/axum/ai-assisted/Cargo.toml b/axum/ai-assisted/Cargo.toml new file mode 100644 index 00000000..6826d49f --- /dev/null +++ b/axum/ai-assisted/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "axum-ai-assisted" +version = "0.1.0" +edition = "2021" + +[dependencies] +axum = "0.8" +shuttle-axum = "0.56.0" +shuttle-runtime = "0.56.0" +tokio = "1.46" diff --git a/axum/ai-assisted/src/main.rs b/axum/ai-assisted/src/main.rs new file mode 100644 index 00000000..d3b9ea08 --- /dev/null +++ b/axum/ai-assisted/src/main.rs @@ -0,0 +1,12 @@ +use axum::{routing::get, Router}; + +async fn hello_world() -> &'static str { + "Hello, world!" +} + +#[shuttle_runtime::main] +async fn main() -> shuttle_axum::ShuttleAxum { + let router = Router::new().route("/", get(hello_world)); + + Ok(router.into()) +} diff --git a/templates.toml b/templates.toml index 8b55af77..59141e6d 100644 --- a/templates.toml +++ b/templates.toml @@ -209,6 +209,13 @@ path = "axum/oauth2" use_cases = ["Web app", "Authentication"] tags = ["axum", "oauth"] +[templates.axum-ai-assisted] +title = "AI Assisted" +description = "AI-assisted development template" +path = "axum/ai-assisted" +use_cases = ["Web app", "AI"] +tags = ["axum", "ai"] + [templates.axum-openai] title = "OpenAI ChatGPT chat" description = "Connect your app to OpenAI ChatGPT" From 1eae9bcf78361790071ef9f5cf81ad8ff17175c6 Mon Sep 17 00:00:00 2001 From: dcodes <101001810+dcodesdev@users.noreply.github.com> Date: Tue, 8 Jul 2025 20:23:21 +0300 Subject: [PATCH 216/239] Updated a template to use axum 0.8 (#220) --- axum/hello-world/Cargo.toml | 2 +- axum/static-files/Cargo.toml | 6 +++--- axum/static-files/src/main.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 7f88f5c1..7d5403d1 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = "0.8.1" +axum = "0.8" shuttle-axum = "0.56.0" shuttle-runtime = "0.56.0" tokio = "1.28.2" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index 4bd0620f..bac9ba36 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" publish = false [dependencies] -axum = "0.7.3" -shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +axum = "0.8" +shuttle-axum = "0.56.0" shuttle-runtime = "0.56.0" tokio = "1.28.2" -tower-http = { version = "0.5.0", features = ["fs"] } +tower-http = { version = "0.6", features = ["fs"] } diff --git a/axum/static-files/src/main.rs b/axum/static-files/src/main.rs index 2213bd4b..2789e2c5 100644 --- a/axum/static-files/src/main.rs +++ b/axum/static-files/src/main.rs @@ -4,7 +4,7 @@ use tower_http::services::ServeDir; #[shuttle_runtime::main] async fn main() -> shuttle_axum::ShuttleAxum { // ServeDir falls back to serve index.html when requesting a directory - let router = Router::new().nest_service("/", ServeDir::new("assets")); + let router = Router::new().fallback_service(ServeDir::new("assets")); Ok(router.into()) } From 039d7d0130ebad66e2111e39e9a3ca50e914568a Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 9 Jul 2025 13:40:22 +0200 Subject: [PATCH 217/239] feat: Axum Todo list template (#216) * nit: remove gitignores * feat: axum-todo-list template * update axum websocket * bump shuttle * size limit for salvo image rescaler * 1.88 clippy * nit: rename bevy dist folder --- axum/htmx-crud/.gitignore | 3 - axum/htmx-crud/src/routes.rs | 5 +- axum/jwt-authentication/.gitignore | 2 - axum/metadata/src/main.rs | 2 +- axum/oauth2/.gitignore | 2 - axum/openai/.gitignore | 3 - axum/postgres/.gitignore | 2 - axum/todo-list/Cargo.toml | 15 +++ axum/todo-list/README.md | 28 +++++ axum/todo-list/Shuttle.toml | 4 + axum/todo-list/assets/index.html | 26 +++++ axum/todo-list/assets/script.js | 106 +++++++++++++++++ axum/todo-list/assets/style.css | 67 +++++++++++ axum/todo-list/migrations/0001_init.sql | 4 + axum/todo-list/src/main.rs | 108 ++++++++++++++++++ axum/websocket/Cargo.toml | 16 +-- axum/websocket/src/main.rs | 6 +- bevy/hello-world/.gitignore | 6 +- bevy/hello-world/Makefile | 2 +- bevy/hello-world/README.md | 1 + bevy/hello-world/Shuttle.toml | 4 +- .../{dist => assets}/Roboto-Black.ttf | Bin bevy/hello-world/{dist => assets}/index.html | 0 bevy/hello-world/server/src/main.rs | 2 +- custom-resource/pdo/.gitignore | 2 - rocket/opendal-memory/src/main.rs | 2 +- rocket/static-files/.gitignore | 2 - salvo/image-rescaler/src/main.rs | 5 + serenity/postgres/src/db.rs | 2 +- serenity/weather-forecast/src/main.rs | 2 +- serenity/weather-forecast/src/weather.rs | 2 +- shuttle-cron/.gitignore | 3 - templates.toml | 7 ++ 33 files changed, 395 insertions(+), 46 deletions(-) delete mode 100644 axum/htmx-crud/.gitignore delete mode 100644 axum/jwt-authentication/.gitignore delete mode 100644 axum/oauth2/.gitignore delete mode 100644 axum/openai/.gitignore delete mode 100644 axum/postgres/.gitignore create mode 100644 axum/todo-list/Cargo.toml create mode 100644 axum/todo-list/README.md create mode 100644 axum/todo-list/Shuttle.toml create mode 100644 axum/todo-list/assets/index.html create mode 100644 axum/todo-list/assets/script.js create mode 100644 axum/todo-list/assets/style.css create mode 100644 axum/todo-list/migrations/0001_init.sql create mode 100644 axum/todo-list/src/main.rs rename bevy/hello-world/{dist => assets}/Roboto-Black.ttf (100%) rename bevy/hello-world/{dist => assets}/index.html (100%) delete mode 100644 custom-resource/pdo/.gitignore delete mode 100644 rocket/static-files/.gitignore delete mode 100644 shuttle-cron/.gitignore diff --git a/axum/htmx-crud/.gitignore b/axum/htmx-crud/.gitignore deleted file mode 100644 index e8541fe9..00000000 --- a/axum/htmx-crud/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/target -.shuttle-storage -Secrets*.toml diff --git a/axum/htmx-crud/src/routes.rs b/axum/htmx-crud/src/routes.rs index 7d4cd504..afe0e8e9 100644 --- a/axum/htmx-crud/src/routes.rs +++ b/axum/htmx-crud/src/routes.rs @@ -83,10 +83,7 @@ pub async fn delete_todo( }) .is_err() { - eprintln!( - "Record with ID {} was deleted but nobody's listening to the stream!", - id - ); + eprintln!("Record with ID {id} was deleted but nobody's listening to the stream!"); } Ok(StatusCode::OK) diff --git a/axum/jwt-authentication/.gitignore b/axum/jwt-authentication/.gitignore deleted file mode 100644 index a1a5734e..00000000 --- a/axum/jwt-authentication/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target -Secrets*.toml diff --git a/axum/metadata/src/main.rs b/axum/metadata/src/main.rs index 9ddc6ac6..d30418f8 100644 --- a/axum/metadata/src/main.rs +++ b/axum/metadata/src/main.rs @@ -5,7 +5,7 @@ use shuttle_runtime::DeploymentMetadata; async fn main( #[shuttle_runtime::Metadata] metadata: DeploymentMetadata, ) -> shuttle_axum::ShuttleAxum { - let router = Router::new().route("/", get(format!("{:?}", metadata))); + let router = Router::new().route("/", get(format!("{metadata:?}"))); Ok(router.into()) } diff --git a/axum/oauth2/.gitignore b/axum/oauth2/.gitignore deleted file mode 100644 index 4fcf1cd7..00000000 --- a/axum/oauth2/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -target/ -Secrets*.toml diff --git a/axum/openai/.gitignore b/axum/openai/.gitignore deleted file mode 100644 index cfcbc42b..00000000 --- a/axum/openai/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/target -.shuttle* -Secrets*.toml diff --git a/axum/postgres/.gitignore b/axum/postgres/.gitignore deleted file mode 100644 index a1a5734e..00000000 --- a/axum/postgres/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target -Secrets*.toml diff --git a/axum/todo-list/Cargo.toml b/axum/todo-list/Cargo.toml new file mode 100644 index 00000000..b3b4a49c --- /dev/null +++ b/axum/todo-list/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "todo-list" +version = "0.1.0" +edition = "2024" + +[dependencies] +axum = "0.8" +serde = { version = "1", features = ["derive"] } +shuttle-axum = "0.56.0" +shuttle-runtime = "0.56.0" +shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } +sqlx = "0.8" +tokio = "1" +tower-http = { version = "0.6", features = ["fs", "trace"] } +tracing = "0.1" diff --git a/axum/todo-list/README.md b/axum/todo-list/README.md new file mode 100644 index 00000000..12a88b88 --- /dev/null +++ b/axum/todo-list/README.md @@ -0,0 +1,28 @@ +# Todo list app on Shuttle with Axum and Postgres + +This template combines a Postgres database with a file server to make a simple Todo list app. + +## How to use + +Use `shuttle run` to try it locally, and access the UI on . + +Then you can use `shuttle deploy` to deploy it. + +## Example command line usage (local run) + +```bash +curl -X POST -H 'content-type: application/json' localhost:8000/api/todos --data '{"content":"My todo"}' +# {"id":1,"content":"My todo"} + +curl localhost:8000/api/todos +# [{"id":1,"content":"My todo"}] + +curl -X PUT -H 'content-type: application/json' localhost:8000/api/todos/1 --data '{"content":"Updated text"}' +# {"id":1,"content":"Updated text"} + +curl -X DELETE localhost:8000/api/todos/1 +# {"id":1,"content":"Updated text"} + +curl localhost:8000/api/todos +# [] +``` diff --git a/axum/todo-list/Shuttle.toml b/axum/todo-list/Shuttle.toml new file mode 100644 index 00000000..a783bac5 --- /dev/null +++ b/axum/todo-list/Shuttle.toml @@ -0,0 +1,4 @@ +[build] +assets = [ + "assets", +] diff --git a/axum/todo-list/assets/index.html b/axum/todo-list/assets/index.html new file mode 100644 index 00000000..5ede6a58 --- /dev/null +++ b/axum/todo-list/assets/index.html @@ -0,0 +1,26 @@ + + + + Todo list app on Shuttle + + + + +
+

Todo list app on Shuttle

+

This is an example of a CRUD API combined with a static file server with Axum, backed by a Postgres database.

+
+ + +
+
+
+

What to do next?

+

To learn more about Shuttle features, check out the docs!

+

+ This template emits tracing events on each request. + Use the Telemetry feature on Shuttle to export and view them on third-party platforms. +

+
+ + diff --git a/axum/todo-list/assets/script.js b/axum/todo-list/assets/script.js new file mode 100644 index 00000000..b6e9c56e --- /dev/null +++ b/axum/todo-list/assets/script.js @@ -0,0 +1,106 @@ +document.addEventListener('DOMContentLoaded', () => { + const todoForm = document.getElementById('todo-form'); + const todoInput = document.getElementById('todo-input'); + const todoList = document.getElementById('todo-list'); + const API_URL = '/api/todos'; + + // Fetch and display todos + async function fetchTodos() { + try { + const response = await fetch(API_URL); + if (!response.ok) throw new Error('Failed to fetch todos'); + const todos = await response.json(); + todoList.innerHTML = ''; + todos.forEach(todo => renderTodo(todo)); + } catch (error) { + console.error('Error fetching todos:', error); + alert('Error fetching todos'); + } + } + + // Render a single todo item + function renderTodo(todo) { + const div = document.createElement('div'); + + const contentSpan = document.createElement('span'); + contentSpan.textContent = todo.content; + + const buttonDiv = document.createElement('div'); + + const editButton = document.createElement('button'); + editButton.textContent = 'Edit'; + editButton.addEventListener('click', () => editTodo(todo.id, todo.content)); + + const deleteButton = document.createElement('button'); + deleteButton.textContent = 'Delete'; + deleteButton.addEventListener('click', () => deleteTodo(todo.id)); + + buttonDiv.appendChild(editButton); + buttonDiv.appendChild(deleteButton); + + div.appendChild(contentSpan); + div.appendChild(buttonDiv); + + todoList.appendChild(div); + } + + // Add new todo + todoForm.addEventListener('submit', async (e) => { + e.preventDefault(); + const content = todoInput.value.trim(); + if (!content) return; + + try { + const response = await fetch(API_URL, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ content }) + }); + if (!response.ok) throw new Error('Failed to add todo'); + const newTodo = await response.json(); + renderTodo(newTodo); + todoInput.value = ''; + } catch (error) { + console.error('Error adding todo:', error); + alert('Error adding todo'); + } + }); + + // Edit todo + window.editTodo = async (id, currentContent) => { + const newContent = prompt('Edit todo:', currentContent); + if (newContent === null || newContent.trim() === '') return; + + try { + const response = await fetch(`${API_URL}/${id}`, { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ content: newContent.trim() }) + }); + if (!response.ok) throw new Error('Failed to update todo'); + fetchTodos(); + } catch (error) { + console.error('Error updating todo:', error); + alert('Error updating todo'); + } + }; + + // Delete todo + window.deleteTodo = async (id) => { + if (!confirm('Are you sure you want to delete this todo?')) return; + + try { + const response = await fetch(`${API_URL}/${id}`, { + method: 'DELETE' + }); + if (!response.ok) throw new Error('Failed to delete todo'); + fetchTodos(); + } catch (error) { + console.error('Error deleting todo:', error); + alert('Error deleting todo'); + } + }; + + // Initial fetch + fetchTodos(); +}); diff --git a/axum/todo-list/assets/style.css b/axum/todo-list/assets/style.css new file mode 100644 index 00000000..3b087fad --- /dev/null +++ b/axum/todo-list/assets/style.css @@ -0,0 +1,67 @@ +body { + background-color: #33495e; + color: #ffffff; + font-family: Arial, Helvetica, sans-serif; +} + +main { + text-align: center; + max-width: 600px; + margin: 20px auto; + padding: 20px; +} + +a { + color: orange; + text-decoration: none; +} + +#todo-form { + display: flex; + gap: 10px; + margin: 20px 0; +} + +#todo-input { + flex: 1; + padding: 10px; + font-size: 14px; + border: none; + border-radius: 4px; +} + +button { + padding: 10px 18px; + background-color: orange; + border: none; + border-radius: 4px; + color: #33495e; + cursor: pointer; + font-size: 16px; +} + +button:hover { + background-color: #ffbf00; +} + +#todo-list { + min-height: 100px; + margin-bottom: 20px; +} + +#todo-list > div { + display: flex; + justify-content: space-between; + align-items: center; + background-color: #445566; + margin: 5px 0; +} + +#todo-list > div > span { + padding: 10px; +} + +#todo-list > div > div { + display: flex; + gap: 4px; +} diff --git a/axum/todo-list/migrations/0001_init.sql b/axum/todo-list/migrations/0001_init.sql new file mode 100644 index 00000000..99bb6539 --- /dev/null +++ b/axum/todo-list/migrations/0001_init.sql @@ -0,0 +1,4 @@ +CREATE TABLE IF NOT EXISTS todos ( + id SERIAL PRIMARY KEY, + content TEXT NOT NULL +); diff --git a/axum/todo-list/src/main.rs b/axum/todo-list/src/main.rs new file mode 100644 index 00000000..06544d5e --- /dev/null +++ b/axum/todo-list/src/main.rs @@ -0,0 +1,108 @@ +use axum::{ + Json, Router, + extract::{Path, State}, + http::StatusCode, + routing::{delete, get}, +}; +use serde::{Deserialize, Serialize}; +use sqlx::{FromRow, PgPool}; +use tower_http::{ + services::ServeDir, + trace::{DefaultMakeSpan, DefaultOnRequest, DefaultOnResponse, TraceLayer}, +}; +use tracing::Level; + +#[derive(Deserialize)] +struct TodoRequest { + pub content: String, +} + +#[derive(Serialize, FromRow)] +struct TodoResponse { + pub id: i32, + pub content: String, +} + +async fn get_todos( + State(state): State, +) -> Result>, (StatusCode, String)> { + let todos = sqlx::query_as("SELECT id, content FROM todos") + .fetch_all(&state.pool) + .await + .map_err(|e| (StatusCode::BAD_REQUEST, e.to_string()))?; + + Ok(Json(todos)) +} + +async fn post_todos( + State(state): State, + Json(req): Json, +) -> Result, (StatusCode, String)> { + let todo = sqlx::query_as("INSERT INTO todos (content) VALUES ($1) RETURNING id, content") + .bind(&req.content) + .fetch_one(&state.pool) + .await + .map_err(|e| (StatusCode::BAD_REQUEST, dbg!(e).to_string()))?; + + Ok(Json(todo)) +} + +async fn delete_todo( + State(state): State, + Path(id): Path, +) -> Result, (StatusCode, String)> { + let todo = sqlx::query_as("DELETE FROM todos WHERE id = $1 RETURNING id, content") + .bind(id) + .fetch_one(&state.pool) + .await + .map_err(|e| (StatusCode::BAD_REQUEST, e.to_string()))?; + + Ok(Json(todo)) +} + +async fn put_todo( + State(state): State, + Path(id): Path, + Json(req): Json, +) -> Result, (StatusCode, String)> { + let todo = sqlx::query_as("UPDATE todos SET content = $1 WHERE id = $2 RETURNING id, content") + .bind(&req.content) + .bind(id) + .fetch_one(&state.pool) + .await + .map_err(|e| (StatusCode::BAD_REQUEST, e.to_string()))?; + + Ok(Json(todo)) +} + +#[derive(Clone)] +struct AppState { + pool: PgPool, +} + +#[shuttle_runtime::main] +async fn main(#[shuttle_shared_db::Postgres] pool: PgPool) -> shuttle_axum::ShuttleAxum { + sqlx::migrate!() + .run(&pool) + .await + .expect("Failed to run migrations"); + + let state = AppState { pool }; + let router = Router::new() + // API routes + .route("/api/todos", get(get_todos).post(post_todos)) + .route("/api/todos/{id}", delete(delete_todo).put(put_todo)) + // Serve files from 'assets' directory when no API route matches the request. + // ServeDir falls back to serve index.html when requesting a directory. + .fallback_service(ServeDir::new("assets")) + // Emit INFO level tracing events on each request + .layer( + TraceLayer::new_for_http() + .make_span_with(DefaultMakeSpan::new().level(Level::INFO)) + .on_request(DefaultOnRequest::new().level(Level::INFO)) + .on_response(DefaultOnResponse::new().level(Level::INFO)), + ) + .with_state(state); + + Ok(router.into()) +} diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 77696cb0..96294aa8 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -4,13 +4,13 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = { version = "0.7.3", features = ["ws"] } -chrono = { version = "0.4.26", features = ["serde"] } +axum = { version = "0.8", features = ["ws"] } +chrono = { version = "0.4", features = ["serde"] } futures = "0.3.28" -reqwest = "0.11.23" -serde = { version = "1.0.163", features = ["derive"] } -serde_json = "1.0.96" -shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +reqwest = "0.12" +serde = { version = "1", features = ["derive"] } +serde_json = "1" +shuttle-axum = "0.56.0" shuttle-runtime = "0.56.0" -tokio = "1.28.2" -tower-http = { version = "0.5.0", features = ["fs"] } +tokio = "1" +tower-http = { version = "0.6", features = ["fs"] } diff --git a/axum/websocket/src/main.rs b/axum/websocket/src/main.rs index 654847fc..dbf2c00d 100644 --- a/axum/websocket/src/main.rs +++ b/axum/websocket/src/main.rs @@ -37,7 +37,7 @@ struct Response { #[shuttle_runtime::main] async fn main() -> ShuttleAxum { - let (tx, rx) = watch::channel(Message::Text("{}".to_string())); + let (tx, rx) = watch::channel(Message::Text("{}".into())); let state = Arc::new(Mutex::new(State { clients_count: 0, @@ -61,7 +61,7 @@ async fn main() -> ShuttleAxum { }; let msg = serde_json::to_string(&response).unwrap(); - if tx.send(Message::Text(msg)).is_err() { + if tx.send(Message::Text(msg.into())).is_err() { break; } @@ -71,7 +71,7 @@ async fn main() -> ShuttleAxum { let router = Router::new() .route("/websocket", get(websocket_handler)) - .nest_service("/", ServeDir::new("static")) + .fallback_service(ServeDir::new("static")) .layer(Extension(state)); Ok(router.into()) diff --git a/bevy/hello-world/.gitignore b/bevy/hello-world/.gitignore index f5ed2c1c..3a095d55 100644 --- a/bevy/hello-world/.gitignore +++ b/bevy/hello-world/.gitignore @@ -1,5 +1,5 @@ target/ Secrets*.toml -dist/* -!dist/index.html -!dist/Roboto-Black.ttf +assets/* +!assets/index.html +!assets/Roboto-Black.ttf diff --git a/bevy/hello-world/Makefile b/bevy/hello-world/Makefile index 337f1d79..bf0ad49f 100644 --- a/bevy/hello-world/Makefile +++ b/bevy/hello-world/Makefile @@ -1,5 +1,5 @@ build: cargo build --package game --release --target wasm32-unknown-unknown && \ - wasm-bindgen --out-dir dist --target web target/wasm32-unknown-unknown/release/game.wasm + wasm-bindgen --out-dir assets --target web target/wasm32-unknown-unknown/release/game.wasm up: build shuttle run diff --git a/bevy/hello-world/README.md b/bevy/hello-world/README.md index 634df8b5..97ad1808 100644 --- a/bevy/hello-world/README.md +++ b/bevy/hello-world/README.md @@ -3,6 +3,7 @@ Example of how you can compile Bevy to WASM and run it on Shuttle. ## Instructions Make sure you have `wasm-bindgen-cli` and the rustup `wasm32-unknown-unknown` compilation target added. If you don't, you can get them by running the following: + ```bash cargo install wasm-bindgen-cli rustup target add wasm32-unknown-unknown diff --git a/bevy/hello-world/Shuttle.toml b/bevy/hello-world/Shuttle.toml index 7edd1b8f..1ed0b8fb 100644 --- a/bevy/hello-world/Shuttle.toml +++ b/bevy/hello-world/Shuttle.toml @@ -1,9 +1,9 @@ [deploy] include = [ - "dist/*", + "assets/*", ] [build] assets = [ - "dist/*", + "assets/*", ] diff --git a/bevy/hello-world/dist/Roboto-Black.ttf b/bevy/hello-world/assets/Roboto-Black.ttf similarity index 100% rename from bevy/hello-world/dist/Roboto-Black.ttf rename to bevy/hello-world/assets/Roboto-Black.ttf diff --git a/bevy/hello-world/dist/index.html b/bevy/hello-world/assets/index.html similarity index 100% rename from bevy/hello-world/dist/index.html rename to bevy/hello-world/assets/index.html diff --git a/bevy/hello-world/server/src/main.rs b/bevy/hello-world/server/src/main.rs index 853fc147..0c27e63b 100644 --- a/bevy/hello-world/server/src/main.rs +++ b/bevy/hello-world/server/src/main.rs @@ -5,7 +5,7 @@ use tower_http::services::{ServeDir, ServeFile}; async fn main() -> shuttle_axum::ShuttleAxum { let router = Router::new().nest_service( "/", - ServeDir::new("dist").not_found_service(ServeFile::new("dist/index.html")), + ServeDir::new("assets").not_found_service(ServeFile::new("assets/index.html")), ); Ok(router.into()) } diff --git a/custom-resource/pdo/.gitignore b/custom-resource/pdo/.gitignore deleted file mode 100644 index a1a5734e..00000000 --- a/custom-resource/pdo/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target -Secrets*.toml diff --git a/rocket/opendal-memory/src/main.rs b/rocket/opendal-memory/src/main.rs index 92fcb01c..2859a878 100644 --- a/rocket/opendal-memory/src/main.rs +++ b/rocket/opendal-memory/src/main.rs @@ -24,7 +24,7 @@ async fn add( .write(&path, bs) .await .map_err(|e| BadRequest(e.to_string()))?; - Ok(format!("path {path} written {}B data", length)) + Ok(format!("path {path} written {length}B data")) } #[get("/")] diff --git a/rocket/static-files/.gitignore b/rocket/static-files/.gitignore deleted file mode 100644 index a1a5734e..00000000 --- a/rocket/static-files/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target -Secrets*.toml diff --git a/salvo/image-rescaler/src/main.rs b/salvo/image-rescaler/src/main.rs index 60c69ba5..3949b25a 100644 --- a/salvo/image-rescaler/src/main.rs +++ b/salvo/image-rescaler/src/main.rs @@ -7,6 +7,11 @@ async fn get_image(req: &mut Request, res: &mut Response) { let width = req.param::("width").unwrap(); let height = req.param::("height").unwrap(); + if width > 4000 || height > 4000 { + res.stuff(StatusCode::BAD_REQUEST, "Try a smaller image size"); + return; + } + let img = image::load_from_memory_with_format(IMAGE, image::ImageFormat::Png).unwrap(); let img = img.resize_exact(width, height, image::imageops::FilterType::Triangle); let mut buffer = std::io::BufWriter::new(std::io::Cursor::new(Vec::new())); diff --git a/serenity/postgres/src/db.rs b/serenity/postgres/src/db.rs index 29137b43..69fb855a 100644 --- a/serenity/postgres/src/db.rs +++ b/serenity/postgres/src/db.rs @@ -14,7 +14,7 @@ pub(crate) async fn add(pool: &PgPool, note: &str, user_id: i64) -> Result { - format!("Err: {}", err) + format!("Err: {err}") } } } diff --git a/serenity/weather-forecast/src/weather.rs b/serenity/weather-forecast/src/weather.rs index 21269f52..1af82444 100644 --- a/serenity/weather-forecast/src/weather.rs +++ b/serenity/weather-forecast/src/weather.rs @@ -57,7 +57,7 @@ pub async fn get_forecast( const DAY_REQUEST: &str = "http://dataservice.accuweather.com/forecasts/v1/daily/1day/"; // The URL to call combined with our API_KEY and the place (via the q search parameter) - let url = format!("{}?apikey={}&q={}", LOCATION_REQUEST, api_key, place); + let url = format!("{LOCATION_REQUEST}?apikey={api_key}&q={place}"); // Make the request we will call let request = client.get(url).build().unwrap(); // Execute the request and await a JSON result that will be converted to a diff --git a/shuttle-cron/.gitignore b/shuttle-cron/.gitignore deleted file mode 100644 index e8541fe9..00000000 --- a/shuttle-cron/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/target -.shuttle-storage -Secrets*.toml diff --git a/templates.toml b/templates.toml index 59141e6d..b2ddf6d7 100644 --- a/templates.toml +++ b/templates.toml @@ -244,6 +244,13 @@ path = "axum/static-files" use_cases = ["Web app"] tags = ["axum"] +[templates.axum-todo-list] +title = "Todo list" +description = "CRUD API, Postgres database, and static file server combined into a classic Todo list app" +path = "axum/todo-list" +use_cases = ["Web app", "Storage"] +tags = ["axum", "postgres", "database"] + [templates.axum-turso] title = "Turso" description = "Connect to a Turso DB with shuttle-turso" From 31540236842f5149f5ef9e0a0bb8fb147b84a3a3 Mon Sep 17 00:00:00 2001 From: dcodes <101001810+dcodesdev@users.noreply.github.com> Date: Fri, 18 Jul 2025 16:03:32 +0300 Subject: [PATCH 218/239] New Template: SSE MCP Server (#223) --- mcp/mcp-sse/Cargo.toml | 14 ++++++ mcp/mcp-sse/README.md | 81 ++++++++++++++++++++++++++++++ mcp/mcp-sse/src/main.rs | 72 +++++++++++++++++++++++++++ mcp/mcp-sse/src/mcp_service.rs | 90 ++++++++++++++++++++++++++++++++++ templates.toml | 7 +++ 5 files changed, 264 insertions(+) create mode 100644 mcp/mcp-sse/Cargo.toml create mode 100644 mcp/mcp-sse/README.md create mode 100644 mcp/mcp-sse/src/main.rs create mode 100644 mcp/mcp-sse/src/mcp_service.rs diff --git a/mcp/mcp-sse/Cargo.toml b/mcp/mcp-sse/Cargo.toml new file mode 100644 index 00000000..955f44ed --- /dev/null +++ b/mcp/mcp-sse/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "mcp-sse" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +shuttle-runtime = "0.56.0" +tokio = { version = "1", features = ["macros", "rt-multi-thread", "signal"] } +rmcp = { version = "0.3", features = ["server", "transport-sse-server"] } +axum = "0.8" +anyhow = "1.0" +tracing = "0.1" +tokio-util = "0.7" diff --git a/mcp/mcp-sse/README.md b/mcp/mcp-sse/README.md new file mode 100644 index 00000000..b9ee06c3 --- /dev/null +++ b/mcp/mcp-sse/README.md @@ -0,0 +1,81 @@ +# MCP SSE Server Template + +A [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server template with Server-Sent Events transport, deployed on **Shuttle**. MCP servers enable AI agents to securely connect to external data sources and tools, providing real-time access to databases, APIs, and live data streams. + +## Features + +- MCP server with SSE transport +- Counter service with `increment`, `decrement`, `get_value`, and `reset` operations +- Ready-to-deploy on [Shuttle](https://www.shuttle.dev) + +## Use Cases + +This MCP SSE server template is ideal for: + +- **AI Agent Integration**: Connect AI assistants like Claude, GPT, or local models to real-time data streams +- **Live Data Monitoring**: Stream counter values, metrics, or status updates to AI agents for real-time decision making +- **Interactive Applications**: Build chatbots or AI assistants that can interact with stateful services +- **Prototyping MCP Servers**: Use as a starting point for custom MCP servers with Server-Sent Events transport + +## Quick Start + +### Local Development + +```bash +shuttle run +``` + +### Deploy to Shuttle + +```bash +shuttle deploy +``` + +## Endpoints + +- `http://localhost:8000/sse` - SSE endpoint for MCP client connections +- `http://localhost:8000/message` - Message endpoint + +## Accessing the Deployment + +After deployment, your MCP server will be available at: + +- `https://your-project-name.shuttle.app/sse` - SSE endpoint for MCP client connections +- `https://your-project-name.shuttle.app/message` - Message endpoint + +Replace `your-project-name` with the actual name of your deployed project (e.g., `mcp-z8dz.shuttle.app`). + +## Cursor Integration + +To use this MCP server with Cursor, add the following to your `mcp.json` configuration file: + +```json +{ + "mcpServers": { + "mcp-sse": { + "url": "https://your-project-name.shuttle.app/sse" + } + } +} +``` + +Or if connecting to your local development server: + +```json +{ + "mcpServers": { + "mcp-sse-local": { + "url": "http://localhost:8000/sse" + } + } +} +``` + +Replace `your-project-name` with your actual deployed project name. + +## Tools + +- `increment` - Increment counter by 1 +- `decrement` - Decrement counter by 1 +- `get_value` - Get current counter value +- `reset` - Reset counter to zero diff --git a/mcp/mcp-sse/src/main.rs b/mcp/mcp-sse/src/main.rs new file mode 100644 index 00000000..d826a7b3 --- /dev/null +++ b/mcp/mcp-sse/src/main.rs @@ -0,0 +1,72 @@ +use rmcp::transport::sse_server::{SseServer, SseServerConfig}; +use std::net::SocketAddr; +use tokio_util::sync::CancellationToken; + +mod mcp_service; +use mcp_service::Counter; + +#[shuttle_runtime::main] +async fn shuttle_main() -> Result { + Ok(McpSseService {}) +} + +struct McpSseService {} + +#[shuttle_runtime::async_trait] +impl shuttle_runtime::Service for McpSseService { + async fn bind(self, addr: SocketAddr) -> Result<(), shuttle_runtime::Error> { + tracing::info!("Starting SSE MCP Server on {}", addr); + + // Create SSE server configuration + let config = SseServerConfig { + bind: addr, + sse_path: "/sse".to_string(), + post_path: "/message".to_string(), + ct: CancellationToken::new(), + sse_keep_alive: Some(std::time::Duration::from_secs(30)), + }; + + // Create SSE server + let (sse_server, router) = SseServer::new(config); + + // Create TCP listener + let listener = tokio::net::TcpListener::bind(addr).await.map_err(|e| { + shuttle_runtime::Error::Custom(anyhow::anyhow!("Failed to bind: {}", e)) + })?; + + // Setup graceful shutdown + let ct = sse_server.config.ct.child_token(); + let server = axum::serve(listener, router).with_graceful_shutdown(async move { + ct.cancelled().await; + tracing::info!("SSE server shutting down gracefully"); + }); + + // Start the HTTP server in a background task + tokio::spawn(async move { + if let Err(e) = server.await { + tracing::error!("SSE server error: {}", e); + } + }); + + // Register the Counter service with the SSE server + let ct = sse_server.with_service(Counter::new); + + tracing::info!("SSE MCP Server started successfully"); + tracing::info!("SSE endpoint: http://{}/sse", addr); + tracing::info!("Message endpoint: http://{}/message", addr); + + // Wait for shutdown signal + tokio::select! { + _ = tokio::signal::ctrl_c() => { + tracing::info!("Received shutdown signal"); + } + _ = ct.cancelled() => { + tracing::info!("Service cancelled"); + } + } + + ct.cancel(); + tracing::info!("SSE MCP Server shut down"); + Ok(()) + } +} diff --git a/mcp/mcp-sse/src/mcp_service.rs b/mcp/mcp-sse/src/mcp_service.rs new file mode 100644 index 00000000..5ed8c564 --- /dev/null +++ b/mcp/mcp-sse/src/mcp_service.rs @@ -0,0 +1,90 @@ +use rmcp::{ + handler::server::router::tool::ToolRouter, model::ErrorData as McpError, model::*, + service::RequestContext, tool, tool_handler, tool_router, RoleServer, ServerHandler, +}; +use std::future::Future; +use std::sync::Arc; +use tokio::sync::Mutex; + +#[derive(Clone)] +pub struct Counter { + counter: Arc>, + tool_router: ToolRouter, +} + +#[tool_router] +impl Counter { + pub fn new() -> Self { + Self { + counter: Arc::new(Mutex::new(0)), + tool_router: Self::tool_router(), + } + } + + #[tool(description = "Increment the counter by 1")] + async fn increment(&self) -> Result { + let mut counter = self.counter.lock().await; + *counter += 1; + Ok(CallToolResult::success(vec![Content::text(format!( + "Counter incremented to: {}", + *counter + ))])) + } + + #[tool(description = "Decrement the counter by 1")] + async fn decrement(&self) -> Result { + let mut counter = self.counter.lock().await; + *counter -= 1; + Ok(CallToolResult::success(vec![Content::text(format!( + "Counter decremented to: {}", + *counter + ))])) + } + + #[tool(description = "Get the current counter value")] + async fn get_value(&self) -> Result { + let counter = self.counter.lock().await; + Ok(CallToolResult::success(vec![Content::text(format!( + "Current counter value: {}", + *counter + ))])) + } + + #[tool(description = "Reset the counter to zero")] + async fn reset(&self) -> Result { + let mut counter = self.counter.lock().await; + *counter = 0; + Ok(CallToolResult::success(vec![Content::text( + "Counter reset to: 0".to_string(), + )])) + } +} + +#[tool_handler] +impl ServerHandler for Counter { + fn get_info(&self) -> ServerInfo { + ServerInfo { + protocol_version: ProtocolVersion::V_2024_11_05, + capabilities: ServerCapabilities::builder() + .enable_prompts() + .enable_resources() + .enable_tools() + .build(), + server_info: Implementation::from_build_env(), + instructions: Some("This server provides a counter tool that can increment and decrement values. The counter starts at 0 and can be modified using the 'increment', 'decrement', and 'reset' tools. Use 'get_value' to check the current count.".to_string()), + } + } + + async fn initialize( + &self, + _request: InitializeRequestParam, + context: RequestContext, + ) -> Result { + if let Some(http_request_part) = context.extensions.get::() { + let initialize_headers = &http_request_part.headers; + let initialize_uri = &http_request_part.uri; + tracing::info!(?initialize_headers, %initialize_uri, "initialize from http server"); + } + Ok(self.get_info()) + } +} diff --git a/templates.toml b/templates.toml index b2ddf6d7..1256b3a1 100644 --- a/templates.toml +++ b/templates.toml @@ -363,6 +363,13 @@ path = "tracing/custom-tracing-subscriber" use_cases = ["Web app", "Logging"] tags = ["actix-web", "tracing"] +[templates.mcp-sse] +title = "SSE MCP Server" +description = "Model Context Protocol server with Server-Sent Events transport" +path = "mcp/mcp-sse" +use_cases = ["Web app", "MCP"] +tags = ["axum", "mcp", "sse"] + ## EXAMPLES ## From 1ffca034667f047c8d7f696eb054e9ca2562a8f9 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Sat, 19 Jul 2025 03:49:46 +0200 Subject: [PATCH 219/239] chore: update loco for 0.56 (#222) --- loco/hello-world/.cargo/config.toml | 2 +- loco/hello-world/Cargo.toml | 8 ++------ loco/hello-world/src/bin/shuttle.rs | 10 +++------- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/loco/hello-world/.cargo/config.toml b/loco/hello-world/.cargo/config.toml index 56012377..80e0ddb1 100644 --- a/loco/hello-world/.cargo/config.toml +++ b/loco/hello-world/.cargo/config.toml @@ -1,5 +1,5 @@ [alias] -loco = "run --bin hello_world-cli --" +loco = "run --" loco-tool = "run --" playground = "run --example playground" \ No newline at end of file diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index 2d4ecf2c..f69875df 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -10,7 +10,7 @@ default-run = "hello_world-cli" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [workspace.dependencies] -loco-rs = { version = "0.14.0", default-features = false } +loco-rs = { version = "0.16.0", default-features = false } [dependencies] shuttle-axum = "0.56.0" @@ -33,12 +33,8 @@ name = "hello_world-cli" path = "src/bin/main.rs" required-features = [] -[[bin]] -name = "hello_world" -path = "src/bin/shuttle.rs" - [dev-dependencies] loco-rs = { workspace = true, features = ["testing"] } serial_test = { version = "3.1.1" } rstest = { version = "0.21.0" } -insta = { version = "1.34.0", features = ["redactions", "yaml", "filters"] } \ No newline at end of file +insta = { version = "1.34.0", features = ["redactions", "yaml", "filters"] } diff --git a/loco/hello-world/src/bin/shuttle.rs b/loco/hello-world/src/bin/shuttle.rs index 42987fe7..0da090b9 100644 --- a/loco/hello-world/src/bin/shuttle.rs +++ b/loco/hello-world/src/bin/shuttle.rs @@ -2,23 +2,19 @@ use loco_rs::boot::{create_app, StartMode}; use loco_rs::environment::Environment; use hello_world::app::App; -use shuttle_runtime::DeploymentMetadata; - #[shuttle_runtime::main] async fn main( - - #[shuttle_runtime::Metadata] meta: DeploymentMetadata, + #[shuttle_runtime::Metadata] meta: shuttle_runtime::DeploymentMetadata, ) -> shuttle_axum::ShuttleAxum { - let environment = match meta.env { shuttle_runtime::Environment::Local => Environment::Development, shuttle_runtime::Environment::Deployment => Environment::Production, }; - let config = environment + let config = environment .load() .expect("Failed to load configuration from the environment"); - + let boot_result = create_app::(StartMode::ServerOnly, &environment, config) .await .unwrap(); From 6d7b9f2883e028a548d84e4aa9a2fdb69b27b6ec Mon Sep 17 00:00:00 2001 From: dcodes <101001810+dcodesdev@users.noreply.github.com> Date: Wed, 13 Aug 2025 16:58:29 +0300 Subject: [PATCH 220/239] New Example: SSE MCP Server with OAuth (#224) --- ...f546123b0be5f51694966887d645d3fb70324.json | 35 ++ ...7a938f0ff5dda847677b167860702f25ccf4c.json | 36 ++ ...956495a6dbd6f74daf0e8faf75e09cf8db68f.json | 22 + ...a8351507c0bfea0e1036d1e23354ec8cd8a33.json | 28 ++ ...c0f2083d1f036f4734d51eefe2c885fb3f224.json | 22 + ...d9a694ce73c234cc45cbe983c0af4201209e7.json | 18 + ...de833c9cadf575841d87a6fa5aa4b2c9980c8.json | 16 + ...6b914dd7f9364069e346794425a71ac66c93f.json | 22 + ...ffbbc3e9d9c2e5f93beb809186bfdb56e624c.json | 14 + ...4c59409cc0c5a48c6d142def945be3b9cea42.json | 18 + ...bb5dc4fe8f78281494d281dc432c94c4ae289.json | 40 ++ ...7e3590cbfee088bc0f26733aa1cabf6280100.json | 35 ++ ...d80ecf438fc53fe2a46ed771117b6aa901af4.json | 15 + ...1f29b3e9fe6c2234cbbdf89d3b537c4b0744c.json | 14 + mcp/mcp-sse-oauth/Cargo.toml | 36 ++ mcp/mcp-sse-oauth/README.md | 76 +++ ...0250730152154_create_mcp_clients_table.sql | 9 + ...55304_create_authorization_codes_table.sql | 10 + ...0730160425_create_refresh_tokens_table.sql | 8 + .../20250801130039_create_todos_table.sql | 7 + mcp/mcp-sse-oauth/src/auth.rs | 27 + mcp/mcp-sse-oauth/src/auth/authorize.rs | 170 +++++++ mcp/mcp-sse-oauth/src/auth/metadata.rs | 35 ++ mcp/mcp-sse-oauth/src/auth/registration.rs | 104 ++++ mcp/mcp-sse-oauth/src/auth/token.rs | 473 ++++++++++++++++++ mcp/mcp-sse-oauth/src/init.rs | 98 ++++ mcp/mcp-sse-oauth/src/main.rs | 31 ++ mcp/mcp-sse-oauth/src/middleware.rs | 97 ++++ mcp/mcp-sse-oauth/src/todo_mcp.rs | 1 + mcp/mcp-sse-oauth/src/todos/db.rs | 190 +++++++ mcp/mcp-sse-oauth/src/todos/mcp_service.rs | 269 ++++++++++ mcp/mcp-sse-oauth/src/todos/mod.rs | 2 + mcp/mcp-sse-oauth/templates/authorize.html | 106 ++++ templates.toml | 7 + 34 files changed, 2091 insertions(+) create mode 100644 mcp/mcp-sse-oauth/.sqlx/query-217bfa16a13fd5a15e5a4da9a84f546123b0be5f51694966887d645d3fb70324.json create mode 100644 mcp/mcp-sse-oauth/.sqlx/query-42b54df29e520a6ec37e95bce207a938f0ff5dda847677b167860702f25ccf4c.json create mode 100644 mcp/mcp-sse-oauth/.sqlx/query-536e5fcd7993bafbe9605780379956495a6dbd6f74daf0e8faf75e09cf8db68f.json create mode 100644 mcp/mcp-sse-oauth/.sqlx/query-62e9b9c3e0f49213730716c3e2ca8351507c0bfea0e1036d1e23354ec8cd8a33.json create mode 100644 mcp/mcp-sse-oauth/.sqlx/query-9115ee9dc3ed927e07bda04ee58c0f2083d1f036f4734d51eefe2c885fb3f224.json create mode 100644 mcp/mcp-sse-oauth/.sqlx/query-a149861e30fa51aa8498bb7bde5d9a694ce73c234cc45cbe983c0af4201209e7.json create mode 100644 mcp/mcp-sse-oauth/.sqlx/query-a2fdfd8c403facf7d51c42f83cade833c9cadf575841d87a6fa5aa4b2c9980c8.json create mode 100644 mcp/mcp-sse-oauth/.sqlx/query-a88efa50d79be271b704dc7305e6b914dd7f9364069e346794425a71ac66c93f.json create mode 100644 mcp/mcp-sse-oauth/.sqlx/query-c064867a2f4cc1a2bf400c76c99ffbbc3e9d9c2e5f93beb809186bfdb56e624c.json create mode 100644 mcp/mcp-sse-oauth/.sqlx/query-c8e1649bf318624c8e179d3fd414c59409cc0c5a48c6d142def945be3b9cea42.json create mode 100644 mcp/mcp-sse-oauth/.sqlx/query-c9eab86ef4b150b366ce2906e99bb5dc4fe8f78281494d281dc432c94c4ae289.json create mode 100644 mcp/mcp-sse-oauth/.sqlx/query-cfd88c925fe09ded69567ecc2447e3590cbfee088bc0f26733aa1cabf6280100.json create mode 100644 mcp/mcp-sse-oauth/.sqlx/query-d98527716a2f666540c6d110477d80ecf438fc53fe2a46ed771117b6aa901af4.json create mode 100644 mcp/mcp-sse-oauth/.sqlx/query-e3aec0e000a2606a5732f3f3dfc1f29b3e9fe6c2234cbbdf89d3b537c4b0744c.json create mode 100644 mcp/mcp-sse-oauth/Cargo.toml create mode 100644 mcp/mcp-sse-oauth/README.md create mode 100644 mcp/mcp-sse-oauth/migrations/20250730152154_create_mcp_clients_table.sql create mode 100644 mcp/mcp-sse-oauth/migrations/20250730155304_create_authorization_codes_table.sql create mode 100644 mcp/mcp-sse-oauth/migrations/20250730160425_create_refresh_tokens_table.sql create mode 100644 mcp/mcp-sse-oauth/migrations/20250801130039_create_todos_table.sql create mode 100644 mcp/mcp-sse-oauth/src/auth.rs create mode 100644 mcp/mcp-sse-oauth/src/auth/authorize.rs create mode 100644 mcp/mcp-sse-oauth/src/auth/metadata.rs create mode 100644 mcp/mcp-sse-oauth/src/auth/registration.rs create mode 100644 mcp/mcp-sse-oauth/src/auth/token.rs create mode 100644 mcp/mcp-sse-oauth/src/init.rs create mode 100644 mcp/mcp-sse-oauth/src/main.rs create mode 100644 mcp/mcp-sse-oauth/src/middleware.rs create mode 100644 mcp/mcp-sse-oauth/src/todo_mcp.rs create mode 100644 mcp/mcp-sse-oauth/src/todos/db.rs create mode 100644 mcp/mcp-sse-oauth/src/todos/mcp_service.rs create mode 100644 mcp/mcp-sse-oauth/src/todos/mod.rs create mode 100644 mcp/mcp-sse-oauth/templates/authorize.html diff --git a/mcp/mcp-sse-oauth/.sqlx/query-217bfa16a13fd5a15e5a4da9a84f546123b0be5f51694966887d645d3fb70324.json b/mcp/mcp-sse-oauth/.sqlx/query-217bfa16a13fd5a15e5a4da9a84f546123b0be5f51694966887d645d3fb70324.json new file mode 100644 index 00000000..3eff02c8 --- /dev/null +++ b/mcp/mcp-sse-oauth/.sqlx/query-217bfa16a13fd5a15e5a4da9a84f546123b0be5f51694966887d645d3fb70324.json @@ -0,0 +1,35 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT id, title, completed\n FROM todos\n WHERE id = $1 AND client_id = $2\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "title", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "completed", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Text" + ] + }, + "nullable": [ + false, + false, + false + ] + }, + "hash": "217bfa16a13fd5a15e5a4da9a84f546123b0be5f51694966887d645d3fb70324" +} diff --git a/mcp/mcp-sse-oauth/.sqlx/query-42b54df29e520a6ec37e95bce207a938f0ff5dda847677b167860702f25ccf4c.json b/mcp/mcp-sse-oauth/.sqlx/query-42b54df29e520a6ec37e95bce207a938f0ff5dda847677b167860702f25ccf4c.json new file mode 100644 index 00000000..2fbe7196 --- /dev/null +++ b/mcp/mcp-sse-oauth/.sqlx/query-42b54df29e520a6ec37e95bce207a938f0ff5dda847677b167860702f25ccf4c.json @@ -0,0 +1,36 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO todos (title, completed, client_id)\n VALUES ($1, COALESCE($2, FALSE), $3)\n RETURNING id, title, completed\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "title", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "completed", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Varchar", + "Bool", + "Varchar" + ] + }, + "nullable": [ + false, + false, + false + ] + }, + "hash": "42b54df29e520a6ec37e95bce207a938f0ff5dda847677b167860702f25ccf4c" +} diff --git a/mcp/mcp-sse-oauth/.sqlx/query-536e5fcd7993bafbe9605780379956495a6dbd6f74daf0e8faf75e09cf8db68f.json b/mcp/mcp-sse-oauth/.sqlx/query-536e5fcd7993bafbe9605780379956495a6dbd6f74daf0e8faf75e09cf8db68f.json new file mode 100644 index 00000000..d2320cbc --- /dev/null +++ b/mcp/mcp-sse-oauth/.sqlx/query-536e5fcd7993bafbe9605780379956495a6dbd6f74daf0e8faf75e09cf8db68f.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT client_name FROM mcp_clients WHERE client_id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "client_name", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false + ] + }, + "hash": "536e5fcd7993bafbe9605780379956495a6dbd6f74daf0e8faf75e09cf8db68f" +} diff --git a/mcp/mcp-sse-oauth/.sqlx/query-62e9b9c3e0f49213730716c3e2ca8351507c0bfea0e1036d1e23354ec8cd8a33.json b/mcp/mcp-sse-oauth/.sqlx/query-62e9b9c3e0f49213730716c3e2ca8351507c0bfea0e1036d1e23354ec8cd8a33.json new file mode 100644 index 00000000..f5ed6e46 --- /dev/null +++ b/mcp/mcp-sse-oauth/.sqlx/query-62e9b9c3e0f49213730716c3e2ca8351507c0bfea0e1036d1e23354ec8cd8a33.json @@ -0,0 +1,28 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT client_id, expires_at\n FROM refresh_tokens \n WHERE token = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "client_id", + "type_info": "Varchar" + }, + { + "ordinal": 1, + "name": "expires_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false, + false + ] + }, + "hash": "62e9b9c3e0f49213730716c3e2ca8351507c0bfea0e1036d1e23354ec8cd8a33" +} diff --git a/mcp/mcp-sse-oauth/.sqlx/query-9115ee9dc3ed927e07bda04ee58c0f2083d1f036f4734d51eefe2c885fb3f224.json b/mcp/mcp-sse-oauth/.sqlx/query-9115ee9dc3ed927e07bda04ee58c0f2083d1f036f4734d51eefe2c885fb3f224.json new file mode 100644 index 00000000..ba3f6b9c --- /dev/null +++ b/mcp/mcp-sse-oauth/.sqlx/query-9115ee9dc3ed927e07bda04ee58c0f2083d1f036f4734d51eefe2c885fb3f224.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT client_id FROM mcp_clients WHERE client_id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "client_id", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false + ] + }, + "hash": "9115ee9dc3ed927e07bda04ee58c0f2083d1f036f4734d51eefe2c885fb3f224" +} diff --git a/mcp/mcp-sse-oauth/.sqlx/query-a149861e30fa51aa8498bb7bde5d9a694ce73c234cc45cbe983c0af4201209e7.json b/mcp/mcp-sse-oauth/.sqlx/query-a149861e30fa51aa8498bb7bde5d9a694ce73c234cc45cbe983c0af4201209e7.json new file mode 100644 index 00000000..2c0c62ad --- /dev/null +++ b/mcp/mcp-sse-oauth/.sqlx/query-a149861e30fa51aa8498bb7bde5d9a694ce73c234cc45cbe983c0af4201209e7.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO mcp_clients (client_id, client_secret, client_name, redirect_uris, client_secret_expires_at)\n VALUES ($1, $2, $3, $4, $5)\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Varchar", + "Varchar", + "Varchar", + "TextArray", + "Timestamptz" + ] + }, + "nullable": [] + }, + "hash": "a149861e30fa51aa8498bb7bde5d9a694ce73c234cc45cbe983c0af4201209e7" +} diff --git a/mcp/mcp-sse-oauth/.sqlx/query-a2fdfd8c403facf7d51c42f83cade833c9cadf575841d87a6fa5aa4b2c9980c8.json b/mcp/mcp-sse-oauth/.sqlx/query-a2fdfd8c403facf7d51c42f83cade833c9cadf575841d87a6fa5aa4b2c9980c8.json new file mode 100644 index 00000000..24f86e6e --- /dev/null +++ b/mcp/mcp-sse-oauth/.sqlx/query-a2fdfd8c403facf7d51c42f83cade833c9cadf575841d87a6fa5aa4b2c9980c8.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO refresh_tokens (token, client_id, expires_at)\n VALUES ($1, $2, $3)\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Varchar", + "Varchar", + "Timestamptz" + ] + }, + "nullable": [] + }, + "hash": "a2fdfd8c403facf7d51c42f83cade833c9cadf575841d87a6fa5aa4b2c9980c8" +} diff --git a/mcp/mcp-sse-oauth/.sqlx/query-a88efa50d79be271b704dc7305e6b914dd7f9364069e346794425a71ac66c93f.json b/mcp/mcp-sse-oauth/.sqlx/query-a88efa50d79be271b704dc7305e6b914dd7f9364069e346794425a71ac66c93f.json new file mode 100644 index 00000000..46261c55 --- /dev/null +++ b/mcp/mcp-sse-oauth/.sqlx/query-a88efa50d79be271b704dc7305e6b914dd7f9364069e346794425a71ac66c93f.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT client_secret FROM mcp_clients WHERE client_id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "client_secret", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false + ] + }, + "hash": "a88efa50d79be271b704dc7305e6b914dd7f9364069e346794425a71ac66c93f" +} diff --git a/mcp/mcp-sse-oauth/.sqlx/query-c064867a2f4cc1a2bf400c76c99ffbbc3e9d9c2e5f93beb809186bfdb56e624c.json b/mcp/mcp-sse-oauth/.sqlx/query-c064867a2f4cc1a2bf400c76c99ffbbc3e9d9c2e5f93beb809186bfdb56e624c.json new file mode 100644 index 00000000..998d0575 --- /dev/null +++ b/mcp/mcp-sse-oauth/.sqlx/query-c064867a2f4cc1a2bf400c76c99ffbbc3e9d9c2e5f93beb809186bfdb56e624c.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM authorization_codes WHERE code = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [] + }, + "hash": "c064867a2f4cc1a2bf400c76c99ffbbc3e9d9c2e5f93beb809186bfdb56e624c" +} diff --git a/mcp/mcp-sse-oauth/.sqlx/query-c8e1649bf318624c8e179d3fd414c59409cc0c5a48c6d142def945be3b9cea42.json b/mcp/mcp-sse-oauth/.sqlx/query-c8e1649bf318624c8e179d3fd414c59409cc0c5a48c6d142def945be3b9cea42.json new file mode 100644 index 00000000..77f9c29d --- /dev/null +++ b/mcp/mcp-sse-oauth/.sqlx/query-c8e1649bf318624c8e179d3fd414c59409cc0c5a48c6d142def945be3b9cea42.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO authorization_codes (code, client_id, redirect_uri, code_challenge, expires_at)\n VALUES ($1, $2, $3, $4, $5)\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Varchar", + "Varchar", + "Text", + "Varchar", + "Timestamptz" + ] + }, + "nullable": [] + }, + "hash": "c8e1649bf318624c8e179d3fd414c59409cc0c5a48c6d142def945be3b9cea42" +} diff --git a/mcp/mcp-sse-oauth/.sqlx/query-c9eab86ef4b150b366ce2906e99bb5dc4fe8f78281494d281dc432c94c4ae289.json b/mcp/mcp-sse-oauth/.sqlx/query-c9eab86ef4b150b366ce2906e99bb5dc4fe8f78281494d281dc432c94c4ae289.json new file mode 100644 index 00000000..da4747bd --- /dev/null +++ b/mcp/mcp-sse-oauth/.sqlx/query-c9eab86ef4b150b366ce2906e99bb5dc4fe8f78281494d281dc432c94c4ae289.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT client_id, redirect_uri, code_challenge, expires_at\n FROM authorization_codes \n WHERE code = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "client_id", + "type_info": "Varchar" + }, + { + "ordinal": 1, + "name": "redirect_uri", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "code_challenge", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "expires_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "c9eab86ef4b150b366ce2906e99bb5dc4fe8f78281494d281dc432c94c4ae289" +} diff --git a/mcp/mcp-sse-oauth/.sqlx/query-cfd88c925fe09ded69567ecc2447e3590cbfee088bc0f26733aa1cabf6280100.json b/mcp/mcp-sse-oauth/.sqlx/query-cfd88c925fe09ded69567ecc2447e3590cbfee088bc0f26733aa1cabf6280100.json new file mode 100644 index 00000000..40206a7f --- /dev/null +++ b/mcp/mcp-sse-oauth/.sqlx/query-cfd88c925fe09ded69567ecc2447e3590cbfee088bc0f26733aa1cabf6280100.json @@ -0,0 +1,35 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT id, title, completed\n FROM todos\n WHERE id = $1 AND client_id = $2\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "title", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "completed", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Text" + ] + }, + "nullable": [ + false, + false, + false + ] + }, + "hash": "cfd88c925fe09ded69567ecc2447e3590cbfee088bc0f26733aa1cabf6280100" +} diff --git a/mcp/mcp-sse-oauth/.sqlx/query-d98527716a2f666540c6d110477d80ecf438fc53fe2a46ed771117b6aa901af4.json b/mcp/mcp-sse-oauth/.sqlx/query-d98527716a2f666540c6d110477d80ecf438fc53fe2a46ed771117b6aa901af4.json new file mode 100644 index 00000000..c7eaed75 --- /dev/null +++ b/mcp/mcp-sse-oauth/.sqlx/query-d98527716a2f666540c6d110477d80ecf438fc53fe2a46ed771117b6aa901af4.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM todos WHERE id = $1 AND client_id = $2", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Text" + ] + }, + "nullable": [] + }, + "hash": "d98527716a2f666540c6d110477d80ecf438fc53fe2a46ed771117b6aa901af4" +} diff --git a/mcp/mcp-sse-oauth/.sqlx/query-e3aec0e000a2606a5732f3f3dfc1f29b3e9fe6c2234cbbdf89d3b537c4b0744c.json b/mcp/mcp-sse-oauth/.sqlx/query-e3aec0e000a2606a5732f3f3dfc1f29b3e9fe6c2234cbbdf89d3b537c4b0744c.json new file mode 100644 index 00000000..1df5ff8a --- /dev/null +++ b/mcp/mcp-sse-oauth/.sqlx/query-e3aec0e000a2606a5732f3f3dfc1f29b3e9fe6c2234cbbdf89d3b537c4b0744c.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM refresh_tokens WHERE token = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [] + }, + "hash": "e3aec0e000a2606a5732f3f3dfc1f29b3e9fe6c2234cbbdf89d3b537c4b0744c" +} diff --git a/mcp/mcp-sse-oauth/Cargo.toml b/mcp/mcp-sse-oauth/Cargo.toml new file mode 100644 index 00000000..c2a27dee --- /dev/null +++ b/mcp/mcp-sse-oauth/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "mcp-sse-oauth" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +schemars = { version = "1" } +shuttle-runtime = "0.56.0" +shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } +tokio = { version = "1", features = ["macros", "rt-multi-thread", "signal"] } +rmcp = { version = "0.5", features = [ + "server", + "transport-sse-server", + "auth", +] } +axum = "0.8" +anyhow = "1.0" +tracing = "0.1" +tokio-util = "0.7" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +tower-http = { version = "0.6.6", features = ["cors"] } +sqlx = { version = "0.8.2", features = [ + "runtime-tokio-rustls", + "postgres", + "chrono", + "uuid", +] } +uuid = { version = "1.17", features = ["v4", "serde"] } +rand = "0.9" +chrono = { version = "0.4", features = ["serde"] } +askama = "0.14" +jsonwebtoken = "9.3" +sha2 = "0.10" +base64 = "0.22" diff --git a/mcp/mcp-sse-oauth/README.md b/mcp/mcp-sse-oauth/README.md new file mode 100644 index 00000000..88165278 --- /dev/null +++ b/mcp/mcp-sse-oauth/README.md @@ -0,0 +1,76 @@ +# MCP SSE OAuth Server (Shuttle) + +A Model Context Protocol (MCP) server that provides secure todo management functionality over Server-Sent Events (SSE), protected by OAuth2 with PKCE (Proof Key for Code Exchange). The server includes a complete authentication system and todo management tools backed by PostgreSQL. Designed to run both locally and on Shuttle. + +## Features + +- **OAuth2 PKCE Authentication**: Secure authentication flow with PKCE support +- **Server-Sent Events (SSE)**: Real-time MCP communication over SSE transport +- **PostgreSQL Integration**: Persistent storage with automatic migrations +- **Production Ready**: Deployable on Shuttle with proper secrets management + +## Architecture + +The server consists of several key components: + +- **Authentication Layer**: OAuth2 server with PKCE support (`src/auth/`) +- **MCP Service**: Todo management tools over MCP protocol (`src/todos/mcp_service.rs`) +- **SSE Transport**: Real-time communication layer (`src/init.rs`) +- **Database Layer**: PostgreSQL with SQLx for data persistence (`src/todos/db.rs`) +- **Middleware**: Token validation and request authentication (`src/middleware.rs`) + +## MCP Tools + +The server exposes the following MCP tools for authenticated clients: + +- `create_todo` - Create a new todo item +- `get_todo` - Retrieve a specific todo by ID +- `list_todos` - List todos with optional filtering by completion status +- `update_todo` - Update an existing todo's title or completion status +- `delete_todo` - Delete a todo by ID + +All tools are scoped to the authenticated client's session, ensuring data isolation between different OAuth clients. + +## Setup and Development + +### Prerequisites + +- Rust (latest stable version) +- PostgreSQL (for local development) +- Shuttle CLI (for deployment) + +### Local Development + +Run the following commands to get started: + +```bash +# Initialize the project +shuttle init --from shuttle-hq/shuttle-examples --subfolder mcp/mcp-sse-oauth + +# Navigate to the project directory +cd mcp-sse-oauth + +# Run the development server +shuttle run + +# Deploy the server +shuttle deploy +``` + +## API Endpoints + +### OAuth Endpoints + +| Endpoint | Method | Description | +| ----------------------------------------------- | ------ | ----------------------------------- | +| `/oauth/register` | POST | Register a new OAuth client | +| `/oauth/authorize` | GET | OAuth authorization endpoint | +| `/oauth/token` | POST | Token exchange and refresh endpoint | +| `/oauth/.well-known/oauth-authorization-server` | GET | OAuth server metadata | + +### MCP Endpoints + +| Endpoint | Method | Description | +| -------------- | ------ | ------------------------------------------------- | +| `/mcp/sse` | GET | Server-Sent Events endpoint for MCP communication | +| `/mcp/message` | POST | HTTP endpoint for MCP message posting | diff --git a/mcp/mcp-sse-oauth/migrations/20250730152154_create_mcp_clients_table.sql b/mcp/mcp-sse-oauth/migrations/20250730152154_create_mcp_clients_table.sql new file mode 100644 index 00000000..18dc5fef --- /dev/null +++ b/mcp/mcp-sse-oauth/migrations/20250730152154_create_mcp_clients_table.sql @@ -0,0 +1,9 @@ +-- Simplified MCP clients table +CREATE TABLE IF NOT EXISTS mcp_clients ( + client_id VARCHAR(255) PRIMARY KEY, + client_secret VARCHAR(255) NOT NULL, + client_name VARCHAR(255) NOT NULL DEFAULT 'MCP Client', + redirect_uris TEXT[] NOT NULL, + created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + client_secret_expires_at TIMESTAMP WITH TIME ZONE DEFAULT (CURRENT_TIMESTAMP + INTERVAL '90 days') +); \ No newline at end of file diff --git a/mcp/mcp-sse-oauth/migrations/20250730155304_create_authorization_codes_table.sql b/mcp/mcp-sse-oauth/migrations/20250730155304_create_authorization_codes_table.sql new file mode 100644 index 00000000..d1d83260 --- /dev/null +++ b/mcp/mcp-sse-oauth/migrations/20250730155304_create_authorization_codes_table.sql @@ -0,0 +1,10 @@ +-- Simplified authorization codes table +CREATE TABLE authorization_codes ( + code VARCHAR(128) PRIMARY KEY, + client_id VARCHAR(255) NOT NULL, + redirect_uri TEXT NOT NULL, + code_challenge VARCHAR(128) NOT NULL, + expires_at TIMESTAMP WITH TIME ZONE NOT NULL, + created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (client_id) REFERENCES mcp_clients(client_id) ON DELETE CASCADE +); \ No newline at end of file diff --git a/mcp/mcp-sse-oauth/migrations/20250730160425_create_refresh_tokens_table.sql b/mcp/mcp-sse-oauth/migrations/20250730160425_create_refresh_tokens_table.sql new file mode 100644 index 00000000..ea7e86ce --- /dev/null +++ b/mcp/mcp-sse-oauth/migrations/20250730160425_create_refresh_tokens_table.sql @@ -0,0 +1,8 @@ +-- Simplified refresh tokens table +CREATE TABLE refresh_tokens ( + token VARCHAR(128) PRIMARY KEY, + client_id VARCHAR(255) NOT NULL, + expires_at TIMESTAMP WITH TIME ZONE NOT NULL, + created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (client_id) REFERENCES mcp_clients(client_id) ON DELETE CASCADE +); \ No newline at end of file diff --git a/mcp/mcp-sse-oauth/migrations/20250801130039_create_todos_table.sql b/mcp/mcp-sse-oauth/migrations/20250801130039_create_todos_table.sql new file mode 100644 index 00000000..f9f87b3d --- /dev/null +++ b/mcp/mcp-sse-oauth/migrations/20250801130039_create_todos_table.sql @@ -0,0 +1,7 @@ +-- Simple todos table +CREATE TABLE todos ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + title VARCHAR(255) NOT NULL, + completed BOOLEAN NOT NULL DEFAULT FALSE, + client_id VARCHAR(255) NOT NULL +); \ No newline at end of file diff --git a/mcp/mcp-sse-oauth/src/auth.rs b/mcp/mcp-sse-oauth/src/auth.rs new file mode 100644 index 00000000..33067a58 --- /dev/null +++ b/mcp/mcp-sse-oauth/src/auth.rs @@ -0,0 +1,27 @@ +pub mod authorize; +pub mod metadata; +pub mod registration; +pub mod token; + +pub use authorize::{authorize_get, authorize_post}; +pub use metadata::oauth_authorization_server; +pub use registration::client_registration; +pub use token::token_post; + +use crate::init::AppState; +use axum::{ + routing::{get, post}, + Router, +}; +use std::sync::Arc; + +pub fn get_auth_router() -> Router> { + Router::new() + .route( + "/.well-known/oauth-authorization-server", + get(oauth_authorization_server), + ) + .route("/oauth/register", post(client_registration)) + .route("/oauth/authorize", get(authorize_get).post(authorize_post)) + .route("/oauth/token", post(token_post)) +} diff --git a/mcp/mcp-sse-oauth/src/auth/authorize.rs b/mcp/mcp-sse-oauth/src/auth/authorize.rs new file mode 100644 index 00000000..1a9a596a --- /dev/null +++ b/mcp/mcp-sse-oauth/src/auth/authorize.rs @@ -0,0 +1,170 @@ +use crate::init::AppState; +use askama::Template; +use axum::{ + extract::{Query, State}, + http::StatusCode, + response::{Html, IntoResponse, Redirect}, + Form, +}; +use chrono::{Duration, Utc}; +use rand::Rng; +use serde::Deserialize; +use std::sync::Arc; +use tracing::error; + +#[derive(Template)] +#[template(path = "authorize.html")] +struct AuthorizeTemplate { + client_id: String, + client_name: String, + redirect_uri: String, + scope: String, + scopes: Vec, + code_challenge: String, + code_challenge_method: String, + state: String, +} + +#[derive(Debug, Deserialize)] +pub struct AuthorizeRequest { + pub response_type: String, + pub client_id: String, + pub redirect_uri: String, + pub scope: Option, + pub state: Option, + pub code_challenge: String, + pub code_challenge_method: String, +} + +#[derive(Debug, Deserialize)] +pub struct AuthorizeForm { + pub client_id: String, + pub redirect_uri: String, + pub code_challenge: String, + pub state: Option, + pub action: String, +} + +fn generate_authorization_code() -> String { + use std::fmt::Write; + let mut code = String::new(); + let mut rng = rand::rng(); + for _ in 0..43 { + let byte: u8 = rng.random(); + write!(&mut code, "{byte:02x}").unwrap(); + } + code +} + +pub async fn authorize_get( + Query(params): Query, + State(state): State>, +) -> impl IntoResponse { + // Validate required parameters + if params.response_type != "code" { + return ( + StatusCode::BAD_REQUEST, + Html("Unsupported response type".to_string()), + ) + .into_response(); + } + + // Look up client in database + let client_result = sqlx::query!( + "SELECT client_name FROM mcp_clients WHERE client_id = $1", + params.client_id + ) + .fetch_optional(&state.pool) + .await; + + let client = match client_result { + Ok(Some(client)) => client, + Ok(None) => { + return (StatusCode::BAD_REQUEST, Html("Invalid client".to_string())).into_response() + } + Err(e) => { + error!("Database error: {}", e); + return ( + StatusCode::INTERNAL_SERVER_ERROR, + Html("Internal server error".to_string()), + ) + .into_response(); + } + }; + + let scope = params.scope.unwrap_or_else(|| "profile email".to_string()); + let scopes: Vec = scope.split_whitespace().map(|s| s.to_string()).collect(); + + let template = AuthorizeTemplate { + client_id: params.client_id, + client_name: client.client_name, + redirect_uri: params.redirect_uri, + scope: scope.clone(), + scopes, + code_challenge: params.code_challenge, + code_challenge_method: params.code_challenge_method, + state: params.state.unwrap_or_default(), + }; + + match template.render() { + Ok(html) => Html(html).into_response(), + Err(e) => { + error!("Template render error: {}", e); + ( + StatusCode::INTERNAL_SERVER_ERROR, + Html("Template error".to_string()), + ) + .into_response() + } + } +} + +pub async fn authorize_post( + State(state): State>, + Form(form): Form, +) -> impl IntoResponse { + if form.action == "deny" { + let mut redirect_url = format!("{}?error=access_denied", form.redirect_uri); + if let Some(state) = form.state { + redirect_url.push_str(&format!("&state={state}")); + } + return Redirect::to(&redirect_url).into_response(); + } + + // Generate authorization code + let auth_code = generate_authorization_code(); + let expires_at = Utc::now() + Duration::minutes(10); // 10 minute expiration + + // Store authorization code in database + let store_result = sqlx::query!( + r#" + INSERT INTO authorization_codes (code, client_id, redirect_uri, code_challenge, expires_at) + VALUES ($1, $2, $3, $4, $5) + "#, + auth_code, + form.client_id, + form.redirect_uri, + form.code_challenge, + expires_at + ) + .execute(&state.pool) + .await; + + match store_result { + Ok(_) => { + let mut redirect_url = format!("{}?code={}", form.redirect_uri, auth_code); + if let Some(state) = form.state { + redirect_url.push_str(&format!("&state={state}")); + } + Redirect::to(&redirect_url).into_response() + } + Err(e) => { + error!("Failed to store authorization code: {}", e); + let mut redirect_url = format!("{}?error=server_error", form.redirect_uri); + if let Some(state) = form.state { + redirect_url.push_str(&format!("&state={state}")); + } + Redirect::to(&redirect_url).into_response() + } + } +} diff --git a/mcp/mcp-sse-oauth/src/auth/metadata.rs b/mcp/mcp-sse-oauth/src/auth/metadata.rs new file mode 100644 index 00000000..0b3a14a5 --- /dev/null +++ b/mcp/mcp-sse-oauth/src/auth/metadata.rs @@ -0,0 +1,35 @@ +use crate::init::AppState; +use axum::{extract::State, http::StatusCode, response::IntoResponse, Json}; +use rmcp::transport::auth::AuthorizationMetadata; +use serde_json::Value; +use std::{collections::HashMap, sync::Arc}; + +pub async fn oauth_authorization_server(State(state): State>) -> impl IntoResponse { + let base_url = state + .secrets + .get("BASE_URL") + .expect("BASE_URL secret not found"); + + let mut additional_fields = HashMap::new(); + additional_fields.insert( + "response_types_supported".into(), + Value::Array(vec![Value::String("code".into())]), + ); + additional_fields.insert( + "code_challenge_methods_supported".into(), + Value::Array(vec![Value::String("S256".into())]), + ); + + let metadata = AuthorizationMetadata { + issuer: Some(base_url.clone()), + registration_endpoint: format!("{base_url}/oauth/register"), + authorization_endpoint: format!("{base_url}/oauth/authorize"), + token_endpoint: format!("{base_url}/oauth/token"), + + scopes_supported: Some(vec!["profile".to_string(), "email".to_string()]), + jwks_uri: None, + additional_fields, + }; + + (StatusCode::OK, Json(metadata)).into_response() +} diff --git a/mcp/mcp-sse-oauth/src/auth/registration.rs b/mcp/mcp-sse-oauth/src/auth/registration.rs new file mode 100644 index 00000000..1fcf8acd --- /dev/null +++ b/mcp/mcp-sse-oauth/src/auth/registration.rs @@ -0,0 +1,104 @@ +use crate::init::AppState; +use axum::{extract::State, http::StatusCode, response::IntoResponse, Json}; +use chrono; +use rand; +use serde::{Deserialize, Serialize}; +use std::sync::Arc; +use tracing::error; +use uuid::Uuid; + +#[derive(Debug, Deserialize)] +pub struct ClientRegistrationRequest { + pub client_name: Option, + pub redirect_uris: Vec, + pub scope: Option, +} + +#[derive(Debug, Serialize)] +pub struct ClientRegistrationResponse { + pub client_id: String, + pub client_secret: String, + pub client_name: String, + pub redirect_uris: Vec, + pub scope: String, + pub client_id_issued_at: i64, + pub client_secret_expires_at: i64, +} + +fn generate_client_secret() -> String { + use std::fmt::Write; + let mut secret = String::new(); + for _ in 0..32 { + let byte: u8 = rand::random(); + write!(&mut secret, "{byte:02x}").unwrap(); + } + secret +} + +pub async fn client_registration( + State(state): State>, + Json(request): Json, +) -> impl IntoResponse { + // Validate redirect URIs are provided + if request.redirect_uris.is_empty() { + return ( + StatusCode::BAD_REQUEST, + Json(serde_json::json!({ + "error": "invalid_request", + "error_description": "redirect_uris is required and must not be empty" + })), + ) + .into_response(); + } + + // Generate client credentials + let client_id = Uuid::new_v4().to_string(); + let client_secret = generate_client_secret(); + let client_name = request + .client_name + .unwrap_or_else(|| "MCP Client".to_string()); + let scopes = request.scope.unwrap_or_else(|| "mcp".to_string()); + let issued_at = chrono::Utc::now().timestamp(); + let expires_at = chrono::Utc::now() + chrono::Duration::days(90); + + // Store client in database + let query_result = sqlx::query!( + r#" + INSERT INTO mcp_clients (client_id, client_secret, client_name, redirect_uris, client_secret_expires_at) + VALUES ($1, $2, $3, $4, $5) + "#, + client_id, + client_secret, + client_name, + &request.redirect_uris, + expires_at + ) + .execute(&state.pool) + .await; + + match query_result { + Ok(_) => { + let response = ClientRegistrationResponse { + client_id: client_id.clone(), + client_secret, + client_name, + redirect_uris: request.redirect_uris, + scope: scopes, + client_id_issued_at: issued_at, + client_secret_expires_at: expires_at.timestamp(), + }; + (StatusCode::CREATED, Json(response)).into_response() + } + Err(e) => { + error!("Failed to register client: {}", e); + ( + StatusCode::INTERNAL_SERVER_ERROR, + Json(serde_json::json!({ + "error": "server_error", + "error_description": "Failed to register client" + })), + ) + .into_response() + } + } +} diff --git a/mcp/mcp-sse-oauth/src/auth/token.rs b/mcp/mcp-sse-oauth/src/auth/token.rs new file mode 100644 index 00000000..f90e26d2 --- /dev/null +++ b/mcp/mcp-sse-oauth/src/auth/token.rs @@ -0,0 +1,473 @@ +use crate::init::AppState; +use axum::{ + extract::State, + http::StatusCode, + response::{IntoResponse, Json, Response}, + Form, +}; +use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; +use chrono::{Duration, Utc}; +use jsonwebtoken::{encode, EncodingKey, Header}; +use rand::Rng; +use serde::{Deserialize, Serialize}; +use sha2::{Digest, Sha256}; +use std::sync::Arc; +use tracing::error; + +#[derive(Debug, Deserialize)] +pub struct TokenRequest { + pub grant_type: String, + pub code: Option, + pub redirect_uri: Option, + pub client_id: String, + pub client_secret: Option, + pub code_verifier: Option, + pub refresh_token: Option, +} + +#[derive(Debug, Serialize)] +pub struct TokenResponse { + pub access_token: String, + pub token_type: String, + pub expires_in: i64, + pub refresh_token: String, + pub scope: String, +} + +#[derive(Debug, Serialize)] +pub struct ErrorResponse { + pub error: String, + pub error_description: Option, +} + +#[derive(Debug, Serialize)] +struct Claims { + sub: String, // client_id + iat: i64, // issued at + exp: i64, // expires at + scope: String, // granted scopes +} + +fn verify_pkce_challenge(code_verifier: &str, code_challenge: &str) -> bool { + let mut hasher = Sha256::new(); + hasher.update(code_verifier.as_bytes()); + let hash = hasher.finalize(); + let encoded = URL_SAFE_NO_PAD.encode(hash); + encoded == code_challenge +} + +fn generate_refresh_token() -> String { + use std::fmt::Write; + let mut token = String::new(); + let mut rng = rand::rng(); + for _ in 0..64 { + let byte: u8 = rng.random(); + write!(&mut token, "{byte:02x}").unwrap(); + } + token +} + +fn generate_access_token( + client_id: &str, + scope: &str, + jwt_secret: &str, +) -> Result { + let now = Utc::now(); + let claims = Claims { + sub: client_id.to_string(), + iat: now.timestamp(), + exp: (now + Duration::minutes(15)).timestamp(), // 15 minute expiration + scope: scope.to_string(), + }; + + let key = EncodingKey::from_secret(jwt_secret.as_bytes()); + encode(&Header::default(), &claims, &key) +} + +async fn validate_client_credentials( + state: &AppState, + client_id: &str, + client_secret: Option<&String>, +) -> Result<(), ErrorResponse> { + let client_secret = match client_secret { + Some(secret) => secret, + None => { + return Err(ErrorResponse { + error: "invalid_client".to_string(), + error_description: Some("client_secret parameter is required".to_string()), + }); + } + }; + + let client_result = sqlx::query!( + "SELECT client_secret FROM mcp_clients WHERE client_id = $1", + client_id + ) + .fetch_optional(&state.pool) + .await; + + let client = match client_result { + Ok(Some(client)) => client, + Ok(None) => { + return Err(ErrorResponse { + error: "invalid_client".to_string(), + error_description: Some("Client not found".to_string()), + }); + } + Err(e) => { + error!("Database error during client validation: {}", e); + return Err(ErrorResponse { + error: "server_error".to_string(), + error_description: Some("Internal server error".to_string()), + }); + } + }; + + if client.client_secret != *client_secret { + return Err(ErrorResponse { + error: "invalid_client".to_string(), + error_description: Some("Invalid client credentials".to_string()), + }); + } + + Ok(()) +} + +pub async fn token_post( + State(state): State>, + Form(request): Form, +) -> Response { + match request.grant_type.as_str() { + "authorization_code" => handle_authorization_code_grant(state, request) + .await + .into_response(), + "refresh_token" => handle_refresh_token_grant(state, request) + .await + .into_response(), + _ => { + let error = ErrorResponse { + error: "unsupported_grant_type".to_string(), + error_description: Some( + "Only authorization_code and refresh_token grant types are supported" + .to_string(), + ), + }; + (StatusCode::BAD_REQUEST, Json(error)).into_response() + } + } +} + +async fn handle_authorization_code_grant( + state: Arc, + request: TokenRequest, +) -> impl IntoResponse { + // Validate client credentials + if let Err(error) = + validate_client_credentials(&state, &request.client_id, request.client_secret.as_ref()) + .await + { + return (StatusCode::UNAUTHORIZED, Json(error)).into_response(); + } + + // Validate required parameters for authorization code grant + let code = match request.code { + Some(code) => code, + None => { + let error = ErrorResponse { + error: "invalid_request".to_string(), + error_description: Some("code parameter is required".to_string()), + }; + return (StatusCode::BAD_REQUEST, Json(error)).into_response(); + } + }; + + let redirect_uri = match request.redirect_uri { + Some(uri) => uri, + None => { + let error = ErrorResponse { + error: "invalid_request".to_string(), + error_description: Some("redirect_uri parameter is required".to_string()), + }; + return (StatusCode::BAD_REQUEST, Json(error)).into_response(); + } + }; + + let code_verifier = match request.code_verifier { + Some(verifier) => verifier, + None => { + let error = ErrorResponse { + error: "invalid_request".to_string(), + error_description: Some("code_verifier parameter is required".to_string()), + }; + return (StatusCode::BAD_REQUEST, Json(error)).into_response(); + } + }; + + // Look up authorization code in database + let auth_code_result = sqlx::query!( + r#" + SELECT client_id, redirect_uri, code_challenge, expires_at + FROM authorization_codes + WHERE code = $1 + "#, + code + ) + .fetch_optional(&state.pool) + .await; + + let auth_code = match auth_code_result { + Ok(Some(code)) => code, + Ok(None) => { + let error = ErrorResponse { + error: "invalid_grant".to_string(), + error_description: Some("Authorization code not found".to_string()), + }; + return (StatusCode::BAD_REQUEST, Json(error)).into_response(); + } + Err(e) => { + error!("Database error: {}", e); + let error = ErrorResponse { + error: "server_error".to_string(), + error_description: Some("Internal server error".to_string()), + }; + return (StatusCode::INTERNAL_SERVER_ERROR, Json(error)).into_response(); + } + }; + + // Validate authorization code hasn't expired + + if Utc::now() > auth_code.expires_at { + let error = ErrorResponse { + error: "invalid_grant".to_string(), + error_description: Some("Authorization code expired".to_string()), + }; + return (StatusCode::BAD_REQUEST, Json(error)).into_response(); + } + + if auth_code.client_id != request.client_id { + let error = ErrorResponse { + error: "invalid_grant".to_string(), + error_description: Some("Client ID mismatch".to_string()), + }; + return (StatusCode::BAD_REQUEST, Json(error)).into_response(); + } + + if auth_code.redirect_uri != redirect_uri { + let error = ErrorResponse { + error: "invalid_grant".to_string(), + error_description: Some("Redirect URI mismatch".to_string()), + }; + return (StatusCode::BAD_REQUEST, Json(error)).into_response(); + } + + // Verify PKCE code challenge + if !verify_pkce_challenge(&code_verifier, &auth_code.code_challenge) { + let error = ErrorResponse { + error: "invalid_grant".to_string(), + error_description: Some("PKCE verification failed".to_string()), + }; + return (StatusCode::BAD_REQUEST, Json(error)).into_response(); + } + + // Delete authorization code (one-time use) + let delete_result = sqlx::query!("DELETE FROM authorization_codes WHERE code = $1", code) + .execute(&state.pool) + .await; + + if let Err(e) = delete_result { + error!("Failed to delete authorization code: {}", e); + } + + // Generate access token and refresh token + let scope = "mcp"; + + let jwt_secret = state + .secrets + .get("JWT_SECRET") + .expect("JWT_SECRET secret not found"); + + let access_token = match generate_access_token(&request.client_id, scope, &jwt_secret) { + Ok(token) => token, + Err(e) => { + error!("Failed to generate access token: {}", e); + let error = ErrorResponse { + error: "server_error".to_string(), + error_description: Some("Failed to generate access token".to_string()), + }; + return (StatusCode::INTERNAL_SERVER_ERROR, Json(error)).into_response(); + } + }; + + let refresh_token = generate_refresh_token(); + let refresh_expires_at = Utc::now() + Duration::days(30); // 30 day expiration + + // Store refresh token in database + let store_refresh_result = sqlx::query!( + r#" + INSERT INTO refresh_tokens (token, client_id, expires_at) + VALUES ($1, $2, $3) + "#, + refresh_token, + request.client_id, + refresh_expires_at + ) + .execute(&state.pool) + .await; + + if let Err(e) = store_refresh_result { + error!("Failed to store refresh token: {}", e); + let error = ErrorResponse { + error: "server_error".to_string(), + error_description: Some("Failed to store refresh token".to_string()), + }; + return (StatusCode::INTERNAL_SERVER_ERROR, Json(error)).into_response(); + } + + let response = TokenResponse { + access_token, + token_type: "Bearer".to_string(), + expires_in: 900, // 15 minutes + refresh_token, + scope: scope.to_string(), + }; + + (StatusCode::OK, Json(response)).into_response() +} + +async fn handle_refresh_token_grant( + state: Arc, + request: TokenRequest, +) -> impl IntoResponse { + // Validate client credentials + if let Err(error) = + validate_client_credentials(&state, &request.client_id, request.client_secret.as_ref()) + .await + { + return (StatusCode::UNAUTHORIZED, Json(error)).into_response(); + } + + // Validate required parameters for refresh token grant + let refresh_token = match request.refresh_token { + Some(token) => token, + None => { + let error = ErrorResponse { + error: "invalid_request".to_string(), + error_description: Some("refresh_token parameter is required".to_string()), + }; + return (StatusCode::BAD_REQUEST, Json(error)).into_response(); + } + }; + + // Look up refresh token in database + let refresh_token_result = sqlx::query!( + r#" + SELECT client_id, expires_at + FROM refresh_tokens + WHERE token = $1 + "#, + refresh_token + ) + .fetch_optional(&state.pool) + .await; + + let refresh_token_record = match refresh_token_result { + Ok(Some(token)) => token, + Ok(None) => { + let error = ErrorResponse { + error: "invalid_grant".to_string(), + error_description: Some("Refresh token not found".to_string()), + }; + return (StatusCode::BAD_REQUEST, Json(error)).into_response(); + } + Err(e) => { + error!("Database error: {}", e); + let error = ErrorResponse { + error: "server_error".to_string(), + error_description: Some("Internal server error".to_string()), + }; + return (StatusCode::INTERNAL_SERVER_ERROR, Json(error)).into_response(); + } + }; + + // Validate refresh token hasn't expired + + if Utc::now() > refresh_token_record.expires_at { + let error = ErrorResponse { + error: "invalid_grant".to_string(), + error_description: Some("Refresh token expired".to_string()), + }; + return (StatusCode::BAD_REQUEST, Json(error)).into_response(); + } + + if refresh_token_record.client_id != request.client_id { + let error = ErrorResponse { + error: "invalid_grant".to_string(), + error_description: Some("Client ID mismatch".to_string()), + }; + return (StatusCode::BAD_REQUEST, Json(error)).into_response(); + } + + // Delete old refresh token (rotation) + let delete_result = sqlx::query!("DELETE FROM refresh_tokens WHERE token = $1", refresh_token) + .execute(&state.pool) + .await; + + if let Err(e) = delete_result { + error!("Failed to delete old refresh token: {}", e); + } + + // Generate new access token and refresh token + let scope = "mcp"; + + let jwt_secret = state + .secrets + .get("JWT_SECRET") + .expect("JWT_SECRET secret not found"); + + let access_token = match generate_access_token(&request.client_id, scope, &jwt_secret) { + Ok(token) => token, + Err(e) => { + error!("Failed to generate access token: {}", e); + let error = ErrorResponse { + error: "server_error".to_string(), + error_description: Some("Failed to generate access token".to_string()), + }; + return (StatusCode::INTERNAL_SERVER_ERROR, Json(error)).into_response(); + } + }; + + let new_refresh_token = generate_refresh_token(); + let refresh_expires_at = Utc::now() + Duration::days(30); // 30 day expiration + + // Store new refresh token in database + let store_refresh_result = sqlx::query!( + r#" + INSERT INTO refresh_tokens (token, client_id, expires_at) + VALUES ($1, $2, $3) + "#, + new_refresh_token, + request.client_id, + refresh_expires_at + ) + .execute(&state.pool) + .await; + + if let Err(e) = store_refresh_result { + error!("Failed to store new refresh token: {}", e); + let error = ErrorResponse { + error: "server_error".to_string(), + error_description: Some("Failed to store refresh token".to_string()), + }; + return (StatusCode::INTERNAL_SERVER_ERROR, Json(error)).into_response(); + } + + let response = TokenResponse { + access_token, + token_type: "Bearer".to_string(), + expires_in: 900, // 15 minutes + refresh_token: new_refresh_token, + scope: scope.to_string(), + }; + + (StatusCode::OK, Json(response)).into_response() +} diff --git a/mcp/mcp-sse-oauth/src/init.rs b/mcp/mcp-sse-oauth/src/init.rs new file mode 100644 index 00000000..6a8625ea --- /dev/null +++ b/mcp/mcp-sse-oauth/src/init.rs @@ -0,0 +1,98 @@ +use crate::{auth::get_auth_router, middleware::validate_token_middleware, todo_mcp::TodoService}; +use axum::{middleware, Router}; +use rmcp::transport::{sse_server::SseServerConfig, SseServer}; +use sqlx::PgPool; +use std::{net::SocketAddr, sync::Arc, time::Duration}; +use tokio_util::sync::CancellationToken; +use tower_http::cors::{Any, CorsLayer}; +use tracing::{error, info}; + +#[derive(Clone)] +pub struct AppState { + pub pool: PgPool, + pub secrets: shuttle_runtime::SecretStore, +} + +impl AppState { + pub fn new(pool: PgPool, secrets: shuttle_runtime::SecretStore) -> Self { + Self { pool, secrets } + } +} + +pub async fn init( + addr: SocketAddr, + pool: PgPool, + secrets: shuttle_runtime::SecretStore, +) -> Result<(), shuttle_runtime::Error> { + // Run database migrations + sqlx::migrate!() + .run(&pool) + .await + .map_err(|e| shuttle_runtime::Error::Custom(anyhow::anyhow!("Migration failed: {}", e)))?; + + // Create the OAuth store + let app_state = Arc::new(AppState::new(pool, secrets)); + + // Create SSE server configuration for MCP + let sse_config = SseServerConfig { + bind: addr, + sse_path: "/mcp/sse".to_string(), + post_path: "/mcp/message".to_string(), + ct: CancellationToken::new(), + sse_keep_alive: Some(Duration::from_secs(15)), + }; + + // Create SSE server + let (sse_server, sse_router) = SseServer::new(sse_config); + + // Create protected SSE routes (require authorization) + let protected_sse_router = sse_router.layer(middleware::from_fn_with_state( + app_state.clone(), + validate_token_middleware, + )); + + // Create CORS layer for the oauth authorization server endpoint + let cors_layer = CorsLayer::new() + .allow_origin(Any) + .allow_methods(Any) + .allow_headers(Any); + + let auth_router = get_auth_router(); + + // Create HTTP router with auth routes (non-protected) and protected SSE router + let app = Router::new() + .merge(auth_router) + .with_state(app_state.clone()) + .merge(protected_sse_router) + .layer(cors_layer); + // Register token validation middleware for SSE + let cancel_token = sse_server.config.ct.clone(); + // Handle Ctrl+C + let cancel_token2 = sse_server.config.ct.clone(); + // Start SSE server with TodoService + sse_server.with_service(move || TodoService::new(Arc::new(app_state.pool.clone()))); + + // Start HTTP server + info!("MCP OAuth Server started on {}", addr); + let listener = tokio::net::TcpListener::bind(addr).await?; + let server = axum::serve(listener, app).with_graceful_shutdown(async move { + cancel_token.cancelled().await; + info!("Server is shutting down"); + }); + + tokio::spawn(async move { + match tokio::signal::ctrl_c().await { + Ok(()) => { + info!("Received Ctrl+C, shutting down"); + cancel_token2.cancel(); + } + Err(e) => error!("Failed to listen for Ctrl+C: {}", e), + } + }); + + if let Err(e) = server.await { + error!("Server error: {}", e); + } + + Ok(()) +} diff --git a/mcp/mcp-sse-oauth/src/main.rs b/mcp/mcp-sse-oauth/src/main.rs new file mode 100644 index 00000000..7809f235 --- /dev/null +++ b/mcp/mcp-sse-oauth/src/main.rs @@ -0,0 +1,31 @@ +use sqlx::PgPool; +use std::net::SocketAddr; + +mod auth; +mod init; +mod middleware; +mod todo_mcp; +mod todos; + +struct McpSseService { + pool: PgPool, + secrets: shuttle_runtime::SecretStore, +} + +#[shuttle_runtime::async_trait] +impl shuttle_runtime::Service for McpSseService { + async fn bind(self, addr: SocketAddr) -> Result<(), shuttle_runtime::Error> { + init::init(addr, self.pool, self.secrets).await + } +} + +#[shuttle_runtime::main] +async fn main( + #[shuttle_shared_db::Postgres( + local_uri = "postgres://postgres:password@localhost:5432/mcp-sse-auth" + )] + pool: PgPool, + #[shuttle_runtime::Secrets] secrets: shuttle_runtime::SecretStore, +) -> Result { + Ok(McpSseService { pool, secrets }) +} diff --git a/mcp/mcp-sse-oauth/src/middleware.rs b/mcp/mcp-sse-oauth/src/middleware.rs new file mode 100644 index 00000000..7e932c06 --- /dev/null +++ b/mcp/mcp-sse-oauth/src/middleware.rs @@ -0,0 +1,97 @@ +use crate::init::AppState; +use axum::{ + body::Body, + extract::State, + http::{Request, StatusCode}, + middleware::Next, + response::{IntoResponse, Response}, +}; +use jsonwebtoken::{decode, DecodingKey, Validation}; +use serde::{Deserialize, Serialize}; +use std::sync::Arc; +use tracing::error; + +#[derive(Debug, Serialize, Deserialize)] +pub struct Claims { + pub sub: String, // client_id + pub iat: i64, // issued at + pub exp: i64, // expires at + pub scope: String, // granted scopes +} + +pub async fn validate_token_middleware( + State(state): State>, + mut request: Request, + next: Next, +) -> Response { + let auth_header = request.headers().get("Authorization"); + let token = match auth_header { + Some(header) => { + let header_str = match header.to_str() { + Ok(s) => s, + Err(_) => { + error!("Invalid Authorization header encoding"); + return StatusCode::UNAUTHORIZED.into_response(); + } + }; + + if let Some(stripped) = header_str.strip_prefix("Bearer ") { + stripped.to_string() + } else { + error!("Authorization header missing Bearer prefix"); + return StatusCode::UNAUTHORIZED.into_response(); + } + } + None => { + error!("Missing Authorization header"); + return StatusCode::UNAUTHORIZED.into_response(); + } + }; + + let jwt_secret = state + .secrets + .get("JWT_SECRET") + .expect("JWT_SECRET secret not found"); + + let key = DecodingKey::from_secret(jwt_secret.as_bytes()); + let validation = Validation::default(); + + match decode::(&token, &key, &validation) { + Ok(token_data) => { + // Check if token is expired (JWT validation already handles this, but being explicit) + let now = chrono::Utc::now().timestamp(); + if token_data.claims.exp < now { + error!("Token has expired"); + return StatusCode::UNAUTHORIZED.into_response(); + } + + // Optionally, verify the client still exists in database + let client_exists = sqlx::query!( + "SELECT client_id FROM mcp_clients WHERE client_id = $1", + token_data.claims.sub + ) + .fetch_optional(&state.pool) + .await; + + match client_exists { + Ok(Some(_)) => { + // Add client_id to request extensions for downstream handlers + request.extensions_mut().insert(token_data.claims.sub); + next.run(request).await + } + Ok(None) => { + error!("Client no longer exists: {}", token_data.claims.sub); + StatusCode::UNAUTHORIZED.into_response() + } + Err(e) => { + error!("Database error validating client: {}", e); + StatusCode::INTERNAL_SERVER_ERROR.into_response() + } + } + } + Err(e) => { + error!("Token validation failed: {}", e); + StatusCode::UNAUTHORIZED.into_response() + } + } +} diff --git a/mcp/mcp-sse-oauth/src/todo_mcp.rs b/mcp/mcp-sse-oauth/src/todo_mcp.rs new file mode 100644 index 00000000..a1bf2d30 --- /dev/null +++ b/mcp/mcp-sse-oauth/src/todo_mcp.rs @@ -0,0 +1 @@ +pub use crate::todos::mcp_service::TodoService; diff --git a/mcp/mcp-sse-oauth/src/todos/db.rs b/mcp/mcp-sse-oauth/src/todos/db.rs new file mode 100644 index 00000000..bfb8e6bd --- /dev/null +++ b/mcp/mcp-sse-oauth/src/todos/db.rs @@ -0,0 +1,190 @@ +use serde::{Deserialize, Serialize}; +use sqlx::{PgPool, Row}; +use uuid::Uuid; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Todo { + pub id: Uuid, + pub title: String, + pub completed: bool, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct CreateTodoRequest { + pub title: String, + pub completed: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct UpdateTodoRequest { + pub title: Option, + pub completed: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct ListTodosFilter { + pub completed: Option, +} + +pub async fn create_todo( + pool: &PgPool, + request: CreateTodoRequest, + client_id: &str, +) -> Result { + let row = sqlx::query!( + r#" + INSERT INTO todos (title, completed, client_id) + VALUES ($1, COALESCE($2, FALSE), $3) + RETURNING id, title, completed + "#, + request.title, + request.completed, + client_id + ) + .fetch_one(pool) + .await?; + + Ok(Todo { + id: row.id, + title: row.title, + completed: row.completed, + }) +} + +pub async fn list_todos( + pool: &PgPool, + client_id: &str, + filter: Option, +) -> Result, sqlx::Error> { + let mut query = "SELECT id, title, completed FROM todos WHERE client_id = $1".to_string(); + let param_count = 2; + + if let Some(f) = &filter { + if f.completed.is_some() { + query.push_str(&format!(" AND completed = ${param_count}")); + } + } + + query.push_str(" ORDER BY id DESC"); + + let mut query_builder = sqlx::query(&query).bind(client_id); + + if let Some(f) = &filter { + if let Some(completed) = f.completed { + query_builder = query_builder.bind(completed); + } + } + + let rows = query_builder.fetch_all(pool).await?; + + let todos = rows + .into_iter() + .map(|row| Todo { + id: row.get("id"), + title: row.get("title"), + completed: row.get("completed"), + }) + .collect(); + + Ok(todos) +} + +pub async fn update_todo( + pool: &PgPool, + id: Uuid, + client_id: &str, + request: UpdateTodoRequest, +) -> Result, sqlx::Error> { + let mut set_clauses = Vec::new(); + let mut param_count = 1; + + if request.title.is_some() { + set_clauses.push(format!("title = ${param_count}")); + param_count += 1; + } + if request.completed.is_some() { + set_clauses.push(format!("completed = ${param_count}")); + param_count += 1; + } + + if set_clauses.is_empty() { + let row = sqlx::query!( + r#" + SELECT id, title, completed + FROM todos + WHERE id = $1 AND client_id = $2 + "#, + id, + client_id + ) + .fetch_optional(pool) + .await?; + + return Ok(row.map(|r| Todo { + id: r.id, + title: r.title, + completed: r.completed, + })); + } + + let query = format!( + "UPDATE todos SET {} WHERE id = ${} AND client_id = ${} RETURNING id, title, completed", + set_clauses.join(", "), + param_count, + param_count + 1 + ); + + let mut query_builder = sqlx::query(&query); + + if let Some(title) = request.title { + query_builder = query_builder.bind(title); + } + if let Some(completed) = request.completed { + query_builder = query_builder.bind(completed); + } + query_builder = query_builder.bind(id).bind(client_id); + + let row = query_builder.fetch_optional(pool).await?; + + Ok(row.map(|r| Todo { + id: r.get("id"), + title: r.get("title"), + completed: r.get("completed"), + })) +} + +pub async fn delete_todo(pool: &PgPool, id: Uuid, client_id: &str) -> Result { + let result = sqlx::query!( + "DELETE FROM todos WHERE id = $1 AND client_id = $2", + id, + client_id + ) + .execute(pool) + .await?; + + Ok(result.rows_affected() > 0) +} + +pub async fn get_todo_by_id( + pool: &PgPool, + id: Uuid, + client_id: &str, +) -> Result, sqlx::Error> { + let row = sqlx::query!( + r#" + SELECT id, title, completed + FROM todos + WHERE id = $1 AND client_id = $2 + "#, + id, + client_id + ) + .fetch_optional(pool) + .await?; + + Ok(row.map(|r| Todo { + id: r.id, + title: r.title, + completed: r.completed, + })) +} diff --git a/mcp/mcp-sse-oauth/src/todos/mcp_service.rs b/mcp/mcp-sse-oauth/src/todos/mcp_service.rs new file mode 100644 index 00000000..6846deee --- /dev/null +++ b/mcp/mcp-sse-oauth/src/todos/mcp_service.rs @@ -0,0 +1,269 @@ +use super::db::{self, CreateTodoRequest, ListTodosFilter, UpdateTodoRequest}; +use rmcp::{ + handler::server::{router::tool::ToolRouter, tool::Parameters}, + model::*, + schemars, + service::RequestContext, + tool, tool_handler, tool_router, ErrorData as McpError, RoleServer, ServerHandler, +}; +use serde::{Deserialize, Serialize}; +use sqlx::PgPool; +use std::future::Future; +use std::sync::Arc; +use tokio::sync::Mutex; +use uuid::Uuid; + +#[derive(Clone)] +pub struct TodoService { + db_pool: Arc, + tool_router: ToolRouter, + client_id: Arc>>, +} + +#[derive(Debug, Serialize, Deserialize, schemars::JsonSchema)] +pub struct CreateTodoInput { + pub title: String, + pub completed: Option, +} + +#[derive(Debug, Serialize, Deserialize, schemars::JsonSchema)] +pub struct GetTodoInput { + pub id: String, +} + +#[derive(Debug, Serialize, Deserialize, schemars::JsonSchema)] +pub struct ListTodosInput { + pub completed: Option, +} + +#[derive(Debug, Serialize, Deserialize, schemars::JsonSchema)] +pub struct UpdateTodoInput { + pub id: String, + pub title: Option, + pub completed: Option, +} + +#[derive(Debug, Serialize, Deserialize, schemars::JsonSchema)] +pub struct DeleteTodoInput { + pub id: String, +} + +#[tool_router] +impl TodoService { + pub fn new(db_pool: Arc) -> Self { + Self { + db_pool, + tool_router: Self::tool_router(), + client_id: Arc::new(Mutex::new(None)), + } + } + + #[tool(description = "Create a new todo item")] + async fn create_todo( + &self, + Parameters(input): Parameters, + ) -> Result { + let client_id = { + let reader = self.client_id.lock().await; + reader.clone().ok_or_else(|| { + McpError::internal_error("Client not authenticated".to_string(), None) + })? + }; + + let request = CreateTodoRequest { + title: input.title, + completed: input.completed, + }; + + match db::create_todo(&self.db_pool, request, &client_id).await { + Ok(todo) => { + let todo_json = serde_json::to_string_pretty(&todo).map_err(|e| { + McpError::internal_error(format!("Serialization error: {e}"), None) + })?; + Ok(CallToolResult::success(vec![Content::text(format!( + "Todo created successfully:\n{todo_json}" + ))])) + } + Err(e) => Err(McpError::internal_error( + format!("Failed to create todo: {e}"), + None, + )), + } + } + + #[tool(description = "Get a specific todo by ID")] + async fn get_todo( + &self, + Parameters(input): Parameters, + ) -> Result { + let id = input + .id + .parse::() + .map_err(|e| McpError::invalid_params(format!("Invalid UUID format: {e}"), None))?; + + let client_id = { + let reader = self.client_id.lock().await; + reader.clone().ok_or_else(|| { + McpError::internal_error("Client not authenticated".to_string(), None) + })? + }; + + match db::get_todo_by_id(&self.db_pool, id, &client_id).await { + Ok(Some(todo)) => { + let todo_json = serde_json::to_string_pretty(&todo).map_err(|e| { + McpError::internal_error(format!("Serialization error: {e}"), None) + })?; + Ok(CallToolResult::success(vec![Content::text(todo_json)])) + } + Ok(None) => Ok(CallToolResult::success(vec![Content::text(format!( + "Todo with ID {id} not found or not accessible" + ))])), + Err(e) => Err(McpError::internal_error( + format!("Failed to get todo: {e}"), + None, + )), + } + } + + #[tool(description = "List todos with optional filtering")] + async fn list_todos( + &self, + Parameters(input): Parameters, + ) -> Result { + let client_id = { + let reader = self.client_id.lock().await; + reader.clone().ok_or_else(|| { + McpError::internal_error("Client not authenticated".to_string(), None) + })? + }; + + let filter = if input.completed.is_some() { + Some(ListTodosFilter { + completed: input.completed, + }) + } else { + None + }; + + match db::list_todos(&self.db_pool, &client_id, filter).await { + Ok(todos) => { + let todos_json = serde_json::to_string_pretty(&todos).map_err(|e| { + McpError::internal_error(format!("Serialization error: {e}"), None) + })?; + Ok(CallToolResult::success(vec![Content::text(format!( + "Found {} todos:\n{}", + todos.len(), + todos_json + ))])) + } + Err(e) => Err(McpError::internal_error( + format!("Failed to list todos: {e}"), + None, + )), + } + } + + #[tool(description = "Update an existing todo")] + async fn update_todo( + &self, + Parameters(input): Parameters, + ) -> Result { + let id = input + .id + .parse::() + .map_err(|e| McpError::invalid_params(format!("Invalid UUID format: {e}"), None))?; + + let client_id = { + let reader = self.client_id.lock().await; + reader.clone().ok_or_else(|| { + McpError::internal_error("Client not authenticated".to_string(), None) + })? + }; + + let request = UpdateTodoRequest { + title: input.title, + completed: input.completed, + }; + + match db::update_todo(&self.db_pool, id, &client_id, request).await { + Ok(Some(todo)) => { + let todo_json = serde_json::to_string_pretty(&todo).map_err(|e| { + McpError::internal_error(format!("Serialization error: {e}"), None) + })?; + Ok(CallToolResult::success(vec![Content::text(format!( + "Todo updated successfully:\n{todo_json}" + ))])) + } + Ok(None) => Ok(CallToolResult::success(vec![Content::text(format!( + "Todo with ID {id} not found or not accessible" + ))])), + Err(e) => Err(McpError::internal_error( + format!("Failed to update todo: {e}"), + None, + )), + } + } + + #[tool(description = "Delete a todo by ID")] + async fn delete_todo( + &self, + Parameters(input): Parameters, + ) -> Result { + let id = input + .id + .parse::() + .map_err(|e| McpError::invalid_params(format!("Invalid UUID format: {e}"), None))?; + + let client_id = { + let reader = self.client_id.lock().await; + reader.clone().ok_or_else(|| { + McpError::internal_error("Client not authenticated".to_string(), None) + })? + }; + + match db::delete_todo(&self.db_pool, id, &client_id).await { + Ok(true) => Ok(CallToolResult::success(vec![Content::text(format!( + "Todo with ID {id} deleted successfully" + ))])), + Ok(false) => Ok(CallToolResult::success(vec![Content::text(format!( + "Todo with ID {id} not found or not accessible" + ))])), + Err(e) => Err(McpError::internal_error( + format!("Failed to delete todo: {e}"), + None, + )), + } + } +} + +#[tool_handler] +impl ServerHandler for TodoService { + fn get_info(&self) -> ServerInfo { + ServerInfo { + protocol_version: ProtocolVersion::V_2024_11_05, + capabilities: ServerCapabilities::builder() + .enable_prompts() + .enable_resources() + .enable_tools() + .build(), + server_info: Implementation::from_build_env(), + instructions: Some("This server provides todo management tools. You can create, read, update, and delete todos. Each todo has an id, title, and completion status.".to_string()), + } + } + + async fn initialize( + &self, + _request: InitializeRequestParam, + context: RequestContext, + ) -> Result { + if let Some(http_request_part) = context.extensions.get::() { + if let Some(client_id) = http_request_part.extensions.get::() { + let mut writer = self.client_id.lock().await; + *writer = Some(client_id.clone()); + } else { + tracing::warn!("No client_id found in HTTP request extensions"); + } + } + Ok(self.get_info()) + } +} diff --git a/mcp/mcp-sse-oauth/src/todos/mod.rs b/mcp/mcp-sse-oauth/src/todos/mod.rs new file mode 100644 index 00000000..61025f53 --- /dev/null +++ b/mcp/mcp-sse-oauth/src/todos/mod.rs @@ -0,0 +1,2 @@ +pub mod db; +pub mod mcp_service; diff --git a/mcp/mcp-sse-oauth/templates/authorize.html b/mcp/mcp-sse-oauth/templates/authorize.html new file mode 100644 index 00000000..22218078 --- /dev/null +++ b/mcp/mcp-sse-oauth/templates/authorize.html @@ -0,0 +1,106 @@ + + + + + + Authorize Application + + + +
+

Authorize Application

+ +
+

Application: {{ client_name }}

+

Redirect URI: {{ redirect_uri }}

+
+ +
+

Permissions requested:

+ {% for scope in scopes %} +
{{ scope }}
+ {% endfor %} +
+ +
+ + + + + + + +
+ + +
+
+
+ + \ No newline at end of file diff --git a/templates.toml b/templates.toml index 1256b3a1..0f662861 100644 --- a/templates.toml +++ b/templates.toml @@ -370,6 +370,13 @@ path = "mcp/mcp-sse" use_cases = ["Web app", "MCP"] tags = ["axum", "mcp", "sse"] +[templates.mcp-sse-oauth] +title = "SSE MCP Server with OAuth" +description = "MCP server with SSE transport and OAuth" +path = "mcp/mcp-sse-oauth" +use_cases = ["MCP", "AI", "AI Agents"] +tags = ["axum", "mcp", "sse", "oauth"] + ## EXAMPLES ## From 9e0c254d9a1f793c9cb737306866ca92fb87f4c6 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 10 Sep 2025 15:42:05 +0200 Subject: [PATCH 221/239] chore: services cleanup, bumps (#226) * chore: remove shuttle-tide * chore: remove shuttle-thruster * bump salvo * bump warp * bump openai * bump opendal * bump libsql * chore: update all axum examples to 0.8, except axum/oath2 --- axum/htmx-crud/Cargo.toml | 12 ++++++------ axum/htmx-crud/src/router.rs | 2 +- axum/htmx-crud/src/templates.rs | 9 +++++---- axum/jwt-authentication/Cargo.toml | 11 +++++------ axum/jwt-authentication/src/main.rs | 2 -- axum/metadata/Cargo.toml | 4 ++-- axum/oauth2/Cargo.toml | 4 ++-- axum/openai/Cargo.toml | 10 +++++----- axum/openai/src/endpoints/auth.rs | 1 - axum/openai/src/main.rs | 5 ++--- axum/postgres/Cargo.toml | 8 ++++---- axum/postgres/src/main.rs | 2 +- axum/qdrant/Cargo.toml | 4 ++-- axum/turso/Cargo.toml | 6 +++--- bevy/hello-world/server/Cargo.toml | 6 +++--- bevy/hello-world/server/src/main.rs | 3 +-- custom-resource/pdo/Cargo.toml | 4 ++-- fullstack-templates/saas/backend/Cargo.toml | 16 ++++++++-------- fullstack-templates/saas/backend/src/main.rs | 3 +-- .../saas/backend/src/router.rs | 4 ++-- other/feature-flags/Cargo.toml | 4 ++-- other/standalone-binary/Cargo.toml | 4 ++-- rocket/opendal-memory/Cargo.toml | 2 +- rocket/url-shortener/Cargo.toml | 2 +- salvo/hello-world/Cargo.toml | 2 +- salvo/image-rescaler/Cargo.toml | 4 ++-- salvo/image-rescaler/src/main.rs | 2 +- templates.toml | 17 ----------------- thruster/hello-world/Cargo.toml | 10 ---------- thruster/hello-world/src/main.rs | 19 ------------------- tide/hello-world/Cargo.toml | 10 ---------- tide/hello-world/src/main.rs | 9 --------- warp/hello-world/Cargo.toml | 2 +- 33 files changed, 66 insertions(+), 137 deletions(-) delete mode 100644 thruster/hello-world/Cargo.toml delete mode 100644 thruster/hello-world/src/main.rs delete mode 100644 tide/hello-world/Cargo.toml delete mode 100644 tide/hello-world/src/main.rs diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index 9ddfbb13..f8ea4900 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -4,12 +4,12 @@ version = "0.1.0" edition = "2021" [dependencies] -askama = { version = "0.12.1", features = ["with-axum"] } -askama_axum = "0.4.0" -axum = "0.7.4" -serde = { version = "1.0.189", features = ["derive"] } -serde_json = "1.0.107" -shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +askama = "0.14" +askama_web = { version = "0.14", features = ["axum-0.8"] } +axum = "0.8" +serde = { version = "1", features = ["derive"] } +serde_json = "1" +shuttle-axum = "0.56.0" shuttle-runtime = "0.56.0" shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" diff --git a/axum/htmx-crud/src/router.rs b/axum/htmx-crud/src/router.rs index de84cb24..d2a4257b 100644 --- a/axum/htmx-crud/src/router.rs +++ b/axum/htmx-crud/src/router.rs @@ -23,7 +23,7 @@ pub fn init_router(db: PgPool) -> Router { .route("/stream", get(routes::stream)) .route("/styles.css", get(routes::styles)) .route("/todos", get(routes::fetch_todos).post(routes::create_todo)) - .route("/todos/:id", delete(routes::delete_todo)) + .route("/todos/{id}", delete(routes::delete_todo)) .route("/todos/stream", get(routes::handle_stream)) .with_state(state) .layer(Extension(tx)) diff --git a/axum/htmx-crud/src/templates.rs b/axum/htmx-crud/src/templates.rs index 71043986..b08b9460 100644 --- a/axum/htmx-crud/src/templates.rs +++ b/axum/htmx-crud/src/templates.rs @@ -1,21 +1,22 @@ use crate::models; use askama::Template; +use askama_web::WebTemplate; -#[derive(Template)] +#[derive(Template, WebTemplate)] #[template(path = "index.html")] pub struct HelloTemplate; -#[derive(Template)] +#[derive(Template, WebTemplate)] #[template(path = "stream.html")] pub struct StreamTemplate; -#[derive(Template)] +#[derive(Template, WebTemplate)] #[template(path = "todos.html")] pub struct Records { pub todos: Vec, } -#[derive(Template)] +#[derive(Template, WebTemplate)] #[template(path = "todo.html")] pub struct TodoNewTemplate { pub todo: models::Todo, diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index e50e38e0..532ba933 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -4,13 +4,12 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = "0.7.3" -axum-extra = { version = "0.9.1", features = ["typed-header"] } +axum = "0.8" +axum-extra = { version = "0.10", features = ["typed-header"] } jsonwebtoken = "8.3.0" once_cell = "1.18.0" -serde = { version = "1.0.188", features = ["derive"] } -serde_json = "1.0.107" -shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +serde = { version = "1", features = ["derive"] } +serde_json = "1" +shuttle-axum = "0.56.0" shuttle-runtime = "0.56.0" tokio = "1.28.2" -tracing-subscriber = "0.3.17" diff --git a/axum/jwt-authentication/src/main.rs b/axum/jwt-authentication/src/main.rs index 9413efc6..ad7effed 100644 --- a/axum/jwt-authentication/src/main.rs +++ b/axum/jwt-authentication/src/main.rs @@ -1,5 +1,4 @@ use axum::{ - async_trait, extract::FromRequestParts, http::{request::Parts, StatusCode}, response::{IntoResponse, Response}, @@ -95,7 +94,6 @@ impl AuthBody { // implement FromRequestParts for Claims (the JWT struct) // FromRequestParts allows us to use Claims without consuming the request -#[async_trait] impl FromRequestParts for Claims where S: Send + Sync, diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index 7e49e951..0a9383dc 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = "0.7.3" -shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +axum = "0.8" +shuttle-axum = "0.56.0" shuttle-runtime = "0.56.0" tokio = "1.28.2" diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index 817b46e3..36a3ed30 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -10,12 +10,12 @@ axum-extra = { version = "0.9.2", features = ["cookie-private"] } chrono = { version = "0.4.35", features = ["clock"] } oauth2 = "4.4.1" reqwest = { version = "0.11.18", features = ["json"] } -serde = { version = "1.0.183", features = ["derive"] } +serde = { version = "1", features = ["derive"] } shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } shuttle-runtime = "0.56.0" shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["macros", "chrono"] } -thiserror = "1.0.57" +thiserror = "2" time = "0.3.25" tokio = "1.28.2" tracing = "0.1.37" diff --git a/axum/openai/Cargo.toml b/axum/openai/Cargo.toml index fd6a92ae..bde9f37d 100644 --- a/axum/openai/Cargo.toml +++ b/axum/openai/Cargo.toml @@ -4,15 +4,15 @@ version = "0.1.0" edition = "2021" [dependencies] -async-openai = "0.28.0" +async-openai = "0.29" argon2 = "0.5.3" -axum = "0.7.4" -axum-extra = { version = "0.9.4", features = ["cookie", "cookie-private"] } +axum = "0.8" +axum-extra = { version = "0.10", features = ["cookie", "cookie-private"] } derive_more = { version = "1.0.0", features = ["full"] } jsonwebtoken = "9.3.0" serde = { version = "1.0.215", features = ["derive"] } -serde_json = "1.0.133" -shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +serde_json = "1" +shuttle-axum = "0.56.0" shuttle-openai = "0.56.0" shuttle-runtime = "0.56.0" shuttle-shared-db = { version = "0.56.0", features = ["postgres"] } diff --git a/axum/openai/src/endpoints/auth.rs b/axum/openai/src/endpoints/auth.rs index db39d9ce..9c3b4a30 100644 --- a/axum/openai/src/endpoints/auth.rs +++ b/axum/openai/src/endpoints/auth.rs @@ -105,7 +105,6 @@ pub struct Claims { exp: usize, } -#[axum::async_trait] impl FromRequestParts for Claims { type Rejection = (StatusCode, String); async fn from_request_parts( diff --git a/axum/openai/src/main.rs b/axum/openai/src/main.rs index 3812976b..87282463 100644 --- a/axum/openai/src/main.rs +++ b/axum/openai/src/main.rs @@ -52,14 +52,13 @@ async fn main( get(endpoints::openai::get_conversation_list), ) .route( - "/api/chat/conversations/:id", + "/api/chat/conversations/{id}", get(endpoints::openai::fetch_conversation_messages) .post(endpoints::openai::send_message), ) .route("/api/chat/create", post(endpoints::openai::create_chat)) .layer(cors) - .nest_service( - "/", + .fallback_service( ServeDir::new("frontend/dist") .not_found_service(ServeFile::new("frontend/dist/index.html")), ) diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 79f4e859..609e7222 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -4,10 +4,10 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = "0.7.3" -serde = { version = "1.0.188", features = ["derive"] } -shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +axum = "0.8" +serde = { version = "1", features = ["derive"] } +shuttle-axum = "0.56.0" shuttle-runtime = "0.56.0" shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } -sqlx = "0.8.2" +sqlx = "0.8" tokio = "1.28.2" diff --git a/axum/postgres/src/main.rs b/axum/postgres/src/main.rs index b13219fe..7ae68e0d 100644 --- a/axum/postgres/src/main.rs +++ b/axum/postgres/src/main.rs @@ -51,7 +51,7 @@ async fn main(#[shuttle_shared_db::Postgres] pool: PgPool) -> shuttle_axum::Shut let state = MyState { pool }; let router = Router::new() .route("/todos", post(add)) - .route("/todos/:id", get(retrieve)) + .route("/todos/{id}", get(retrieve)) .with_state(state); Ok(router.into()) diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index 45c1332f..b9fc9725 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -4,9 +4,9 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = "0.7.3" +axum = "0.8" qdrant-client = "1.10.1" -shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +shuttle-axum = "0.56.0" shuttle-qdrant = "0.56.0" shuttle-runtime = "0.56.0" tokio = "1.26.0" diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index 543f496a..e47fed3e 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -4,11 +4,11 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = "0.7.3" -shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +axum = "0.8" +shuttle-axum = "0.56.0" shuttle-runtime = "0.56.0" shuttle-turso = "0.56.0" -libsql = "0.6.0" +libsql = "0.9" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } serde_json = "1.0.99" diff --git a/bevy/hello-world/server/Cargo.toml b/bevy/hello-world/server/Cargo.toml index 89041337..5079a3ec 100644 --- a/bevy/hello-world/server/Cargo.toml +++ b/bevy/hello-world/server/Cargo.toml @@ -4,8 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = "0.7.4" -shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +axum = "0.8" +shuttle-axum = "0.56.0" shuttle-runtime = "0.56.0" tokio = "1.28.2" -tower-http = { version = "0.5.0", features = ["fs"] } +tower-http = { version = "0.6", features = ["fs"] } diff --git a/bevy/hello-world/server/src/main.rs b/bevy/hello-world/server/src/main.rs index 0c27e63b..f01fe67a 100644 --- a/bevy/hello-world/server/src/main.rs +++ b/bevy/hello-world/server/src/main.rs @@ -3,8 +3,7 @@ use tower_http::services::{ServeDir, ServeFile}; #[shuttle_runtime::main] async fn main() -> shuttle_axum::ShuttleAxum { - let router = Router::new().nest_service( - "/", + let router = Router::new().fallback_service( ServeDir::new("assets").not_found_service(ServeFile::new("assets/index.html")), ); Ok(router.into()) diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index d87b7011..d7108e60 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] async-trait = "0.1.56" -axum = "0.7.3" +axum = "0.8" serde = { version = "1", features = ["derive"] } shuttle-service = "0.56.0" -shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +shuttle-axum = "0.56.0" shuttle-runtime = "0.56.0" tokio = "1.28.2" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 96eb8f82..7e783284 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -6,21 +6,21 @@ publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -async-stripe = { version = "0.31.0", features = ["runtime-tokio-hyper"] } -axum = "0.7.3" -axum-extra = { version = "0.9.1", features = ["cookie-private"] } -axum-macros = "0.4.0" +async-stripe = { version = "0.41", features = ["runtime-tokio-hyper"] } +axum = "0.8" +axum-extra = { version = "0.10", features = ["cookie-private"] } +axum-macros = "0.5" bcrypt = "0.15.0" http = "1.0.0" lettre = "0.11.4" rand = "0.8.5" -reqwest = "0.11.16" +reqwest = "0.12" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +shuttle-axum = "0.56.0" shuttle-runtime = "0.56.0" shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" -tower = "0.4.13" -tower-http = { version = "0.5.0", features = ["cors", "fs"] } +tower = "0.5" +tower-http = { version = "0.6", features = ["cors", "fs"] } diff --git a/fullstack-templates/saas/backend/src/main.rs b/fullstack-templates/saas/backend/src/main.rs index afdd4613..ed14fceb 100644 --- a/fullstack-templates/saas/backend/src/main.rs +++ b/fullstack-templates/saas/backend/src/main.rs @@ -55,8 +55,7 @@ async fn main( let api_router = create_api_router(state); - let router = Router::new().nest("/api", api_router).nest_service( - "/", + let router = Router::new().nest("/api", api_router).fallback_service( ServeDir::new("dist").not_found_service(ServeFile::new("dist/index.html")), ); diff --git a/fullstack-templates/saas/backend/src/router.rs b/fullstack-templates/saas/backend/src/router.rs index 97043469..2e3eb99b 100644 --- a/fullstack-templates/saas/backend/src/router.rs +++ b/fullstack-templates/saas/backend/src/router.rs @@ -33,7 +33,7 @@ pub fn create_api_router(state: AppState) -> Router { .route("/", post(get_all_customers)) .route("/names", post(get_customer_names)) .route( - "/:id", + "/{id}", post(get_one_customer) .put(edit_customer) .delete(destroy_customer), @@ -43,7 +43,7 @@ pub fn create_api_router(state: AppState) -> Router { let deals_router = Router::new() .route("/", post(get_all_deals)) .route( - "/:id", + "/{id}", post(get_one_deal).put(edit_deal).delete(destroy_deal), ) .route("/create", post(create_deal)); diff --git a/other/feature-flags/Cargo.toml b/other/feature-flags/Cargo.toml index c7b73a5f..a7e9669e 100644 --- a/other/feature-flags/Cargo.toml +++ b/other/feature-flags/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" publish = false [dependencies] -axum = "0.7.3" -shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +axum = "0.8" +shuttle-axum = "0.56.0" shuttle-runtime = "0.56.0" [features] diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 1aeb613c..16791a8b 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -13,8 +13,8 @@ name = "standalone" path = "src/bin/standalone.rs" [dependencies] -axum = "0.7.3" +axum = "0.8" dotenvy = "0.15.7" -shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } +shuttle-axum = "0.56.0" shuttle-runtime = "0.56.0" tokio = "1.28.2" diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index 0900662b..4653d182 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -opendal = "0.51" +opendal = "0.54" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } shuttle-opendal = "0.56.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index 3d22f9f0..ff836145 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] nanoid = "0.4.0" -opendal = "0.51" +opendal = "0.54" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" shuttle-rocket = "0.56.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index b4c4393d..bd02b97d 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -salvo = "0.75.0" +salvo = "0.83" shuttle-salvo = "0.56.0" shuttle-runtime = "0.56.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml index 93633757..1654c406 100644 --- a/salvo/image-rescaler/Cargo.toml +++ b/salvo/image-rescaler/Cargo.toml @@ -4,8 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -image = "0.24.8" -salvo = "0.75.0" +image = "0.25" +salvo = "0.83" shuttle-salvo = "0.56.0" shuttle-runtime = "0.56.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/src/main.rs b/salvo/image-rescaler/src/main.rs index 3949b25a..b083ba64 100644 --- a/salvo/image-rescaler/src/main.rs +++ b/salvo/image-rescaler/src/main.rs @@ -15,7 +15,7 @@ async fn get_image(req: &mut Request, res: &mut Response) { let img = image::load_from_memory_with_format(IMAGE, image::ImageFormat::Png).unwrap(); let img = img.resize_exact(width, height, image::imageops::FilterType::Triangle); let mut buffer = std::io::BufWriter::new(std::io::Cursor::new(Vec::new())); - img.write_to(&mut buffer, image::ImageOutputFormat::Png) + img.write_to(&mut buffer, image::ImageFormat::Png) .unwrap(); let bytes = buffer.into_inner().unwrap().into_inner(); diff --git a/templates.toml b/templates.toml index 1256b3a1..0fa1179d 100644 --- a/templates.toml +++ b/templates.toml @@ -16,7 +16,6 @@ poise = "https://avatars.githubusercontent.com/u/32077193?v=4" rama = "https://avatars.githubusercontent.com/u/87996217?v=4" serenity = "https://avatars.githubusercontent.com/u/32077193?v=4" salvo = "https://avatars.githubusercontent.com/u/77909452?v=4" -tide = "https://avatars.githubusercontent.com/u/56456261?v=4" tower = "https://avatars.githubusercontent.com/u/26263939?v=4" postgres = "https://avatars.githubusercontent.com/u/177543?v=4" clerk = "https://avatars.githubusercontent.com/u/49538330?v=4" @@ -110,22 +109,6 @@ use_cases = ["Discord bot"] tags = ["serenity"] template = "serenity" -[starters.thruster-hello-world] -title = "Thruster" -description = "Web framework" -path = "thruster/hello-world" -use_cases = ["Web app"] -tags = ["thruster"] -template = "thruster" - -[starters.tide-hello-world] -title = "Tide" -description = "Web framework" -path = "tide/hello-world" -use_cases = ["Web app"] -tags = ["tide"] -template = "tide" - [starters.tower-hello-world] title = "Tower" description = "Modular service library" diff --git a/thruster/hello-world/Cargo.toml b/thruster/hello-world/Cargo.toml deleted file mode 100644 index 0e6f1c7d..00000000 --- a/thruster/hello-world/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "hello-world" -version = "0.1.0" -edition = "2021" - -[dependencies] -shuttle-thruster = "0.56.0" -shuttle-runtime = "0.56.0" -thruster = { version = "1.3.0", features = ["hyper_server"] } -tokio = "1.26.0" diff --git a/thruster/hello-world/src/main.rs b/thruster/hello-world/src/main.rs deleted file mode 100644 index a05ff16f..00000000 --- a/thruster/hello-world/src/main.rs +++ /dev/null @@ -1,19 +0,0 @@ -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) -> MiddlewareResult { - context.body("Hello, World!"); - Ok(context) -} - -#[shuttle_runtime::main] -async fn thruster() -> shuttle_thruster::ShuttleThruster> { - let server = HyperServer::new( - App::::create(generate_context, ()).get("/", m![hello]), - ); - - Ok(server.into()) -} diff --git a/tide/hello-world/Cargo.toml b/tide/hello-world/Cargo.toml deleted file mode 100644 index 9dd2fef3..00000000 --- a/tide/hello-world/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "hello-world" -version = "0.1.0" -edition = "2021" - -[dependencies] -shuttle-tide = "0.56.0" -shuttle-runtime = "0.56.0" -tokio = "1.26.0" -tide = "0.16.0" diff --git a/tide/hello-world/src/main.rs b/tide/hello-world/src/main.rs deleted file mode 100644 index c211b1f8..00000000 --- a/tide/hello-world/src/main.rs +++ /dev/null @@ -1,9 +0,0 @@ -#[shuttle_runtime::main] -async fn tide() -> shuttle_tide::ShuttleTide<()> { - let mut app = tide::new(); - app.with(tide::log::LogMiddleware::new()); - - app.at("/").get(|_| async { Ok("Hello, world!") }); - - Ok(app.into()) -} diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 28018fca..8852da12 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" shuttle-runtime = "0.56.0" shuttle-warp = "0.56.0" tokio = "1.26.0" -warp = "0.3.3" +warp = "0.4" From 75b663657cba87af6455f1e07bc4502bf968ef66 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 10 Sep 2025 16:03:53 +0200 Subject: [PATCH 222/239] fmt --- salvo/image-rescaler/src/main.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/salvo/image-rescaler/src/main.rs b/salvo/image-rescaler/src/main.rs index b083ba64..30b2c76a 100644 --- a/salvo/image-rescaler/src/main.rs +++ b/salvo/image-rescaler/src/main.rs @@ -15,8 +15,7 @@ async fn get_image(req: &mut Request, res: &mut Response) { let img = image::load_from_memory_with_format(IMAGE, image::ImageFormat::Png).unwrap(); let img = img.resize_exact(width, height, image::imageops::FilterType::Triangle); let mut buffer = std::io::BufWriter::new(std::io::Cursor::new(Vec::new())); - img.write_to(&mut buffer, image::ImageFormat::Png) - .unwrap(); + img.write_to(&mut buffer, image::ImageFormat::Png).unwrap(); let bytes = buffer.into_inner().unwrap().into_inner(); res.add_header("content-type", "image/png", true).unwrap(); From 0866919f5dc7b5e6318049addb364f434fdb457c Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Wed, 10 Sep 2025 16:23:54 +0200 Subject: [PATCH 223/239] chore: 0.57.0 --- actix-web/clerk/backend/Cargo.toml | 4 ++-- actix-web/cookie-authentication/Cargo.toml | 4 ++-- actix-web/hello-world/Cargo.toml | 4 ++-- actix-web/postgres/Cargo.toml | 6 +++--- actix-web/static-files/Cargo.toml | 4 ++-- actix-web/websocket-actorless/Cargo.toml | 4 ++-- axum/ai-assisted/Cargo.toml | 4 ++-- axum/hello-world/Cargo.toml | 4 ++-- axum/htmx-crud/Cargo.toml | 6 +++--- axum/jwt-authentication/Cargo.toml | 4 ++-- axum/metadata/Cargo.toml | 4 ++-- axum/oauth2/Cargo.toml | 6 +++--- axum/openai/Cargo.toml | 8 ++++---- axum/postgres/Cargo.toml | 6 +++--- axum/qdrant/Cargo.toml | 6 +++--- axum/static-files/Cargo.toml | 4 ++-- axum/todo-list/Cargo.toml | 6 +++--- axum/turso/Cargo.toml | 6 +++--- axum/websocket/Cargo.toml | 4 ++-- bevy/hello-world/server/Cargo.toml | 4 ++-- custom-resource/pdo/Cargo.toml | 6 +++--- custom-service/none/Cargo.toml | 2 +- fullstack-templates/saas/backend/Cargo.toml | 6 +++--- loco/hello-world/Cargo.toml | 4 ++-- mcp/mcp-sse/Cargo.toml | 2 +- other/feature-flags/Cargo.toml | 4 ++-- other/standalone-binary/Cargo.toml | 4 ++-- poem/hello-world/Cargo.toml | 4 ++-- poise/hello-world/Cargo.toml | 4 ++-- rama/hello-world-tcp/Cargo.toml | 4 ++-- rama/hello-world/Cargo.toml | 4 ++-- rama/static-files/Cargo.toml | 4 ++-- rocket/dyn-templates/Cargo.toml | 4 ++-- rocket/hello-world/Cargo.toml | 4 ++-- rocket/jwt-authentication/Cargo.toml | 4 ++-- rocket/opendal-memory/Cargo.toml | 6 +++--- rocket/postgres/Cargo.toml | 6 +++--- rocket/secrets/Cargo.toml | 4 ++-- rocket/static-files/Cargo.toml | 4 ++-- rocket/url-shortener/Cargo.toml | 6 +++--- rocket/workspace/hello-world/Cargo.toml | 4 ++-- salvo/hello-world/Cargo.toml | 4 ++-- salvo/image-rescaler/Cargo.toml | 4 ++-- serenity/hello-world/Cargo.toml | 4 ++-- serenity/postgres/Cargo.toml | 6 +++--- serenity/weather-forecast/Cargo.toml | 4 ++-- shuttle-cron/Cargo.toml | 4 ++-- tower/hello-world/Cargo.toml | 4 ++-- tracing/custom-tracing-subscriber/Cargo.toml | 4 ++-- warp/hello-world/Cargo.toml | 4 ++-- 50 files changed, 113 insertions(+), 113 deletions(-) diff --git a/actix-web/clerk/backend/Cargo.toml b/actix-web/clerk/backend/Cargo.toml index 18fbc21a..0b45e72e 100644 --- a/actix-web/clerk/backend/Cargo.toml +++ b/actix-web/clerk/backend/Cargo.toml @@ -10,5 +10,5 @@ clerk-rs = "0.2.3" openssl-sys = { version = "0.9.9", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-actix-web = "0.57.0" +shuttle-runtime = "0.57.0" diff --git a/actix-web/cookie-authentication/Cargo.toml b/actix-web/cookie-authentication/Cargo.toml index 298143b8..373a8104 100644 --- a/actix-web/cookie-authentication/Cargo.toml +++ b/actix-web/cookie-authentication/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" actix-identity = "0.7.1" actix-session = { version = "0.9.0", features = ["cookie-session"] } actix-web = "4.3.1" -shuttle-actix-web = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-actix-web = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.26.0" diff --git a/actix-web/hello-world/Cargo.toml b/actix-web/hello-world/Cargo.toml index 0deef4be..78b6d34d 100644 --- a/actix-web/hello-world/Cargo.toml +++ b/actix-web/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-actix-web = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.26.0" diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 1d77e68e..16734499 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-actix-web = "0.57.0" +shuttle-runtime = "0.57.0" serde = "1.0.148" -shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } +shuttle-shared-db = { version = "0.57.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/actix-web/static-files/Cargo.toml b/actix-web/static-files/Cargo.toml index 87c9c678..03201ec0 100644 --- a/actix-web/static-files/Cargo.toml +++ b/actix-web/static-files/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] actix-files = "0.6.2" actix-web = "4.3.1" -shuttle-actix-web = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-actix-web = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.26.0" diff --git a/actix-web/websocket-actorless/Cargo.toml b/actix-web/websocket-actorless/Cargo.toml index 9a2b4992..24ebb743 100644 --- a/actix-web/websocket-actorless/Cargo.toml +++ b/actix-web/websocket-actorless/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" reqwest = "0.11" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -shuttle-actix-web = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-actix-web = "0.57.0" +shuttle-runtime = "0.57.0" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tracing = "0.1" diff --git a/axum/ai-assisted/Cargo.toml b/axum/ai-assisted/Cargo.toml index 6826d49f..518c7ffa 100644 --- a/axum/ai-assisted/Cargo.toml +++ b/axum/ai-assisted/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.8" -shuttle-axum = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-axum = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.46" diff --git a/axum/hello-world/Cargo.toml b/axum/hello-world/Cargo.toml index 7d5403d1..ccd3bd9d 100644 --- a/axum/hello-world/Cargo.toml +++ b/axum/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.8" -shuttle-axum = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-axum = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.28.2" diff --git a/axum/htmx-crud/Cargo.toml b/axum/htmx-crud/Cargo.toml index f8ea4900..cfb3e05b 100644 --- a/axum/htmx-crud/Cargo.toml +++ b/axum/htmx-crud/Cargo.toml @@ -9,9 +9,9 @@ askama_web = { version = "0.14", features = ["axum-0.8"] } axum = "0.8" serde = { version = "1", features = ["derive"] } serde_json = "1" -shuttle-axum = "0.56.0" -shuttle-runtime = "0.56.0" -shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.57.0" +shuttle-runtime = "0.57.0" +shuttle-shared-db = { version = "0.57.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.28.2" tokio-stream = { version = "0.1.14", features = ["sync"] } diff --git a/axum/jwt-authentication/Cargo.toml b/axum/jwt-authentication/Cargo.toml index 532ba933..a823df2c 100644 --- a/axum/jwt-authentication/Cargo.toml +++ b/axum/jwt-authentication/Cargo.toml @@ -10,6 +10,6 @@ jsonwebtoken = "8.3.0" once_cell = "1.18.0" serde = { version = "1", features = ["derive"] } serde_json = "1" -shuttle-axum = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-axum = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.28.2" diff --git a/axum/metadata/Cargo.toml b/axum/metadata/Cargo.toml index 0a9383dc..22db1d42 100644 --- a/axum/metadata/Cargo.toml +++ b/axum/metadata/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = "0.8" -shuttle-axum = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-axum = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.28.2" diff --git a/axum/oauth2/Cargo.toml b/axum/oauth2/Cargo.toml index 36a3ed30..4528210a 100644 --- a/axum/oauth2/Cargo.toml +++ b/axum/oauth2/Cargo.toml @@ -11,9 +11,9 @@ chrono = { version = "0.4.35", features = ["clock"] } oauth2 = "4.4.1" reqwest = { version = "0.11.18", features = ["json"] } serde = { version = "1", features = ["derive"] } -shuttle-axum = { version = "0.56.0", default-features = false, features = ["axum-0-7"] } -shuttle-runtime = "0.56.0" -shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } +shuttle-axum = { version = "0.57.0", default-features = false, features = ["axum-0-7"] } +shuttle-runtime = "0.57.0" +shuttle-shared-db = { version = "0.57.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["macros", "chrono"] } thiserror = "2" time = "0.3.25" diff --git a/axum/openai/Cargo.toml b/axum/openai/Cargo.toml index bde9f37d..d58da3e2 100644 --- a/axum/openai/Cargo.toml +++ b/axum/openai/Cargo.toml @@ -12,10 +12,10 @@ derive_more = { version = "1.0.0", features = ["full"] } jsonwebtoken = "9.3.0" serde = { version = "1.0.215", features = ["derive"] } serde_json = "1" -shuttle-axum = "0.56.0" -shuttle-openai = "0.56.0" -shuttle-runtime = "0.56.0" -shuttle-shared-db = { version = "0.56.0", features = ["postgres"] } +shuttle-axum = "0.57.0" +shuttle-openai = "0.57.0" +shuttle-runtime = "0.57.0" +shuttle-shared-db = { version = "0.57.0", features = ["postgres"] } sqlx = { version = "0.8.2", features = [ "runtime-tokio-rustls", "postgres", diff --git a/axum/postgres/Cargo.toml b/axum/postgres/Cargo.toml index 609e7222..2535cf97 100644 --- a/axum/postgres/Cargo.toml +++ b/axum/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] axum = "0.8" serde = { version = "1", features = ["derive"] } -shuttle-axum = "0.56.0" -shuttle-runtime = "0.56.0" -shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.57.0" +shuttle-runtime = "0.57.0" +shuttle-shared-db = { version = "0.57.0", features = ["postgres", "sqlx"] } sqlx = "0.8" tokio = "1.28.2" diff --git a/axum/qdrant/Cargo.toml b/axum/qdrant/Cargo.toml index b9fc9725..3b1cfb7f 100644 --- a/axum/qdrant/Cargo.toml +++ b/axum/qdrant/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] axum = "0.8" qdrant-client = "1.10.1" -shuttle-axum = "0.56.0" -shuttle-qdrant = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-axum = "0.57.0" +shuttle-qdrant = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.26.0" diff --git a/axum/static-files/Cargo.toml b/axum/static-files/Cargo.toml index bac9ba36..80d54b55 100644 --- a/axum/static-files/Cargo.toml +++ b/axum/static-files/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] axum = "0.8" -shuttle-axum = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-axum = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.28.2" tower-http = { version = "0.6", features = ["fs"] } diff --git a/axum/todo-list/Cargo.toml b/axum/todo-list/Cargo.toml index b3b4a49c..af78cb99 100644 --- a/axum/todo-list/Cargo.toml +++ b/axum/todo-list/Cargo.toml @@ -6,9 +6,9 @@ edition = "2024" [dependencies] axum = "0.8" serde = { version = "1", features = ["derive"] } -shuttle-axum = "0.56.0" -shuttle-runtime = "0.56.0" -shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.57.0" +shuttle-runtime = "0.57.0" +shuttle-shared-db = { version = "0.57.0", features = ["postgres", "sqlx"] } sqlx = "0.8" tokio = "1" tower-http = { version = "0.6", features = ["fs", "trace"] } diff --git a/axum/turso/Cargo.toml b/axum/turso/Cargo.toml index e47fed3e..4aafa2d1 100644 --- a/axum/turso/Cargo.toml +++ b/axum/turso/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] axum = "0.8" -shuttle-axum = "0.56.0" -shuttle-runtime = "0.56.0" -shuttle-turso = "0.56.0" +shuttle-axum = "0.57.0" +shuttle-runtime = "0.57.0" +shuttle-turso = "0.57.0" libsql = "0.9" tokio = "1.26.0" serde = { version = "1.0.164", features = ["derive"] } diff --git a/axum/websocket/Cargo.toml b/axum/websocket/Cargo.toml index 96294aa8..0e1ea112 100644 --- a/axum/websocket/Cargo.toml +++ b/axum/websocket/Cargo.toml @@ -10,7 +10,7 @@ futures = "0.3.28" reqwest = "0.12" serde = { version = "1", features = ["derive"] } serde_json = "1" -shuttle-axum = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-axum = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1" tower-http = { version = "0.6", features = ["fs"] } diff --git a/bevy/hello-world/server/Cargo.toml b/bevy/hello-world/server/Cargo.toml index 5079a3ec..6a34d2bd 100644 --- a/bevy/hello-world/server/Cargo.toml +++ b/bevy/hello-world/server/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] axum = "0.8" -shuttle-axum = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-axum = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.28.2" tower-http = { version = "0.6", features = ["fs"] } diff --git a/custom-resource/pdo/Cargo.toml b/custom-resource/pdo/Cargo.toml index d7108e60..2c3bffd1 100644 --- a/custom-resource/pdo/Cargo.toml +++ b/custom-resource/pdo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" async-trait = "0.1.56" axum = "0.8" serde = { version = "1", features = ["derive"] } -shuttle-service = "0.56.0" -shuttle-axum = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-service = "0.57.0" +shuttle-axum = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.28.2" diff --git a/custom-service/none/Cargo.toml b/custom-service/none/Cargo.toml index d303c5fb..59573cb3 100644 --- a/custom-service/none/Cargo.toml +++ b/custom-service/none/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.56.0" +shuttle-runtime = "0.57.0" tokio = "1" diff --git a/fullstack-templates/saas/backend/Cargo.toml b/fullstack-templates/saas/backend/Cargo.toml index 7e783284..67396ba2 100644 --- a/fullstack-templates/saas/backend/Cargo.toml +++ b/fullstack-templates/saas/backend/Cargo.toml @@ -16,9 +16,9 @@ lettre = "0.11.4" rand = "0.8.5" reqwest = "0.12" serde = { version = "1.0.160", features = ["derive"] } -shuttle-axum = "0.56.0" -shuttle-runtime = "0.56.0" -shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } +shuttle-axum = "0.57.0" +shuttle-runtime = "0.57.0" +shuttle-shared-db = { version = "0.57.0", features = ["postgres", "sqlx"] } sqlx = { version = "0.8.2", features = ["time"] } time = { version = "0.3.20", features = ["serde"] } tokio = "1.27.0" diff --git a/loco/hello-world/Cargo.toml b/loco/hello-world/Cargo.toml index f69875df..f994eb56 100644 --- a/loco/hello-world/Cargo.toml +++ b/loco/hello-world/Cargo.toml @@ -13,8 +13,8 @@ default-run = "hello_world-cli" loco-rs = { version = "0.16.0", default-features = false } [dependencies] -shuttle-axum = "0.56.0" -shuttle-runtime = { version = "0.56.0", default-features = false } +shuttle-axum = "0.57.0" +shuttle-runtime = { version = "0.57.0", default-features = false } loco-rs = { workspace = true , features = ["cli"] } serde = { version = "1", features = ["derive"] } diff --git a/mcp/mcp-sse/Cargo.toml b/mcp/mcp-sse/Cargo.toml index 955f44ed..28b1d9a4 100644 --- a/mcp/mcp-sse/Cargo.toml +++ b/mcp/mcp-sse/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" publish = false [dependencies] -shuttle-runtime = "0.56.0" +shuttle-runtime = "0.57.0" tokio = { version = "1", features = ["macros", "rt-multi-thread", "signal"] } rmcp = { version = "0.3", features = ["server", "transport-sse-server"] } axum = "0.8" diff --git a/other/feature-flags/Cargo.toml b/other/feature-flags/Cargo.toml index a7e9669e..508fea0d 100644 --- a/other/feature-flags/Cargo.toml +++ b/other/feature-flags/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] axum = "0.8" -shuttle-axum = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-axum = "0.57.0" +shuttle-runtime = "0.57.0" [features] # Shuttle will disable default features and enable the feature "shuttle" if it exists. diff --git a/other/standalone-binary/Cargo.toml b/other/standalone-binary/Cargo.toml index 16791a8b..5b20014b 100644 --- a/other/standalone-binary/Cargo.toml +++ b/other/standalone-binary/Cargo.toml @@ -15,6 +15,6 @@ path = "src/bin/standalone.rs" [dependencies] axum = "0.8" dotenvy = "0.15.7" -shuttle-axum = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-axum = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.28.2" diff --git a/poem/hello-world/Cargo.toml b/poem/hello-world/Cargo.toml index c6e21cab..e7691c20 100644 --- a/poem/hello-world/Cargo.toml +++ b/poem/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] poem = "3.0.0" -shuttle-poem = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-poem = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.26.0" diff --git a/poise/hello-world/Cargo.toml b/poise/hello-world/Cargo.toml index 12454b2d..bda5d7ca 100644 --- a/poise/hello-world/Cargo.toml +++ b/poise/hello-world/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] anyhow = "1.0.68" poise = "0.6.1" -shuttle-runtime = "0.56.0" +shuttle-runtime = "0.57.0" # Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity -shuttle-serenity = "0.56.0" +shuttle-serenity = "0.57.0" tracing = "0.1.37" tokio = "1.26.0" diff --git a/rama/hello-world-tcp/Cargo.toml b/rama/hello-world-tcp/Cargo.toml index bbafab91..c535bda5 100644 --- a/rama/hello-world-tcp/Cargo.toml +++ b/rama/hello-world-tcp/Cargo.toml @@ -5,6 +5,6 @@ edition = "2024" [dependencies] rama = "0.2" -shuttle-rama = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-rama = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.45" diff --git a/rama/hello-world/Cargo.toml b/rama/hello-world/Cargo.toml index d366ecb8..e3515a66 100644 --- a/rama/hello-world/Cargo.toml +++ b/rama/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2024" [dependencies] rama = { version = "0.2", features = ["http"] } -shuttle-rama = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-rama = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.45" diff --git a/rama/static-files/Cargo.toml b/rama/static-files/Cargo.toml index 202894b0..6cf719e2 100644 --- a/rama/static-files/Cargo.toml +++ b/rama/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2024" [dependencies] rama = "0.2" -shuttle-rama = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-rama = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.45" diff --git a/rocket/dyn-templates/Cargo.toml b/rocket/dyn-templates/Cargo.toml index 9dcd6b32..8db24685 100644 --- a/rocket/dyn-templates/Cargo.toml +++ b/rocket/dyn-templates/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" rocket_dyn_templates = { version = "0.1.0", features = ["handlebars"] } -shuttle-rocket = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-rocket = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.26.0" diff --git a/rocket/hello-world/Cargo.toml b/rocket/hello-world/Cargo.toml index 75a532dd..752bfec7 100644 --- a/rocket/hello-world/Cargo.toml +++ b/rocket/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-rocket = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.26.0" diff --git a/rocket/jwt-authentication/Cargo.toml b/rocket/jwt-authentication/Cargo.toml index 83970d22..8799bf91 100644 --- a/rocket/jwt-authentication/Cargo.toml +++ b/rocket/jwt-authentication/Cargo.toml @@ -9,6 +9,6 @@ jsonwebtoken = { version = "8.1.1", default-features = false } lazy_static = "1.4.0" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-rocket = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-rocket = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.26.0" diff --git a/rocket/opendal-memory/Cargo.toml b/rocket/opendal-memory/Cargo.toml index 4653d182..93fc2fe0 100644 --- a/rocket/opendal-memory/Cargo.toml +++ b/rocket/opendal-memory/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" opendal = "0.54" rocket = { version = "0.5.0", features = ["json"] } serde = { version = "1.0.148", features = ["derive"] } -shuttle-opendal = "0.56.0" -shuttle-rocket = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-opendal = "0.57.0" +shuttle-rocket = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.26.0" diff --git a/rocket/postgres/Cargo.toml b/rocket/postgres/Cargo.toml index 36c6c8cd..b21022f8 100644 --- a/rocket/postgres/Cargo.toml +++ b/rocket/postgres/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.56.0" -shuttle-runtime = "0.56.0" -shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } +shuttle-rocket = "0.57.0" +shuttle-runtime = "0.57.0" +shuttle-shared-db = { version = "0.57.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/rocket/secrets/Cargo.toml b/rocket/secrets/Cargo.toml index 1e82b25b..69f01d77 100644 --- a/rocket/secrets/Cargo.toml +++ b/rocket/secrets/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] anyhow = "1.0.66" rocket = "0.5.0" -shuttle-rocket = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-rocket = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.26.0" diff --git a/rocket/static-files/Cargo.toml b/rocket/static-files/Cargo.toml index 5ef197a4..db0d1a35 100644 --- a/rocket/static-files/Cargo.toml +++ b/rocket/static-files/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" -shuttle-rocket = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-rocket = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.26.0" diff --git a/rocket/url-shortener/Cargo.toml b/rocket/url-shortener/Cargo.toml index ff836145..f80aaf0e 100644 --- a/rocket/url-shortener/Cargo.toml +++ b/rocket/url-shortener/Cargo.toml @@ -8,8 +8,8 @@ nanoid = "0.4.0" opendal = "0.54" rocket = { version = "0.5.0", features = ["json"] } serde = "1.0.148" -shuttle-rocket = "0.56.0" -shuttle-runtime = "0.56.0" -shuttle-shared-db = { version = "0.56.0", features = ["opendal-postgres"] } +shuttle-rocket = "0.57.0" +shuttle-runtime = "0.57.0" +shuttle-shared-db = { version = "0.57.0", features = ["opendal-postgres"] } tokio = "1.26.0" url = "2.5.4" diff --git a/rocket/workspace/hello-world/Cargo.toml b/rocket/workspace/hello-world/Cargo.toml index aa0ef458..3dbf7761 100644 --- a/rocket/workspace/hello-world/Cargo.toml +++ b/rocket/workspace/hello-world/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] rocket = "0.5.0" shared = { path = "../shared", version = "0.1.0" } -shuttle-rocket = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-rocket = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.26.0" diff --git a/salvo/hello-world/Cargo.toml b/salvo/hello-world/Cargo.toml index bd02b97d..13836f07 100644 --- a/salvo/hello-world/Cargo.toml +++ b/salvo/hello-world/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] salvo = "0.83" -shuttle-salvo = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-salvo = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.26.0" diff --git a/salvo/image-rescaler/Cargo.toml b/salvo/image-rescaler/Cargo.toml index 1654c406..8af8a8ff 100644 --- a/salvo/image-rescaler/Cargo.toml +++ b/salvo/image-rescaler/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] image = "0.25" salvo = "0.83" -shuttle-salvo = "0.56.0" -shuttle-runtime = "0.56.0" +shuttle-salvo = "0.57.0" +shuttle-runtime = "0.57.0" tokio = "1.26.0" diff --git a/serenity/hello-world/Cargo.toml b/serenity/hello-world/Cargo.toml index b6367810..16a5f204 100644 --- a/serenity/hello-world/Cargo.toml +++ b/serenity/hello-world/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] anyhow = "1.0.66" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.56.0" -shuttle-serenity = "0.56.0" +shuttle-runtime = "0.57.0" +shuttle-serenity = "0.57.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/postgres/Cargo.toml b/serenity/postgres/Cargo.toml index 80bc410c..eb35b55b 100644 --- a/serenity/postgres/Cargo.toml +++ b/serenity/postgres/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" anyhow = "1.0.66" serde = "1.0.148" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.56.0" -shuttle-serenity = "0.56.0" -shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } +shuttle-runtime = "0.57.0" +shuttle-serenity = "0.57.0" +shuttle-shared-db = { version = "0.57.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" tracing = "0.1.37" diff --git a/serenity/weather-forecast/Cargo.toml b/serenity/weather-forecast/Cargo.toml index 187e6464..915560b7 100644 --- a/serenity/weather-forecast/Cargo.toml +++ b/serenity/weather-forecast/Cargo.toml @@ -8,7 +8,7 @@ anyhow = "1.0.66" reqwest = { version = "0.11.24", features = ["json"] } serde = "1.0.197" serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] } -shuttle-runtime = "0.56.0" -shuttle-serenity = "0.56.0" +shuttle-runtime = "0.57.0" +shuttle-serenity = "0.57.0" tokio = "1.26.0" tracing = "0.1.37" diff --git a/shuttle-cron/Cargo.toml b/shuttle-cron/Cargo.toml index dd8d4135..6a7abf46 100644 --- a/shuttle-cron/Cargo.toml +++ b/shuttle-cron/Cargo.toml @@ -10,7 +10,7 @@ apalis-sql = { version = "0.6", features = ["postgres"] } apalis-cron = { version = "0.6" } chrono = { version = "0.4.32", features = ["clock", "serde"] } serde = { version = "1.0.195", features = ["derive"] } -shuttle-runtime = "0.56.0" -shuttle-shared-db = { version = "0.56.0", features = ["postgres"] } +shuttle-runtime = "0.57.0" +shuttle-shared-db = { version = "0.57.0", features = ["postgres"] } sqlx = { version = "0.8", features = ["runtime-tokio-native-tls", "postgres"] } tokio = "1" diff --git a/tower/hello-world/Cargo.toml b/tower/hello-world/Cargo.toml index 515a2f3e..2a77d0ee 100644 --- a/tower/hello-world/Cargo.toml +++ b/tower/hello-world/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] hyper = { version = "0.14.23", features = ["full"] } -shuttle-runtime = "0.56.0" -shuttle-tower = "0.56.0" +shuttle-runtime = "0.57.0" +shuttle-tower = "0.57.0" tower = { version = "0.4.13", features = ["full"] } tokio = "1.26.0" diff --git a/tracing/custom-tracing-subscriber/Cargo.toml b/tracing/custom-tracing-subscriber/Cargo.toml index 7417858f..da1880b2 100644 --- a/tracing/custom-tracing-subscriber/Cargo.toml +++ b/tracing/custom-tracing-subscriber/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" -shuttle-actix-web = "0.56.0" +shuttle-actix-web = "0.57.0" # disable default features to disable the Shuttle default tracing subscriber -shuttle-runtime = { version = "0.56.0", default-features = false } +shuttle-runtime = { version = "0.57.0", default-features = false } tokio = "1.26.0" tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } diff --git a/warp/hello-world/Cargo.toml b/warp/hello-world/Cargo.toml index 8852da12..ce1096f8 100644 --- a/warp/hello-world/Cargo.toml +++ b/warp/hello-world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -shuttle-runtime = "0.56.0" -shuttle-warp = "0.56.0" +shuttle-runtime = "0.57.0" +shuttle-warp = "0.57.0" tokio = "1.26.0" warp = "0.4" From 6afd79e4163b23dae78fdc296fa577685ddb27f7 Mon Sep 17 00:00:00 2001 From: dcodes <101001810+dcodesdev@users.noreply.github.com> Date: Thu, 11 Sep 2025 13:32:07 +0300 Subject: [PATCH 224/239] New Axum Template (#228) --- ...8a2bdbaeabbe137a871e26741a419a1aa5b19.json | 14 + ...b4344bf1be2f4189b908907e68d238ed8e4f2.json | 40 ++ ...7b0bc19b9bdb0044a51c5202635555b3fdacd.json | 42 ++ ...108e8cc464e7bcb7911a2a0691ff618d51dee.json | 38 ++ ...a9b8cecd5d286967c80638aee2a91d7dc51d0.json | 40 ++ axum/todo-app/Cargo.toml | 27 + axum/todo-app/README.md | 30 + axum/todo-app/Shuttle.toml | 2 + .../20250812165323_create_todos_table.sql | 6 + axum/todo-app/src/database/mod.rs | 3 + axum/todo-app/src/database/repository.rs | 110 ++++ axum/todo-app/src/handlers/error.rs | 55 ++ axum/todo-app/src/handlers/mod.rs | 5 + axum/todo-app/src/handlers/todo.rs | 66 +++ axum/todo-app/src/main.rs | 42 ++ axum/todo-app/src/models/mod.rs | 3 + axum/todo-app/src/models/todo.rs | 47 ++ axum/todo-app/static/index.html | 38 ++ axum/todo-app/static/script.js | 268 +++++++++ axum/todo-app/static/style.css | 552 ++++++++++++++++++ templates.toml | 7 + 21 files changed, 1435 insertions(+) create mode 100644 axum/todo-app/.sqlx/query-183ad1d8316ef2ae5ac6ae4811b8a2bdbaeabbe137a871e26741a419a1aa5b19.json create mode 100644 axum/todo-app/.sqlx/query-25f558e700c67653fdb0a007ef1b4344bf1be2f4189b908907e68d238ed8e4f2.json create mode 100644 axum/todo-app/.sqlx/query-315a9ab6a895eb49f994f8264f87b0bc19b9bdb0044a51c5202635555b3fdacd.json create mode 100644 axum/todo-app/.sqlx/query-520950e2ddac5599f054db1ea66108e8cc464e7bcb7911a2a0691ff618d51dee.json create mode 100644 axum/todo-app/.sqlx/query-f0d6eaf1d0bba6c056d3efb8eeba9b8cecd5d286967c80638aee2a91d7dc51d0.json create mode 100644 axum/todo-app/Cargo.toml create mode 100644 axum/todo-app/README.md create mode 100644 axum/todo-app/Shuttle.toml create mode 100644 axum/todo-app/migrations/20250812165323_create_todos_table.sql create mode 100644 axum/todo-app/src/database/mod.rs create mode 100644 axum/todo-app/src/database/repository.rs create mode 100644 axum/todo-app/src/handlers/error.rs create mode 100644 axum/todo-app/src/handlers/mod.rs create mode 100644 axum/todo-app/src/handlers/todo.rs create mode 100644 axum/todo-app/src/main.rs create mode 100644 axum/todo-app/src/models/mod.rs create mode 100644 axum/todo-app/src/models/todo.rs create mode 100644 axum/todo-app/static/index.html create mode 100644 axum/todo-app/static/script.js create mode 100644 axum/todo-app/static/style.css diff --git a/axum/todo-app/.sqlx/query-183ad1d8316ef2ae5ac6ae4811b8a2bdbaeabbe137a871e26741a419a1aa5b19.json b/axum/todo-app/.sqlx/query-183ad1d8316ef2ae5ac6ae4811b8a2bdbaeabbe137a871e26741a419a1aa5b19.json new file mode 100644 index 00000000..dcc01f60 --- /dev/null +++ b/axum/todo-app/.sqlx/query-183ad1d8316ef2ae5ac6ae4811b8a2bdbaeabbe137a871e26741a419a1aa5b19.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM todos WHERE id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int4" + ] + }, + "nullable": [] + }, + "hash": "183ad1d8316ef2ae5ac6ae4811b8a2bdbaeabbe137a871e26741a419a1aa5b19" +} diff --git a/axum/todo-app/.sqlx/query-25f558e700c67653fdb0a007ef1b4344bf1be2f4189b908907e68d238ed8e4f2.json b/axum/todo-app/.sqlx/query-25f558e700c67653fdb0a007ef1b4344bf1be2f4189b908907e68d238ed8e4f2.json new file mode 100644 index 00000000..b06c210d --- /dev/null +++ b/axum/todo-app/.sqlx/query-25f558e700c67653fdb0a007ef1b4344bf1be2f4189b908907e68d238ed8e4f2.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO todos (title) VALUES ($1) RETURNING id, title, completed, created_at", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "title", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "completed", + "type_info": "Bool" + }, + { + "ordinal": 3, + "name": "created_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Varchar" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "25f558e700c67653fdb0a007ef1b4344bf1be2f4189b908907e68d238ed8e4f2" +} diff --git a/axum/todo-app/.sqlx/query-315a9ab6a895eb49f994f8264f87b0bc19b9bdb0044a51c5202635555b3fdacd.json b/axum/todo-app/.sqlx/query-315a9ab6a895eb49f994f8264f87b0bc19b9bdb0044a51c5202635555b3fdacd.json new file mode 100644 index 00000000..2e8811c7 --- /dev/null +++ b/axum/todo-app/.sqlx/query-315a9ab6a895eb49f994f8264f87b0bc19b9bdb0044a51c5202635555b3fdacd.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE todos SET title = $1, completed = $2 WHERE id = $3 RETURNING id, title, completed, created_at", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "title", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "completed", + "type_info": "Bool" + }, + { + "ordinal": 3, + "name": "created_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Varchar", + "Bool", + "Int4" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "315a9ab6a895eb49f994f8264f87b0bc19b9bdb0044a51c5202635555b3fdacd" +} diff --git a/axum/todo-app/.sqlx/query-520950e2ddac5599f054db1ea66108e8cc464e7bcb7911a2a0691ff618d51dee.json b/axum/todo-app/.sqlx/query-520950e2ddac5599f054db1ea66108e8cc464e7bcb7911a2a0691ff618d51dee.json new file mode 100644 index 00000000..2e4809a8 --- /dev/null +++ b/axum/todo-app/.sqlx/query-520950e2ddac5599f054db1ea66108e8cc464e7bcb7911a2a0691ff618d51dee.json @@ -0,0 +1,38 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT id, title, completed, created_at FROM todos ORDER BY created_at DESC", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "title", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "completed", + "type_info": "Bool" + }, + { + "ordinal": 3, + "name": "created_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "520950e2ddac5599f054db1ea66108e8cc464e7bcb7911a2a0691ff618d51dee" +} diff --git a/axum/todo-app/.sqlx/query-f0d6eaf1d0bba6c056d3efb8eeba9b8cecd5d286967c80638aee2a91d7dc51d0.json b/axum/todo-app/.sqlx/query-f0d6eaf1d0bba6c056d3efb8eeba9b8cecd5d286967c80638aee2a91d7dc51d0.json new file mode 100644 index 00000000..d71948af --- /dev/null +++ b/axum/todo-app/.sqlx/query-f0d6eaf1d0bba6c056d3efb8eeba9b8cecd5d286967c80638aee2a91d7dc51d0.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT id, title, completed, created_at FROM todos WHERE id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "title", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "completed", + "type_info": "Bool" + }, + { + "ordinal": 3, + "name": "created_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Int4" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "f0d6eaf1d0bba6c056d3efb8eeba9b8cecd5d286967c80638aee2a91d7dc51d0" +} diff --git a/axum/todo-app/Cargo.toml b/axum/todo-app/Cargo.toml new file mode 100644 index 00000000..53236eb4 --- /dev/null +++ b/axum/todo-app/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "todo-app-rust" +version = "0.1.0" +edition = "2024" + +[dependencies] +tokio = { version = "1.0", features = ["full"] } +axum = "0.8" +tower = "0.5" +tower-http = { version = "0.6", features = ["cors", "fs"] } +sqlx = { version = "0.8", features = [ + "runtime-tokio-rustls", + "postgres", + "chrono", + "uuid", +] } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +chrono = { version = "0.4", features = ["serde"] } +uuid = { version = "1.0", features = ["v4", "serde"] } +tracing = "0.1" +dotenvy = "0.15" +anyhow = "1.0" +thiserror = "2.0" +shuttle-runtime = "0.56.0" +shuttle-axum = "0.56.0" +shuttle-shared-db = { version = "0.56.0", features = ["postgres", "sqlx"] } diff --git a/axum/todo-app/README.md b/axum/todo-app/README.md new file mode 100644 index 00000000..d3f9eb27 --- /dev/null +++ b/axum/todo-app/README.md @@ -0,0 +1,30 @@ +# Todo App + +A full-stack todo application built with Rust and Axum, deployed on Shuttle. + +## Features + +- Create, read, update, and delete todos +- PostgreSQL database with SQLx +- Static frontend with HTML/CSS/JavaScript +- CORS enabled API + +## API Endpoints + +- `GET /api/todos` - Get all todos +- `POST /api/todos` - Create a new todo +- `GET /api/todos/{id}` - Get a specific todo +- `PUT /api/todos/{id}` - Update a todo +- `DELETE /api/todos/{id}` - Delete a todo + +## Running + +```bash +shuttle run +``` + +## Deployment + +```bash +shuttle deploy +``` diff --git a/axum/todo-app/Shuttle.toml b/axum/todo-app/Shuttle.toml new file mode 100644 index 00000000..885ab3b8 --- /dev/null +++ b/axum/todo-app/Shuttle.toml @@ -0,0 +1,2 @@ +[build] +assets = ["static/*"] diff --git a/axum/todo-app/migrations/20250812165323_create_todos_table.sql b/axum/todo-app/migrations/20250812165323_create_todos_table.sql new file mode 100644 index 00000000..708956a5 --- /dev/null +++ b/axum/todo-app/migrations/20250812165323_create_todos_table.sql @@ -0,0 +1,6 @@ +CREATE TABLE todos ( + id SERIAL PRIMARY KEY, + title VARCHAR(255) NOT NULL, + completed BOOLEAN NOT NULL DEFAULT FALSE, + created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP +); diff --git a/axum/todo-app/src/database/mod.rs b/axum/todo-app/src/database/mod.rs new file mode 100644 index 00000000..a06323f7 --- /dev/null +++ b/axum/todo-app/src/database/mod.rs @@ -0,0 +1,3 @@ +pub mod repository; + +pub use repository::*; diff --git a/axum/todo-app/src/database/repository.rs b/axum/todo-app/src/database/repository.rs new file mode 100644 index 00000000..6daa4d8d --- /dev/null +++ b/axum/todo-app/src/database/repository.rs @@ -0,0 +1,110 @@ +use anyhow::Result; +use sqlx::{Pool, Postgres}; + +use crate::models::{Todo, UpdateTodoRequest}; + +#[derive(Clone)] +pub struct TodoRepository { + pool: Pool, +} + +impl TodoRepository { + pub fn new(pool: Pool) -> Self { + Self { pool } + } + + pub async fn create_todo(&self, title: &str) -> Result { + let row = sqlx::query!( + "INSERT INTO todos (title) VALUES ($1) RETURNING id, title, completed, created_at", + title + ) + .fetch_one(&self.pool) + .await?; + + Ok(Todo { + id: row.id, + title: row.title, + completed: row.completed, + created_at: row.created_at, + }) + } + + pub async fn get_all_todos(&self) -> Result> { + let rows = sqlx::query!( + "SELECT id, title, completed, created_at FROM todos ORDER BY created_at DESC" + ) + .fetch_all(&self.pool) + .await?; + + let todos = rows + .into_iter() + .map(|row| Todo { + id: row.id, + title: row.title, + completed: row.completed, + created_at: row.created_at, + }) + .collect(); + + Ok(todos) + } + + pub async fn get_todo_by_id(&self, id: i32) -> Result> { + let row = sqlx::query!( + "SELECT id, title, completed, created_at FROM todos WHERE id = $1", + id + ) + .fetch_optional(&self.pool) + .await?; + + if let Some(row) = row { + Ok(Some(Todo { + id: row.id, + title: row.title, + completed: row.completed, + created_at: row.created_at, + })) + } else { + Ok(None) + } + } + + pub async fn update_todo(&self, id: i32, update: UpdateTodoRequest) -> Result> { + let existing = self.get_todo_by_id(id).await?; + if existing.is_none() { + return Ok(None); + } + + let existing = existing.unwrap(); + + let new_title = update + .title + .map(|t| t.trim().to_string()) + .unwrap_or(existing.title); + let new_completed = update.completed.unwrap_or(existing.completed); + + let row = sqlx::query!( + "UPDATE todos SET title = $1, completed = $2 WHERE id = $3 RETURNING id, title, completed, created_at", + new_title, + new_completed, + id + ) + .fetch_one(&self.pool) + .await?; + + Ok(Some(Todo { + id: row.id, + title: row.title, + completed: row.completed, + created_at: row.created_at, + })) + } + + pub async fn delete_todo(&self, id: i32) -> Result { + let result = sqlx::query!("DELETE FROM todos WHERE id = $1", id) + .execute(&self.pool) + .await?; + + Ok(result.rows_affected() > 0) + } +} diff --git a/axum/todo-app/src/handlers/error.rs b/axum/todo-app/src/handlers/error.rs new file mode 100644 index 00000000..7ffdb24e --- /dev/null +++ b/axum/todo-app/src/handlers/error.rs @@ -0,0 +1,55 @@ +use axum::{ + Json, + http::StatusCode, + response::{IntoResponse, Response}, +}; +use serde_json::json; + +#[derive(Debug)] +pub enum AppError { + DatabaseError(String), + ValidationError(String), + NotFound(String), + InternalError(String), +} + +impl IntoResponse for AppError { + fn into_response(self) -> Response { + let (status, message) = match self { + AppError::DatabaseError(msg) => { + tracing::error!("Database error: {}", msg); + ( + StatusCode::INTERNAL_SERVER_ERROR, + "Database error occurred".to_string(), + ) + } + AppError::ValidationError(msg) => (StatusCode::BAD_REQUEST, msg), + AppError::NotFound(msg) => (StatusCode::NOT_FOUND, msg), + AppError::InternalError(msg) => { + tracing::error!("Internal error: {}", msg); + ( + StatusCode::INTERNAL_SERVER_ERROR, + "Internal server error".to_string(), + ) + } + }; + + let body = Json(json!({ + "error": message + })); + + (status, body).into_response() + } +} + +impl From for AppError { + fn from(err: sqlx::Error) -> Self { + AppError::DatabaseError(err.to_string()) + } +} + +impl From for AppError { + fn from(err: anyhow::Error) -> Self { + AppError::InternalError(err.to_string()) + } +} diff --git a/axum/todo-app/src/handlers/mod.rs b/axum/todo-app/src/handlers/mod.rs new file mode 100644 index 00000000..119246ee --- /dev/null +++ b/axum/todo-app/src/handlers/mod.rs @@ -0,0 +1,5 @@ +pub mod error; +pub mod todo; + +pub use error::*; +pub use todo::*; diff --git a/axum/todo-app/src/handlers/todo.rs b/axum/todo-app/src/handlers/todo.rs new file mode 100644 index 00000000..febb3ea2 --- /dev/null +++ b/axum/todo-app/src/handlers/todo.rs @@ -0,0 +1,66 @@ +use axum::{ + extract::{Path, State}, + http::StatusCode, + response::Json, +}; +use serde_json::{Value, json}; + +use super::AppError; +use crate::{ + AppState, + models::{CreateTodoRequest, UpdateTodoRequest}, +}; + +pub async fn create_todo( + State(state): State, + Json(payload): Json, +) -> Result<(StatusCode, Json), AppError> { + payload.validate().map_err(AppError::ValidationError)?; + + let todo = state.repo.create_todo(payload.title.trim()).await?; + Ok((StatusCode::CREATED, Json(json!(todo)))) +} + +pub async fn get_todos(State(state): State) -> Result, AppError> { + let todos = state.repo.get_all_todos().await?; + Ok(Json(json!(todos))) +} + +pub async fn get_todo( + State(state): State, + Path(id): Path, +) -> Result, AppError> { + let todo = state + .repo + .get_todo_by_id(id) + .await? + .ok_or_else(|| AppError::NotFound("Todo not found".to_string()))?; + Ok(Json(json!(todo))) +} + +pub async fn update_todo( + State(state): State, + Path(id): Path, + Json(payload): Json, +) -> Result, AppError> { + payload.validate().map_err(AppError::ValidationError)?; + + let todo = state + .repo + .update_todo(id, payload) + .await? + .ok_or_else(|| AppError::NotFound("Todo not found".to_string()))?; + Ok(Json(json!(todo))) +} + +pub async fn delete_todo( + State(state): State, + Path(id): Path, +) -> Result { + let deleted = state.repo.delete_todo(id).await?; + if deleted { + Ok(StatusCode::NO_CONTENT) + } else { + Err(AppError::NotFound("Todo not found".to_string())) + } +} diff --git a/axum/todo-app/src/main.rs b/axum/todo-app/src/main.rs new file mode 100644 index 00000000..8686ef78 --- /dev/null +++ b/axum/todo-app/src/main.rs @@ -0,0 +1,42 @@ +mod database; +mod handlers; +mod models; + +use axum::{Router, routing::get}; +use tower_http::cors::CorsLayer; +use tower_http::services::ServeDir; + +use database::TodoRepository; + +#[derive(Clone)] +pub struct AppState { + pub repo: TodoRepository, +} + +#[shuttle_runtime::main] +async fn main(#[shuttle_shared_db::Postgres] pool: sqlx::PgPool) -> shuttle_axum::ShuttleAxum { + sqlx::migrate!("./migrations") + .run(&pool) + .await + .expect("Failed to run migrations"); + + let repo = TodoRepository::new(pool); + let state = AppState { repo }; + + let app = Router::new() + .route( + "/api/todos", + get(handlers::get_todos).post(handlers::create_todo), + ) + .route( + "/api/todos/{id}", + get(handlers::get_todo) + .put(handlers::update_todo) + .delete(handlers::delete_todo), + ) + .fallback_service(ServeDir::new("static")) + .layer(CorsLayer::permissive()) + .with_state(state); + + Ok(app.into()) +} diff --git a/axum/todo-app/src/models/mod.rs b/axum/todo-app/src/models/mod.rs new file mode 100644 index 00000000..aa54de91 --- /dev/null +++ b/axum/todo-app/src/models/mod.rs @@ -0,0 +1,3 @@ +pub mod todo; + +pub use todo::*; diff --git a/axum/todo-app/src/models/todo.rs b/axum/todo-app/src/models/todo.rs new file mode 100644 index 00000000..764bdd15 --- /dev/null +++ b/axum/todo-app/src/models/todo.rs @@ -0,0 +1,47 @@ +use chrono::{DateTime, Utc}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct Todo { + pub id: i32, + pub title: String, + pub completed: bool, + pub created_at: DateTime, +} + +#[derive(Debug, Deserialize)] +pub struct CreateTodoRequest { + pub title: String, +} + +impl CreateTodoRequest { + pub fn validate(&self) -> Result<(), String> { + if self.title.trim().is_empty() { + return Err("Title cannot be empty".to_string()); + } + if self.title.len() > 255 { + return Err("Title cannot exceed 255 characters".to_string()); + } + Ok(()) + } +} + +#[derive(Debug, Deserialize)] +pub struct UpdateTodoRequest { + pub title: Option, + pub completed: Option, +} + +impl UpdateTodoRequest { + pub fn validate(&self) -> Result<(), String> { + if let Some(ref title) = self.title { + if title.trim().is_empty() { + return Err("Title cannot be empty".to_string()); + } + if title.len() > 255 { + return Err("Title cannot exceed 255 characters".to_string()); + } + } + Ok(()) + } +} diff --git a/axum/todo-app/static/index.html b/axum/todo-app/static/index.html new file mode 100644 index 00000000..53f4c3e0 --- /dev/null +++ b/axum/todo-app/static/index.html @@ -0,0 +1,38 @@ + + + + + + Todo App + + + +
+

Todo App

+ +
+ + +
+ +
+ 0 todos + 0 completed +
+ +
+ + + +
+ +
    + +
+ + +
+ + + + \ No newline at end of file diff --git a/axum/todo-app/static/script.js b/axum/todo-app/static/script.js new file mode 100644 index 00000000..742a12dc --- /dev/null +++ b/axum/todo-app/static/script.js @@ -0,0 +1,268 @@ +class TodoApp { + constructor() { + this.todos = []; + this.currentFilter = 'all'; + this.editingId = null; + + this.initElements(); + this.bindEvents(); + this.loadTodos(); + } + + initElements() { + this.todoList = document.getElementById('todo-list'); + this.newTodoInput = document.getElementById('new-todo-input'); + this.addTodoBtn = document.getElementById('add-todo-btn'); + this.totalTodos = document.getElementById('total-todos'); + this.completedTodos = document.getElementById('completed-todos'); + this.errorMessage = document.getElementById('error-message'); + this.filterBtns = document.querySelectorAll('.filter-btn'); + } + + bindEvents() { + this.addTodoBtn.addEventListener('click', () => this.addTodo()); + this.newTodoInput.addEventListener('keypress', (e) => { + if (e.key === 'Enter') this.addTodo(); + }); + + this.filterBtns.forEach(btn => { + btn.addEventListener('click', (e) => { + this.setFilter(e.target.dataset.filter); + }); + }); + } + + async apiCall(endpoint, options = {}) { + try { + const response = await fetch(`/api${endpoint}`, { + headers: { + 'Content-Type': 'application/json', + ...options.headers + }, + ...options + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error(`HTTP ${response.status}: ${errorText}`); + } + + const contentType = response.headers.get('content-type'); + if (contentType && contentType.includes('application/json')) { + return await response.json(); + } + return null; + } catch (error) { + this.showError(`API Error: ${error.message}`); + throw error; + } + } + + async loadTodos() { + try { + this.todos = await this.apiCall('/todos'); + this.renderTodos(); + this.updateStats(); + } catch (error) { + console.error('Failed to load todos:', error); + } + } + + async addTodo() { + const title = this.newTodoInput.value.trim(); + if (!title) return; + + try { + const newTodo = await this.apiCall('/todos', { + method: 'POST', + body: JSON.stringify({ title }) + }); + + this.todos.unshift(newTodo); + this.newTodoInput.value = ''; + this.renderTodos(); + this.updateStats(); + this.hideError(); + } catch (error) { + console.error('Failed to add todo:', error); + } + } + + async toggleTodo(id) { + const todo = this.todos.find(t => t.id === id); + if (!todo) return; + + try { + const updatedTodo = await this.apiCall(`/todos/${id}`, { + method: 'PUT', + body: JSON.stringify({ + title: todo.title, + completed: !todo.completed + }) + }); + + const index = this.todos.findIndex(t => t.id === id); + this.todos[index] = updatedTodo; + this.renderTodos(); + this.updateStats(); + this.hideError(); + } catch (error) { + console.error('Failed to toggle todo:', error); + } + } + + async deleteTodo(id) { + try { + await this.apiCall(`/todos/${id}`, { + method: 'DELETE' + }); + + this.todos = this.todos.filter(t => t.id !== id); + this.renderTodos(); + this.updateStats(); + this.hideError(); + } catch (error) { + console.error('Failed to delete todo:', error); + } + } + + startEdit(id) { + this.editingId = id; + this.renderTodos(); + + const input = document.querySelector(`[data-id="${id}"] .todo-text`); + if (input) { + input.focus(); + input.select(); + } + } + + async saveEdit(id, newTitle) { + if (!newTitle.trim()) { + this.cancelEdit(); + return; + } + + const todo = this.todos.find(t => t.id === id); + if (!todo) return; + + try { + const updatedTodo = await this.apiCall(`/todos/${id}`, { + method: 'PUT', + body: JSON.stringify({ + title: newTitle.trim(), + completed: todo.completed + }) + }); + + const index = this.todos.findIndex(t => t.id === id); + this.todos[index] = updatedTodo; + this.editingId = null; + this.renderTodos(); + this.hideError(); + } catch (error) { + console.error('Failed to update todo:', error); + this.cancelEdit(); + } + } + + cancelEdit() { + this.editingId = null; + this.renderTodos(); + } + + setFilter(filter) { + this.currentFilter = filter; + + this.filterBtns.forEach(btn => { + btn.classList.toggle('active', btn.dataset.filter === filter); + }); + + this.renderTodos(); + } + + getFilteredTodos() { + switch (this.currentFilter) { + case 'active': + return this.todos.filter(todo => !todo.completed); + case 'completed': + return this.todos.filter(todo => todo.completed); + default: + return this.todos; + } + } + + renderTodos() { + const filteredTodos = this.getFilteredTodos(); + + if (filteredTodos.length === 0) { + this.todoList.innerHTML = ` +
  • + ${this.todos.length === 0 ? 'No todos yet. Add one above!' : 'No todos match the current filter.'} +
  • + `; + return; + } + + this.todoList.innerHTML = filteredTodos.map(todo => { + const isEditing = this.editingId === todo.id; + + return ` +
  • +
    + + ${isEditing ? ` + + ` : ` + ${this.escapeHtml(todo.title)} + `} + +
    + ${!isEditing ? ` + + ` : ''} + +
    +
  • + `; + }).join(''); + } + + updateStats() { + const total = this.todos.length; + const completed = this.todos.filter(todo => todo.completed).length; + + this.totalTodos.textContent = `${total} todo${total !== 1 ? 's' : ''}`; + this.completedTodos.textContent = `${completed} completed`; + } + + showError(message) { + this.errorMessage.textContent = message; + this.errorMessage.style.display = 'block'; + + setTimeout(() => { + this.hideError(); + }, 5000); + } + + hideError() { + this.errorMessage.style.display = 'none'; + } + + escapeHtml(text) { + const div = document.createElement('div'); + div.textContent = text; + return div.innerHTML; + } +} + +// Initialize the app when the DOM is loaded +document.addEventListener('DOMContentLoaded', () => { + window.app = new TodoApp(); +}); \ No newline at end of file diff --git a/axum/todo-app/static/style.css b/axum/todo-app/static/style.css new file mode 100644 index 00000000..a6593dd8 --- /dev/null +++ b/axum/todo-app/static/style.css @@ -0,0 +1,552 @@ +/* Modern CSS Reset and Base Styles */ +* { + box-sizing: border-box; +} + +body { + font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, + sans-serif; + background: linear-gradient(135deg, #0f172a 0%, #1e293b 50%, #334155 100%); + min-height: 100vh; + margin: 0; + padding: 20px; + color: #1e293b; + line-height: 1.6; +} + +/* Container with improved glass morphism effect */ +.container { + max-width: 680px; + margin: 0 auto; + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(20px); + border: 1px solid rgba(255, 255, 255, 0.2); + border-radius: 20px; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.05); + overflow: hidden; + transition: transform 0.3s ease, box-shadow 0.3s ease; +} + +.container:hover { + transform: translateY(-2px); + box-shadow: 0 25px 50px rgba(0, 0, 0, 0.15), 0 1px 3px rgba(0, 0, 0, 0.05); +} + +/* Enhanced header with better typography */ +h1 { + text-align: center; + margin: 0; + padding: 40px 20px 30px; + background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 50%, #06b6d4 100%); + color: white; + font-size: clamp(1.8rem, 4vw, 2.5rem); + font-weight: 700; + letter-spacing: -0.02em; + text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + position: relative; + overflow: hidden; +} + +h1::before { + content: ""; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient( + 90deg, + transparent, + rgba(255, 255, 255, 0.2), + transparent + ); + transition: left 0.5s; +} + +h1:hover::before { + left: 100%; +} + +/* Improved add todo section */ +.add-todo { + padding: 30px; + display: flex; + gap: 12px; + background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%); + border-bottom: 1px solid #e2e8f0; +} + +#new-todo-input { + flex: 1; + padding: 16px 20px; + border: 2px solid #e2e8f0; + border-radius: 12px; + font-size: 16px; + font-weight: 500; + outline: none; + transition: all 0.3s ease; + background: white; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); +} + +#new-todo-input:focus { + border-color: #3b82f6; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1), 0 4px 12px rgba(0, 0, 0, 0.1); + transform: translateY(-1px); +} + +#new-todo-input::placeholder { + color: #94a3b8; + font-weight: 400; +} + +#add-todo-btn { + padding: 16px 28px; + background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%); + color: white; + border: none; + border-radius: 12px; + font-size: 16px; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3); + position: relative; + overflow: hidden; +} + +#add-todo-btn:hover { + transform: translateY(-2px); + box-shadow: 0 8px 20px rgba(59, 130, 246, 0.4); +} + +#add-todo-btn:active { + transform: translateY(0); +} + +/* Enhanced stats section */ +.todo-stats { + display: flex; + justify-content: space-between; + align-items: center; + padding: 20px 30px; + font-size: 14px; + font-weight: 500; + color: #64748b; + background: #f8fafc; + border-bottom: 1px solid #e2e8f0; +} + +.todo-stats span { + padding: 6px 12px; + background: white; + border-radius: 8px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); +} + +/* Modern filter buttons */ +.todo-filters { + display: flex; + padding: 25px 30px; + gap: 8px; + border-bottom: 1px solid #e2e8f0; + background: white; +} + +.filter-btn { + padding: 10px 18px; + border: 2px solid #e2e8f0; + background: white; + border-radius: 10px; + cursor: pointer; + font-size: 14px; + font-weight: 500; + transition: all 0.3s ease; + color: #64748b; +} + +.filter-btn:hover { + background: #f1f5f9; + border-color: #cbd5e1; + transform: translateY(-1px); +} + +.filter-btn.active { + background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%); + color: white; + border-color: transparent; + box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3); +} + +/* Enhanced todo list */ +.todo-list { + list-style: none; + padding: 0; + margin: 0; + min-height: 200px; + background: white; +} + +.todo-item { + display: flex; + align-items: center; + padding: 20px 30px; + border-bottom: 1px solid #f1f5f9; + transition: all 0.3s ease; + position: relative; +} + +.todo-item:hover { + background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%); + transform: translateX(4px); +} + +.todo-item.completed { + opacity: 0.7; +} + +.todo-item.completed::before { + content: ""; + position: absolute; + left: 0; + top: 0; + bottom: 0; + width: 4px; + background: linear-gradient(135deg, #10b981 0%, #059669 100%); +} + +/* Modern checkbox design */ +.todo-checkbox { + width: 24px; + height: 24px; + border: 2px solid #cbd5e1; + border-radius: 8px; + margin-right: 20px; + cursor: pointer; + transition: all 0.3s ease; + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + background: white; +} + +.todo-checkbox:hover { + border-color: #3b82f6; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +.todo-checkbox.completed { + background: linear-gradient(135deg, #10b981 0%, #059669 100%); + border-color: #10b981; + box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3); +} + +.todo-checkbox.completed::after { + content: "✓"; + color: white; + font-size: 14px; + font-weight: bold; + animation: checkmark 0.3s ease; +} + +@keyframes checkmark { + 0% { + transform: scale(0) rotate(45deg); + } + 50% { + transform: scale(1.2) rotate(45deg); + } + 100% { + transform: scale(1) rotate(45deg); + } +} + +/* Enhanced todo text */ +.todo-text { + flex: 1; + font-size: 16px; + font-weight: 500; + color: #1e293b; + cursor: pointer; + transition: all 0.3s ease; + line-height: 1.5; +} + +.todo-text.completed { + text-decoration: line-through; + color: #94a3b8; +} + +.todo-text.editing { + background: white; + border: 2px solid #3b82f6; + border-radius: 8px; + padding: 8px 12px; + outline: none; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); + color: #1e293b; + font-weight: 500; +} + +/* Modern action buttons */ +.todo-actions { + display: flex; + gap: 8px; + opacity: 0; + transition: all 0.3s ease; + transform: translateX(10px); +} + +.todo-item:hover .todo-actions { + opacity: 1; + transform: translateX(0); +} + +.todo-btn { + padding: 8px 14px; + border: none; + border-radius: 8px; + cursor: pointer; + font-size: 12px; + font-weight: 600; + transition: all 0.3s ease; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.edit-btn { + background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%); + color: white; + box-shadow: 0 2px 8px rgba(245, 158, 11, 0.3); +} + +.edit-btn:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(245, 158, 11, 0.4); +} + +.delete-btn { + background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%); + color: white; + box-shadow: 0 2px 8px rgba(239, 68, 68, 0.3); +} + +.delete-btn:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(239, 68, 68, 0.4); +} + +/* Enhanced error message */ +.error-message { + background: linear-gradient(135deg, #fef2f2 0%, #fee2e2 100%); + color: #991b1b; + padding: 16px 30px; + margin: 20px 30px; + border: 1px solid #fecaca; + border-left: 4px solid #ef4444; + border-radius: 12px; + font-size: 14px; + font-weight: 500; + box-shadow: 0 2px 8px rgba(239, 68, 68, 0.1); +} + +/* Beautiful empty state */ +.empty-state { + text-align: center; + padding: 80px 20px; + color: #64748b; + font-size: 16px; + font-weight: 500; +} + +.empty-state::before { + content: "✨"; + display: block; + font-size: 64px; + margin-bottom: 20px; + animation: float 3s ease-in-out infinite; +} + +@keyframes float { + 0%, + 100% { + transform: translateY(0px); + } + 50% { + transform: translateY(-10px); + } +} + +.empty-state::after { + content: "Add your first todo to get started!"; + display: block; + margin-top: 12px; + font-size: 14px; + color: #94a3b8; +} + +/* Enhanced mobile responsiveness */ +@media (max-width: 768px) { + body { + padding: 10px; + } + + .container { + margin: 0; + border-radius: 16px; + min-height: calc(100vh - 20px); + } + + h1 { + padding: 30px 20px 25px; + font-size: 1.8rem; + } + + .add-todo { + flex-direction: column; + padding: 25px 20px; + gap: 16px; + } + + #new-todo-input, + #add-todo-btn { + width: 100%; + } + + .todo-filters { + justify-content: center; + flex-wrap: wrap; + padding: 20px; + } + + .todo-stats { + flex-direction: column; + gap: 8px; + text-align: center; + padding: 20px; + } + + .todo-item { + padding: 16px 20px; + } + + .todo-actions { + opacity: 1; + transform: translateX(0); + } + + .empty-state { + padding: 60px 20px; + } + + .empty-state::before { + font-size: 48px; + } +} + +/* Dark mode support */ +@media (prefers-color-scheme: dark) { + .container { + background: rgba(30, 41, 59, 0.95); + border-color: rgba(255, 255, 255, 0.1); + } + + .add-todo { + background: linear-gradient(135deg, #1e293b 0%, #334155 100%); + border-color: #475569; + } + + #new-todo-input { + background: #334155; + border-color: #475569; + color: #f1f5f9; + } + + #new-todo-input::placeholder { + color: #64748b; + } + + .todo-stats { + background: #1e293b; + border-color: #475569; + color: #94a3b8; + } + + .todo-stats span { + background: #334155; + } + + .todo-filters { + background: #1e293b; + border-color: #475569; + } + + .filter-btn { + background: #334155; + border-color: #475569; + color: #cbd5e1; + } + + .filter-btn:hover { + background: #475569; + } + + .todo-list { + background: #1e293b; + } + + .todo-item { + border-color: #334155; + } + + .todo-item:hover { + background: linear-gradient(135deg, #334155 0%, #475569 100%); + } + + .todo-text { + color: #f1f5f9; + } + + .todo-checkbox { + background: #334155; + border-color: #475569; + } + + .empty-state { + color: #94a3b8; + } + + .todo-text.editing { + background: #334155; + border-color: #60a5fa; + color: #f1f5f9; + box-shadow: 0 0 0 3px rgba(96, 165, 250, 0.1); + } +} + +/* Smooth scrolling and focus improvements */ +html { + scroll-behavior: smooth; +} + +*:focus { + outline: 2px solid #3b82f6; + outline-offset: 2px; +} + +/* Loading animation for dynamic content */ +@keyframes shimmer { + 0% { + background-position: -200px 0; + } + 100% { + background-position: calc(200px + 100%) 0; + } +} + +.loading { + background: linear-gradient(90deg, #f1f5f9 25%, #e2e8f0 50%, #f1f5f9 75%); + background-size: 200px 100%; + animation: shimmer 1.5s infinite; +} diff --git a/templates.toml b/templates.toml index 0f662861..82432003 100644 --- a/templates.toml +++ b/templates.toml @@ -251,6 +251,13 @@ path = "axum/todo-list" use_cases = ["Web app", "Storage"] tags = ["axum", "postgres", "database"] +[templates.axum-todo-app] +title = "Todo app" +description = "CRUD Todo application with Postgres database and frontend" +path = "axum/todo-app" +use_cases = ["Web app", "Storage"] +tags = ["axum", "postgres", "database"] + [templates.axum-turso] title = "Turso" description = "Connect to a Turso DB with shuttle-turso" From b727c0eb821b9ca6000857a3fc9adc5b6d9973c1 Mon Sep 17 00:00:00 2001 From: jonaro00 <54029719+jonaro00@users.noreply.github.com> Date: Thu, 11 Sep 2025 13:56:38 +0200 Subject: [PATCH 225/239] nits --- actix-web/postgres/Cargo.toml | 2 +- actix-web/static-files/assets/index.html | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/actix-web/postgres/Cargo.toml b/actix-web/postgres/Cargo.toml index 16734499..a20cd911 100644 --- a/actix-web/postgres/Cargo.toml +++ b/actix-web/postgres/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] actix-web = "4.3.1" +serde = "1.0.148" shuttle-actix-web = "0.57.0" shuttle-runtime = "0.57.0" -serde = "1.0.148" shuttle-shared-db = { version = "0.57.0", features = ["postgres", "sqlx"] } sqlx = "0.8.2" tokio = "1.26.0" diff --git a/actix-web/static-files/assets/index.html b/actix-web/static-files/assets/index.html index 597ecf5f..75b2e9ea 100644 --- a/actix-web/static-files/assets/index.html +++ b/actix-web/static-files/assets/index.html @@ -1 +1,9 @@ -

    Hello world!

    + + + + Static Files + + +

    This is an example of serving static files with Actix Web and Shuttle.

    + + From 75861ddba7e0c3f9360ab3687a0ba67ede8d8451 Mon Sep 17 00:00:00 2001 From: dcodes <101001810+dcodesdev@users.noreply.github.com> Date: Mon, 15 Sep 2025 21:53:20 +0300 Subject: [PATCH 226/239] New Template: Snippet Sharing App (#229) --- ...acf5ddf9c87a872574afeb20289627a897e7a.json | 14 + ...e8ad247d633fa8a073bdc0c6648089b5b0d4e.json | 66 ++++ ...130ff18e38de22b685489bb6f8eb0abacf281.json | 14 + ...6eb431b51deb808b8b92c547acca53bb6fe55.json | 22 ++ ...6138694ecbe8df8f3618210232ad45d3d7a0c.json | 14 + ...afd5c04ba143a352ab0dcea6cfe980721cd5f.json | 71 +++++ ...30e58455d4f915bc0a0c481ce77a1aff2828c.json | 65 ++++ axum/code-snippet-sharing-app/Cargo.toml | 22 ++ axum/code-snippet-sharing-app/README.md | 58 ++++ .../20240101000000_create_snippets_table.sql | 16 + axum/code-snippet-sharing-app/src/main.rs | 292 ++++++++++++++++++ templates.toml | 7 + 12 files changed, 661 insertions(+) create mode 100644 axum/code-snippet-sharing-app/.sqlx/query-40f717379ce15156cabe7bd200bacf5ddf9c87a872574afeb20289627a897e7a.json create mode 100644 axum/code-snippet-sharing-app/.sqlx/query-49969fd63526646bb069216573be8ad247d633fa8a073bdc0c6648089b5b0d4e.json create mode 100644 axum/code-snippet-sharing-app/.sqlx/query-4d8ecc221df32f11c2b6143999f130ff18e38de22b685489bb6f8eb0abacf281.json create mode 100644 axum/code-snippet-sharing-app/.sqlx/query-89b5d73a044dbac1f3463535b7d6eb431b51deb808b8b92c547acca53bb6fe55.json create mode 100644 axum/code-snippet-sharing-app/.sqlx/query-9bed2880002e53cc7187b8b68256138694ecbe8df8f3618210232ad45d3d7a0c.json create mode 100644 axum/code-snippet-sharing-app/.sqlx/query-a409ebc9ab67f4cbd9daa9e0209afd5c04ba143a352ab0dcea6cfe980721cd5f.json create mode 100644 axum/code-snippet-sharing-app/.sqlx/query-b8207efb0a5e77f676e17f0c68e30e58455d4f915bc0a0c481ce77a1aff2828c.json create mode 100644 axum/code-snippet-sharing-app/Cargo.toml create mode 100644 axum/code-snippet-sharing-app/README.md create mode 100644 axum/code-snippet-sharing-app/migrations/20240101000000_create_snippets_table.sql create mode 100644 axum/code-snippet-sharing-app/src/main.rs diff --git a/axum/code-snippet-sharing-app/.sqlx/query-40f717379ce15156cabe7bd200bacf5ddf9c87a872574afeb20289627a897e7a.json b/axum/code-snippet-sharing-app/.sqlx/query-40f717379ce15156cabe7bd200bacf5ddf9c87a872574afeb20289627a897e7a.json new file mode 100644 index 00000000..61f62aa5 --- /dev/null +++ b/axum/code-snippet-sharing-app/.sqlx/query-40f717379ce15156cabe7bd200bacf5ddf9c87a872574afeb20289627a897e7a.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM snippets WHERE expires_at IS NOT NULL AND expires_at <= $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Timestamptz" + ] + }, + "nullable": [] + }, + "hash": "40f717379ce15156cabe7bd200bacf5ddf9c87a872574afeb20289627a897e7a" +} diff --git a/axum/code-snippet-sharing-app/.sqlx/query-49969fd63526646bb069216573be8ad247d633fa8a073bdc0c6648089b5b0d4e.json b/axum/code-snippet-sharing-app/.sqlx/query-49969fd63526646bb069216573be8ad247d633fa8a073bdc0c6648089b5b0d4e.json new file mode 100644 index 00000000..9303ddfc --- /dev/null +++ b/axum/code-snippet-sharing-app/.sqlx/query-49969fd63526646bb069216573be8ad247d633fa8a073bdc0c6648089b5b0d4e.json @@ -0,0 +1,66 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n id,\n title,\n description,\n language,\n created_at,\n expires_at,\n view_count,\n LENGTH(content) as \"char_count!\"\n FROM snippets\n WHERE is_public = true\n AND (expires_at IS NULL OR expires_at > $1)\n AND language = $2\n ORDER BY created_at DESC\n LIMIT $3\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Varchar" + }, + { + "ordinal": 1, + "name": "title", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "description", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "language", + "type_info": "Varchar" + }, + { + "ordinal": 4, + "name": "created_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 5, + "name": "expires_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 6, + "name": "view_count", + "type_info": "Int4" + }, + { + "ordinal": 7, + "name": "char_count!", + "type_info": "Int4" + } + ], + "parameters": { + "Left": [ + "Timestamptz", + "Text", + "Int8" + ] + }, + "nullable": [ + false, + true, + true, + false, + false, + true, + false, + null + ] + }, + "hash": "49969fd63526646bb069216573be8ad247d633fa8a073bdc0c6648089b5b0d4e" +} diff --git a/axum/code-snippet-sharing-app/.sqlx/query-4d8ecc221df32f11c2b6143999f130ff18e38de22b685489bb6f8eb0abacf281.json b/axum/code-snippet-sharing-app/.sqlx/query-4d8ecc221df32f11c2b6143999f130ff18e38de22b685489bb6f8eb0abacf281.json new file mode 100644 index 00000000..76897346 --- /dev/null +++ b/axum/code-snippet-sharing-app/.sqlx/query-4d8ecc221df32f11c2b6143999f130ff18e38de22b685489bb6f8eb0abacf281.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE snippets SET view_count = view_count + 1 WHERE id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [] + }, + "hash": "4d8ecc221df32f11c2b6143999f130ff18e38de22b685489bb6f8eb0abacf281" +} diff --git a/axum/code-snippet-sharing-app/.sqlx/query-89b5d73a044dbac1f3463535b7d6eb431b51deb808b8b92c547acca53bb6fe55.json b/axum/code-snippet-sharing-app/.sqlx/query-89b5d73a044dbac1f3463535b7d6eb431b51deb808b8b92c547acca53bb6fe55.json new file mode 100644 index 00000000..b79fed91 --- /dev/null +++ b/axum/code-snippet-sharing-app/.sqlx/query-89b5d73a044dbac1f3463535b7d6eb431b51deb808b8b92c547acca53bb6fe55.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO snippets (id, content, language, title, description, created_at, expires_at, view_count, is_public)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Varchar", + "Text", + "Varchar", + "Varchar", + "Text", + "Timestamptz", + "Timestamptz", + "Int4", + "Bool" + ] + }, + "nullable": [] + }, + "hash": "89b5d73a044dbac1f3463535b7d6eb431b51deb808b8b92c547acca53bb6fe55" +} diff --git a/axum/code-snippet-sharing-app/.sqlx/query-9bed2880002e53cc7187b8b68256138694ecbe8df8f3618210232ad45d3d7a0c.json b/axum/code-snippet-sharing-app/.sqlx/query-9bed2880002e53cc7187b8b68256138694ecbe8df8f3618210232ad45d3d7a0c.json new file mode 100644 index 00000000..eaff4244 --- /dev/null +++ b/axum/code-snippet-sharing-app/.sqlx/query-9bed2880002e53cc7187b8b68256138694ecbe8df8f3618210232ad45d3d7a0c.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM snippets WHERE id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [] + }, + "hash": "9bed2880002e53cc7187b8b68256138694ecbe8df8f3618210232ad45d3d7a0c" +} diff --git a/axum/code-snippet-sharing-app/.sqlx/query-a409ebc9ab67f4cbd9daa9e0209afd5c04ba143a352ab0dcea6cfe980721cd5f.json b/axum/code-snippet-sharing-app/.sqlx/query-a409ebc9ab67f4cbd9daa9e0209afd5c04ba143a352ab0dcea6cfe980721cd5f.json new file mode 100644 index 00000000..20fa0d1b --- /dev/null +++ b/axum/code-snippet-sharing-app/.sqlx/query-a409ebc9ab67f4cbd9daa9e0209afd5c04ba143a352ab0dcea6cfe980721cd5f.json @@ -0,0 +1,71 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT id, content, language, title, description, created_at, expires_at, view_count, is_public\n FROM snippets\n WHERE id = $1 AND (expires_at IS NULL OR expires_at > $2)\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Varchar" + }, + { + "ordinal": 1, + "name": "content", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "language", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "title", + "type_info": "Varchar" + }, + { + "ordinal": 4, + "name": "description", + "type_info": "Text" + }, + { + "ordinal": 5, + "name": "created_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 6, + "name": "expires_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 7, + "name": "view_count", + "type_info": "Int4" + }, + { + "ordinal": 8, + "name": "is_public", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Text", + "Timestamptz" + ] + }, + "nullable": [ + false, + false, + false, + true, + true, + false, + true, + false, + false + ] + }, + "hash": "a409ebc9ab67f4cbd9daa9e0209afd5c04ba143a352ab0dcea6cfe980721cd5f" +} diff --git a/axum/code-snippet-sharing-app/.sqlx/query-b8207efb0a5e77f676e17f0c68e30e58455d4f915bc0a0c481ce77a1aff2828c.json b/axum/code-snippet-sharing-app/.sqlx/query-b8207efb0a5e77f676e17f0c68e30e58455d4f915bc0a0c481ce77a1aff2828c.json new file mode 100644 index 00000000..1f79bb19 --- /dev/null +++ b/axum/code-snippet-sharing-app/.sqlx/query-b8207efb0a5e77f676e17f0c68e30e58455d4f915bc0a0c481ce77a1aff2828c.json @@ -0,0 +1,65 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n id,\n title,\n description,\n language,\n created_at,\n expires_at,\n view_count,\n LENGTH(content) as \"char_count!\"\n FROM snippets\n WHERE is_public = true\n AND (expires_at IS NULL OR expires_at > $1)\n ORDER BY created_at DESC\n LIMIT $2\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Varchar" + }, + { + "ordinal": 1, + "name": "title", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "description", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "language", + "type_info": "Varchar" + }, + { + "ordinal": 4, + "name": "created_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 5, + "name": "expires_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 6, + "name": "view_count", + "type_info": "Int4" + }, + { + "ordinal": 7, + "name": "char_count!", + "type_info": "Int4" + } + ], + "parameters": { + "Left": [ + "Timestamptz", + "Int8" + ] + }, + "nullable": [ + false, + true, + true, + false, + false, + true, + false, + null + ] + }, + "hash": "b8207efb0a5e77f676e17f0c68e30e58455d4f915bc0a0c481ce77a1aff2828c" +} diff --git a/axum/code-snippet-sharing-app/Cargo.toml b/axum/code-snippet-sharing-app/Cargo.toml new file mode 100644 index 00000000..74fc7c30 --- /dev/null +++ b/axum/code-snippet-sharing-app/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "code-snippet-sharing-app" +version = "0.1.0" +edition = "2021" + +[dependencies] +axum = "0.8" +tokio = { version = "1", features = ["macros", "rt-multi-thread"] } +shuttle-axum = "0.57.0" +shuttle-runtime = "0.57.0" +shuttle-shared-db = { version = "0.57.0", features = ["postgres", "sqlx"] } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +uuid = { version = "1.0", features = ["v4", "serde"] } +chrono = { version = "0.4", features = ["serde"] } +nanoid = "0.4" +sqlx = { version = "0.8", features = [ + "runtime-tokio-rustls", + "postgres", + "chrono", + "uuid", +] } diff --git a/axum/code-snippet-sharing-app/README.md b/axum/code-snippet-sharing-app/README.md new file mode 100644 index 00000000..a54e0982 --- /dev/null +++ b/axum/code-snippet-sharing-app/README.md @@ -0,0 +1,58 @@ +# Code Snippet Share API + +A lightweight API for sharing code snippets, built with **Rust**, **Axum**, and **Shuttle**. This hands-on tutorial demonstrates how to build, deploy, and manage a snippet-sharing service in the cloud. + +--- + +## Features + +- Create, list, view, and delete code snippets. +- Public and private snippet support. +- Tracks view count for each snippet. +- Filter snippets by programming language. +- Lightweight in-memory storage (ideal for tutorials and demos). + +--- + +## Tech Stack + +- **Rust** - Fast, safe, and expressive. +- **Axum** - Web framework for building async HTTP APIs. +- **Shuttle** - Rust serverless hosting platform. + +--- + +## Getting Started + +### Prerequisites + +- Rust (stable) +- Cargo +- Shuttle CLI: [Install Shuttle](https://docs.shuttle.dev/getting-started/installation) + +### Run Locally + +```bash +shuttle run +``` + +The API will start on `http://127.0.0.1:8000` + +### Deploy to Shuttle + +```bash +shuttle deploy +``` + +Your service will be live with a public URL provided by Shuttle. + +### Project Structure + +```bash +. +├── Cargo.lock +├── Cargo.toml +├── README.md +└── src + └── main.rs +``` diff --git a/axum/code-snippet-sharing-app/migrations/20240101000000_create_snippets_table.sql b/axum/code-snippet-sharing-app/migrations/20240101000000_create_snippets_table.sql new file mode 100644 index 00000000..0f8e60f6 --- /dev/null +++ b/axum/code-snippet-sharing-app/migrations/20240101000000_create_snippets_table.sql @@ -0,0 +1,16 @@ +CREATE TABLE IF NOT EXISTS snippets ( + id VARCHAR PRIMARY KEY NOT NULL, + content TEXT NOT NULL, + language VARCHAR NOT NULL, + title VARCHAR, + description TEXT, + created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + expires_at TIMESTAMPTZ, + view_count INTEGER NOT NULL DEFAULT 0, + is_public BOOLEAN NOT NULL DEFAULT true +); + +CREATE INDEX IF NOT EXISTS idx_snippets_created_at ON snippets(created_at DESC); +CREATE INDEX IF NOT EXISTS idx_snippets_language ON snippets(language); +CREATE INDEX IF NOT EXISTS idx_snippets_is_public ON snippets(is_public); +CREATE INDEX IF NOT EXISTS idx_snippets_expires_at ON snippets(expires_at); \ No newline at end of file diff --git a/axum/code-snippet-sharing-app/src/main.rs b/axum/code-snippet-sharing-app/src/main.rs new file mode 100644 index 00000000..9345f26a --- /dev/null +++ b/axum/code-snippet-sharing-app/src/main.rs @@ -0,0 +1,292 @@ +use chrono::{DateTime, Duration, Utc}; +use serde::{Deserialize, Serialize}; +use serde_json::json; +use shuttle_axum::axum::{ + extract::{Path, Query, State}, + http::StatusCode, + response::Json, + routing::{get, post}, + Router, +}; +use sqlx::PgPool; + +#[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)] +struct Snippet { + id: String, + content: String, + language: String, + title: Option, + description: Option, + created_at: DateTime, + expires_at: Option>, + view_count: i32, + is_public: bool, +} + +#[derive(Deserialize)] +struct CreateSnippet { + content: String, + language: String, + title: Option, + description: Option, + expires_in_hours: Option, + is_public: Option, +} + +#[derive(Deserialize)] +struct ListQuery { + language: Option, + limit: Option, +} + +#[derive(Serialize)] +struct SnippetFull { + id: String, + title: Option, + description: Option, + language: String, + created_at: DateTime, + expires_at: Option>, + view_count: i32, + char_count: usize, + content: String, +} + +#[derive(Serialize)] +struct SnippetInfo { + id: String, + title: Option, + description: Option, + language: String, + created_at: DateTime, + expires_at: Option>, + view_count: i32, + char_count: i32, +} + +#[derive(Serialize)] +struct CreateSnippetResponse { + id: String, + url: String, +} + +// Generate a short, URL-friendly ID +fn generate_snippet_id() -> String { + nanoid::nanoid!(8) // Generates 8-character ID like "V1StGXR8" +} + +async fn health() -> Json { + Json(json!({ + "status": "healthy", + "service": "code-snippet-share", + "timestamp": Utc::now() + })) +} + +async fn create_snippet( + State(pool): State, + Json(payload): Json, +) -> Result<(StatusCode, Json), StatusCode> { + let id = generate_snippet_id(); + let now = Utc::now(); + + // Calculate expiration time if specified + let expires_at = payload + .expires_in_hours + .map(|hours| now + Duration::hours(hours)); + + let result = sqlx::query!( + r#" + INSERT INTO snippets (id, content, language, title, description, created_at, expires_at, view_count, is_public) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) + "#, + id, + payload.content, + payload.language, + payload.title, + payload.description, + now, + expires_at, + 0i32, + payload.is_public.unwrap_or(true) + ) + .execute(&pool) + .await; + + match result { + Ok(_) => { + let response = CreateSnippetResponse { + id: id.clone(), + url: format!("/snippets/{}", id), + }; + Ok((StatusCode::CREATED, Json(response))) + } + Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR), + } +} + +async fn get_snippet_full( + State(pool): State, + Path(id): Path, +) -> Result, StatusCode> { + let now = Utc::now(); + + // First, check if snippet exists and is not expired + let snippet = sqlx::query_as!( + Snippet, + r#" + SELECT id, content, language, title, description, created_at, expires_at, view_count, is_public + FROM snippets + WHERE id = $1 AND (expires_at IS NULL OR expires_at > $2) + "#, + id, + now + ) + .fetch_optional(&pool) + .await + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + + match snippet { + Some(mut snippet) => { + // Increment view count + let result = sqlx::query!( + "UPDATE snippets SET view_count = view_count + 1 WHERE id = $1", + id + ) + .execute(&pool) + .await; + + if result.is_ok() { + snippet.view_count += 1; + } + + let full = SnippetFull { + id: snippet.id, + title: snippet.title, + description: snippet.description, + language: snippet.language, + created_at: snippet.created_at, + expires_at: snippet.expires_at, + view_count: snippet.view_count, + char_count: snippet.content.len(), + content: snippet.content, + }; + + Ok(Json(full)) + } + None => { + // Clean up expired snippets + let _ = sqlx::query!( + "DELETE FROM snippets WHERE expires_at IS NOT NULL AND expires_at <= $1", + now + ) + .execute(&pool) + .await; + + Err(StatusCode::NOT_FOUND) + } + } +} + +async fn list_snippets( + State(pool): State, + Query(params): Query, +) -> Json> { + let now = Utc::now(); + let limit = params.limit.unwrap_or(20).min(100) as i64; + + let query = match params.language { + Some(language) => { + sqlx::query_as!( + SnippetInfo, + r#" + SELECT + id, + title, + description, + language, + created_at, + expires_at, + view_count, + LENGTH(content) as "char_count!" + FROM snippets + WHERE is_public = true + AND (expires_at IS NULL OR expires_at > $1) + AND language = $2 + ORDER BY created_at DESC + LIMIT $3 + "#, + now, + language, + limit + ) + .fetch_all(&pool) + .await + } + None => { + sqlx::query_as!( + SnippetInfo, + r#" + SELECT + id, + title, + description, + language, + created_at, + expires_at, + view_count, + LENGTH(content) as "char_count!" + FROM snippets + WHERE is_public = true + AND (expires_at IS NULL OR expires_at > $1) + ORDER BY created_at DESC + LIMIT $2 + "#, + now, + limit + ) + .fetch_all(&pool) + .await + } + }; + + let snippet_infos = query.unwrap_or_else(|_| vec![]); + Json(snippet_infos) +} + +async fn delete_snippet( + State(pool): State, + Path(id): Path, +) -> Result { + let result = sqlx::query!("DELETE FROM snippets WHERE id = $1", id) + .execute(&pool) + .await + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + + if result.rows_affected() > 0 { + Ok(StatusCode::NO_CONTENT) + } else { + Err(StatusCode::NOT_FOUND) + } +} + +#[shuttle_runtime::main] +async fn main(#[shuttle_shared_db::Postgres] pool: PgPool) -> shuttle_axum::ShuttleAxum { + // Run database migrations + sqlx::migrate!() + .run(&pool) + .await + .expect("Failed to run migrations"); + + // Build the router + let router = Router::new() + .route("/health", get(health)) + .route("/snippets", post(create_snippet).get(list_snippets)) + .route( + "/snippets/{id}", + get(get_snippet_full).delete(delete_snippet), + ) + .with_state(pool); + + Ok(router.into()) +} diff --git a/templates.toml b/templates.toml index 6798b9ba..20ff33b0 100644 --- a/templates.toml +++ b/templates.toml @@ -248,6 +248,13 @@ path = "axum/turso" use_cases = ["Web app", "Storage"] tags = ["turso", "axum", "database", "libsql", "sqlite"] +[templates.axum-code-snippet-sharing-app] +title = "Code Snippet Sharing" +description = "Share and manage code snippets with expiration and view tracking" +path = "axum/code-snippet-sharing-app" +use_cases = ["Web app", "Storage"] +tags = ["axum", "postgres", "database"] + [templates.axum-websocket] title = "Websockets" description = "Health monitoring service using websockets" From 93f1aa843863844224159f4494840f3532c21f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6=28s=29=20=3D=20=E2=88=91=E2=82=99=E2=82=8C=E2=82=81?= =?UTF-8?q?=5E=E2=88=9E=201/n=CB=A2=2E?= Date: Fri, 19 Sep 2025 20:06:56 +0100 Subject: [PATCH 227/239] Create data pipeline monitoring --- axum/data pipeline monitoring | 419 ++++++++++++++++++++++++++++++++++ 1 file changed, 419 insertions(+) create mode 100644 axum/data pipeline monitoring diff --git a/axum/data pipeline monitoring b/axum/data pipeline monitoring new file mode 100644 index 00000000..7fa7290f --- /dev/null +++ b/axum/data pipeline monitoring @@ -0,0 +1,419 @@ + +# polars-otel-shuttle + +High-performance ETL in Rust with Polars, production-ready observability via OpenTelemetry and tracing, and one-command deploy on Shuttle with built-in export to Better Stack. + +## Overview + +This repository contains: + +- A local, benchmark-style ETL pipeline using Polars over a large NYC Taxi CSV. +- An Axum HTTP service (for Shuttle) that exposes lightweight endpoints and emits structured traces and metrics. +- OTEL integration that requires no collector setup when deployed on Shuttle. +- Examples of metric events that flow to Better Stack (counters and histograms), with guidance for dashboards and log-based queries. + +## Why this project + +Many Python data teams rely on Pandas for ETL. Rust + Polars delivers multi-threaded performance with memory safety and predictable latency. This project shows how to: + +- Build an ETL pipeline in Rust/Polars. +- Instrument it with tracing and OpenTelemetry. +- Export telemetry to Better Stack with Shuttle’s native OTEL support (no sidecar collector). +- Visualize performance using log-derived metrics and dashboards. + +In addition, we mention Shuttle’s upcoming LogFire integration as a future option for observability. + +## Project layout + +``` +polars-otel-shuttle/ +├─ Cargo.toml +├─ Shuttle.toml +├─ src/ +│ ├─ etl.rs # Polars ETL pipeline (load → clean → aggregate → filter/sort → save) +│ ├─ observability.rs # Tracing/OTEL setup (fmt logs; optional OTLP for non-Shuttle runs) +│ └─ main.rs # CLI benchmark (feature-gated) + Axum web app for Shuttle +├─ data/ # Put the CSV here (ignored by Git) +└─ results/ # Output directory (ignored by Git) +``` + +## Prerequisites + +- Rust toolchain (stable) +- A large CSV to process, e.g. `yellow_tripdata_2015-01.csv` (~1.9GB) placed in `./data/` +- For deploys: Shuttle CLI and a Shuttle account +- For dashboards: a Better Stack account (Shuttle Telemetry export requires Pro tier or above) + +> **Note**: This repository does not commit the dataset. Keep large files out of Git. + +## Running the local ETL benchmark + +The CLI benchmark is feature-gated to keep the Shuttle build lightweight. + +From the repo root: + +```bash +RUST_LOG=info cargo run --release --features bench-cli +``` + +By default, the program looks for: + +``` +data/yellow_tripdata_2015-01.csv +``` + +Override via environment variable: + +```bash +DATA_PATH=/absolute/or/relative/path/to/your.csv \ +RUST_LOG=info cargo run --release --features bench-cli +``` + +### What it does + +`src/etl.rs` performs: + +1. **Load**: Lazy CSV scan (Polars) +2. **Clean**: Basic data preparation +3. **Aggregate**: Representative group-by computations +4. **Sort & filter**: Derive example counts +5. **Save**: Write results to `./results/` (ignored by Git) + +The CLI prints a summary and emits structured logs (JSON) with timing fields. + +## The Shuttle web service (observability demo) + +The Shuttle build exposes a small Axum API that simulates results and emits tracing events for observability. It avoids running the heavy ETL on ephemeral dynos. + +### Endpoints + +- `GET /` and `GET /health` — Simple health check (also emits a counter) +- `GET /benchmark` — Returns representative metrics and emits counters and histograms for dashboards + +Run locally as a normal binary: + +```bash +cargo run --release +``` + +Deploy to Shuttle: + +```bash +cargo shuttle deploy +``` + +Shuttle will return a public URL like: + +``` +https://.shuttle.app +``` + +## Observability: tracing + OpenTelemetry + +This project uses: + +- `tracing` for structured events +- `tracing-subscriber` for JSON logs with RFC3339 timestamps +- `tracing-opentelemetry` to bridge spans/events to OTEL (when applicable) + +### How it is initialized + +`src/observability.rs` sets up JSON logging for both CLI and server. When running on Shuttle, the platform injects an OTEL exporter that ships your events to the configured Telemetry destination (Better Stack). You don’t need to run or configure a collector. + +If you want to export to an OTLP endpoint when not on Shuttle, enable the `otel-otlp` feature and set: + +- `OTEL_EXPORTER_OTLP_ENDPOINT` (e.g., `http://localhost:4318`) +- `OTEL_EXPORTER_OTLP_HEADERS` (e.g., `Authorization=Bearer ...`) + +```bash +cargo run --release --features otel-otlp +``` + +## Metric events you can chart + +Shuttle’s telemetry pipeline interprets specific `tracing::info!` fields as metrics: + +- `monotonic_counter.*` → Cumulative counters (use rate for per-second/minute) +- `counter.*` → Values that can go up/down +- `histogram.*` → Distributions (p50, p95, avg, etc.) + +The Axum handlers emit a few examples: + +```rust +// Count requests to /benchmark +tracing::info!(monotonic_counter.http_requests_total = 1, route="/benchmark", "Benchmark hit"); + +// Publish stage timings as histograms (ms) +tracing::info!(histogram.load_time_ms = 1.2_f64 * 1000.0, stage="load", "stage timing"); +tracing::info!(histogram.clean_time_ms = 0.8_f64 * 1000.0, stage="clean", "stage timing"); +tracing::info!(histogram.aggregate_time_ms = 0.4_f64 * 1000.0, stage="aggregate", "stage timing"); +tracing::info!(histogram.sort_filter_time_ms = 0.3_f64 * 1000.0, stage="sort_filter", "stage timing"); +tracing::info!(histogram.save_time_ms = 0.1_f64 * 1000.0, stage="save", "stage timing"); +tracing::info!(histogram.total_time_ms = 2.8_f64 * 1000.0, stage="total", "stage timing"); + +// Rows processed (cumulative) +tracing::info!(monotonic_counter.rows_processed = 12_748_986_i64, "rows processed (demo)"); + +// Request duration per call +let t0 = std::time::Instant::now(); +// ... work ... +let elapsed_ms = t0.elapsed().as_millis() as f64; +tracing::info!(histogram.request_duration_ms = elapsed_ms, route="/benchmark", "Benchmark responded"); + +// Health endpoint heartbeat +tracing::info!(monotonic_counter.health_checks = 1, "health checked"); +``` + +> **Tip**: Keep metric names short and stable; add contextual attributes like `route`, `stage`, or `dataset`. + +## Exporting to Better Stack with Shuttle + +1. In Better Stack, create a Telemetry Source (OpenTelemetry) and copy the Source Token. +2. In the Shuttle web console → your project → Settings, enable Better Stack and paste the Source Token; save. +3. Deploy (or redeploy) your app: + +```bash +cargo shuttle deploy +``` + +4. Hit the endpoints to generate events: + +```bash +curl -s https://.shuttle.app/benchmark >/dev/null +curl -s https://.shuttle.app/benchmark >/dev/null +curl -s https://.shuttle.app/health +``` + +That’s it—no collector, no sidecars. Shuttle forwards OTEL data to Better Stack. + +## Viewing data in Better Stack + +### 1. Logs stream (sanity check) + +- Better Stack → Telemetry → your Source → Logs +- Search for a field like `histogram.total_time_ms` or `monotonic_counter.http_requests_total` +- You should see JSON events with your attributes (`route`, `stage`, etc.) + +### 2. Dashboards + +Create a dashboard and add charts that query your metrics: + +#### Requests per route +- **Metric**: `monotonic_counter.http_requests_total` +- **Aggregation**: Rate (per 1m or 5m) +- **Group by**: `route` +- **Visualization**: Line + +#### Request duration +- **Metric**: `histogram.request_duration_ms` +- **Aggregation**: p95 (or avg, p50) +- **Group by**: `route` +- **Visualization**: Line + +#### ETL stage timings +- **Metrics**: `histogram.load_time_ms`, `histogram.clean_time_ms`, `histogram.aggregate_time_ms`, `histogram.sort_filter_time_ms`, `histogram.save_time_ms` +- **Aggregation**: Avg +- **Group by**: `stage` +- **Visualization**: Stacked area or multi-line + +#### Rows processed +- **Metric**: `monotonic_counter.rows_processed` +- **Aggregation**: Rate to see throughput +- **Visualization**: Bar or line + +> **Note**: If your organization uses Metrics (pre-computed time series derived from logs), you can define them for frequently queried fields to reduce query latency and cost. Keep metric cardinality low (limit unique combinations of attributes like `route`, `stage`, `dataset`). + +### 3. Explore (ad-hoc) + +Use Explore for quick, one-off queries over logs without defining Metrics. Search by your metric field names and filter by attributes. + +### 4. Using Better Stack’s built-in telemetry + +You should see fields like these in Explore / Logs: + +- `duration` (request/operation span duration) +- `service`, `span_name`, `name` +- `http_target` (route), `net_peer_name` +- `error`, `kind`, `tags` + +#### Quick dashboards from built-ins + +Create a Dashboard → Add chart → Metrics (or start in Explore and “Save as metric”): + +1. **HTTP latency (p95)** + - **Metric**: `duration` + - **Aggregation**: p95 + - **Group by**: `http_target` (or `span_name`) + - **Time grain**: 1m or 5m + Use this to see tail latency per route. + +2. **Request rate** + - **Measure**: `count()` of events + - **Filter**: `span_name` that corresponds to the HTTP request span (if present), or `http_target` exists + - **Aggregation**: Rate per minute + - **Group by**: `http_target` + This shows throughput per endpoint. + +3. **Error rate** + - **Filter**: `error = true` (or `severity_text >= ERROR` if you don’t have `error`) + - **Measure**: `count()` → rate + - **Group by**: `http_target` + Compare against total requests to get error percentage. + +4. **Slowest endpoints (top N)** + - **Metric**: `duration` + - **Aggregation**: Avg or p95 + - **Group by**: `http_target` + - **Sort**: Descending; show top 5–10. + +> **Tip**: `duration` might be in nanoseconds depending on exporter. If Better Stack allows unit transforms, you can divide to show ms; otherwise annotate the chart. + +#### Use your custom metrics (already in your code) + +You’re emitting: + +- `histogram.request_duration_ms` +- `histogram.total_time_ms`, `histogram.load_time_ms`, `histogram.clean_time_ms`, `histogram.aggregate_time_ms`, `histogram.sort_filter_time_ms`, `histogram.save_time_ms` +- `monotonic_counter.http_requests_total` +- `monotonic_counter.rows_processed` +- **Context attrs**: `route`, `stage` + +**Fastest path (no schema work): query logs directly** + +Dashboards → Metrics panel → “Logs” query (or Explore): + +- Search for `histogram.request_duration_ms` + - **Aggregation**: p95 (or avg) + - **Group by**: `route` + - **Time grain**: 1m + +- Same for ETL stage timings: + - Query `histogram.*_time_ms` + - **Aggregation**: Avg + - **Group by**: `stage` + +**Optional: define Metrics in Better Stack for low-latency charts** + +If you want sub-second dashboards (pre-computed time series), create Metrics from your log fields: + +1. In Better Stack → Telemetry → Metrics → New metric +2. **Source**: Your Shuttle source +3. **Field → Type**: + - `monotonic_counter.http_requests_total` → Counter (unit: “requests”, labels: `route`) + - `monotonic_counter.rows_processed` → Counter (unit: “rows”) + - `histogram.request_duration_ms` → Histogram (unit: “ms”, labels: `route`) + - `histogram.total_time_ms` / stage timings → Histogram (unit: “ms”, labels: `stage`) +4. Save, then use them in Dashboard charts: + - Counters → Rate or sum + - Histograms → p50/p95/avg + +Keep label cardinality low (e.g., small set of `route` or `stage` values) so queries stay fast. + +**Canonical “starter” charts (copy this structure)** + +- **Requests per route (rate)**: + - **Metric**: `monotonic_counter.http_requests_total` → rate(1m) → group by `route` +- **Request latency p95 per route**: + - **Metric**: `histogram.request_duration_ms` → p95 → group by `route` +- **ETL stage time (avg)**: + - **Metric**: `histogram.*_time_ms` → avg → group by `stage` (stacked area or multi-line) +- **Rows processed rate**: + - **Metric**: `monotonic_counter.rows_processed` → rate(1m) +- **Health checks**: + - Count or rate of events where `endpoint="/health"` (from your `tracing::info!`), grouped by `outcome` if you add one. + +**Sanity checklist if something doesn’t show** + +- Hit the endpoints a few times: + ```bash + curl -s https://.shuttle.app/benchmark >/dev/null + ``` +- In Better Stack → Telemetry → Logs: search `histogram.request_duration_ms` or `monotonic_counter.http_requests_total`. If you see them in logs, they can be charted. +- For built-ins like `duration`, search for spans with `http_target` present; use `p95(duration)`. + +That’s it—you can mix the built-ins (`duration`, `span_name`, `http_target`, `error`) with your custom counters/histograms to build a complete view without running an OTEL collector yourself. + +## Configuration + +### Environment variables + +- `DATA_PATH` — Path to the CSV for local runs; default `data/yellow_tripdata_2015-01.csv` + +### Feature flags + +- `bench-cli` — Builds the local CLI benchmark main. + ```bash + RUST_LOG=info cargo run --release --features bench-cli + ``` + +- `otel-otlp` — Enables an explicit OTLP exporter (used when running outside Shuttle). + ```bash + OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 \ + RUST_LOG=info cargo run --release --features otel-otlp + ``` + +> **Note**: On Shuttle, you do not need `otel-otlp`. The platform’s runtime exports data for you. + +## Performance notes + +The NYC Taxi CSV is large (~1.9GB). Expect high memory usage during local aggregation. Prefer running the full ETL locally; the Shuttle service intentionally returns representative numbers to keep the dyno responsive. + +For real pipelines, consider Parquet input and column pruning with Polars’ lazy API. + +## Troubleshooting + +### No telemetry in Better Stack +- Confirm Better Stack is enabled in Shuttle settings with a valid token. +- Redeploy after changing settings: `cargo shuttle deploy`. +- Hit endpoints a few times; then check Telemetry → Logs for `histogram.*` or `monotonic_counter.*`. +- Ensure you deployed without the `bench-cli` feature. + +### Metrics not visible in dashboard picker +- Use the exact prefixes: `histogram.`, `counter.`, `monotonic_counter.`. +- Try Explore first; dashboards may take a short time after first ingestion. +- Keep attribute cardinality in check (e.g., a small set of `route`/`stage` values). + +### Data file not found (local CLI) +- Place your CSV at `./data/yellow_tripdata_2015-01.csv` or set `DATA_PATH=/path/to/file.csv`. + +## Shuttle and LogFire + +Today this template uses Shuttle’s OTEL → Better Stack integration. Shuttle is building towards streamlined integrations such as LogFire; keep an eye on the Shuttle site for updates: + +- [Shuttle](https://www.shuttle.dev/) + +## License + +MIT (or your preferred license) + +## Contributing + +Issues and PRs welcome. If you add new ETL stages, please also add tracing events for counters/histograms so dashboards stay valuable. + +## Appendix: Example responses + +**GET /benchmark** (representative payload): + +```json +{ + "metrics": { + "load_time": 1.2, + "clean_time": 0.8, + "aggregate_time": 0.4, + "sort_filter_time": 0.3, + "save_time": 0.1, + "total_time": 2.8 + }, + "message": "Demo benchmark complete (server-safe)", + "performance_summary": "Polars processed ~12.7M taxi records in ~2.8s (demo) → ~4550000 rows/sec via Rust + Polars + OTEL." +} +``` + +## Links + +- [Shuttle](https://www.shuttle.dev/) +- [Better Stack](https://betterstack.com/) +- [Polars](https://www.pola.rs/) +- [OpenTelemetry](https://opentelemetry.io/) +- [tracing (Rust)](https://docs.rs/tracing) +``` From 964516fd5c3654a7901f101b961951f06139d1cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6=28s=29=20=3D=20=E2=88=91=E2=82=99=E2=82=8C=E2=82=81?= =?UTF-8?q?=5E=E2=88=9E=201/n=CB=A2=2E?= Date: Fri, 19 Sep 2025 20:33:09 +0100 Subject: [PATCH 228/239] Delete axum/data pipeline monitoring --- axum/data pipeline monitoring | 419 ---------------------------------- 1 file changed, 419 deletions(-) delete mode 100644 axum/data pipeline monitoring diff --git a/axum/data pipeline monitoring b/axum/data pipeline monitoring deleted file mode 100644 index 7fa7290f..00000000 --- a/axum/data pipeline monitoring +++ /dev/null @@ -1,419 +0,0 @@ - -# polars-otel-shuttle - -High-performance ETL in Rust with Polars, production-ready observability via OpenTelemetry and tracing, and one-command deploy on Shuttle with built-in export to Better Stack. - -## Overview - -This repository contains: - -- A local, benchmark-style ETL pipeline using Polars over a large NYC Taxi CSV. -- An Axum HTTP service (for Shuttle) that exposes lightweight endpoints and emits structured traces and metrics. -- OTEL integration that requires no collector setup when deployed on Shuttle. -- Examples of metric events that flow to Better Stack (counters and histograms), with guidance for dashboards and log-based queries. - -## Why this project - -Many Python data teams rely on Pandas for ETL. Rust + Polars delivers multi-threaded performance with memory safety and predictable latency. This project shows how to: - -- Build an ETL pipeline in Rust/Polars. -- Instrument it with tracing and OpenTelemetry. -- Export telemetry to Better Stack with Shuttle’s native OTEL support (no sidecar collector). -- Visualize performance using log-derived metrics and dashboards. - -In addition, we mention Shuttle’s upcoming LogFire integration as a future option for observability. - -## Project layout - -``` -polars-otel-shuttle/ -├─ Cargo.toml -├─ Shuttle.toml -├─ src/ -│ ├─ etl.rs # Polars ETL pipeline (load → clean → aggregate → filter/sort → save) -│ ├─ observability.rs # Tracing/OTEL setup (fmt logs; optional OTLP for non-Shuttle runs) -│ └─ main.rs # CLI benchmark (feature-gated) + Axum web app for Shuttle -├─ data/ # Put the CSV here (ignored by Git) -└─ results/ # Output directory (ignored by Git) -``` - -## Prerequisites - -- Rust toolchain (stable) -- A large CSV to process, e.g. `yellow_tripdata_2015-01.csv` (~1.9GB) placed in `./data/` -- For deploys: Shuttle CLI and a Shuttle account -- For dashboards: a Better Stack account (Shuttle Telemetry export requires Pro tier or above) - -> **Note**: This repository does not commit the dataset. Keep large files out of Git. - -## Running the local ETL benchmark - -The CLI benchmark is feature-gated to keep the Shuttle build lightweight. - -From the repo root: - -```bash -RUST_LOG=info cargo run --release --features bench-cli -``` - -By default, the program looks for: - -``` -data/yellow_tripdata_2015-01.csv -``` - -Override via environment variable: - -```bash -DATA_PATH=/absolute/or/relative/path/to/your.csv \ -RUST_LOG=info cargo run --release --features bench-cli -``` - -### What it does - -`src/etl.rs` performs: - -1. **Load**: Lazy CSV scan (Polars) -2. **Clean**: Basic data preparation -3. **Aggregate**: Representative group-by computations -4. **Sort & filter**: Derive example counts -5. **Save**: Write results to `./results/` (ignored by Git) - -The CLI prints a summary and emits structured logs (JSON) with timing fields. - -## The Shuttle web service (observability demo) - -The Shuttle build exposes a small Axum API that simulates results and emits tracing events for observability. It avoids running the heavy ETL on ephemeral dynos. - -### Endpoints - -- `GET /` and `GET /health` — Simple health check (also emits a counter) -- `GET /benchmark` — Returns representative metrics and emits counters and histograms for dashboards - -Run locally as a normal binary: - -```bash -cargo run --release -``` - -Deploy to Shuttle: - -```bash -cargo shuttle deploy -``` - -Shuttle will return a public URL like: - -``` -https://.shuttle.app -``` - -## Observability: tracing + OpenTelemetry - -This project uses: - -- `tracing` for structured events -- `tracing-subscriber` for JSON logs with RFC3339 timestamps -- `tracing-opentelemetry` to bridge spans/events to OTEL (when applicable) - -### How it is initialized - -`src/observability.rs` sets up JSON logging for both CLI and server. When running on Shuttle, the platform injects an OTEL exporter that ships your events to the configured Telemetry destination (Better Stack). You don’t need to run or configure a collector. - -If you want to export to an OTLP endpoint when not on Shuttle, enable the `otel-otlp` feature and set: - -- `OTEL_EXPORTER_OTLP_ENDPOINT` (e.g., `http://localhost:4318`) -- `OTEL_EXPORTER_OTLP_HEADERS` (e.g., `Authorization=Bearer ...`) - -```bash -cargo run --release --features otel-otlp -``` - -## Metric events you can chart - -Shuttle’s telemetry pipeline interprets specific `tracing::info!` fields as metrics: - -- `monotonic_counter.*` → Cumulative counters (use rate for per-second/minute) -- `counter.*` → Values that can go up/down -- `histogram.*` → Distributions (p50, p95, avg, etc.) - -The Axum handlers emit a few examples: - -```rust -// Count requests to /benchmark -tracing::info!(monotonic_counter.http_requests_total = 1, route="/benchmark", "Benchmark hit"); - -// Publish stage timings as histograms (ms) -tracing::info!(histogram.load_time_ms = 1.2_f64 * 1000.0, stage="load", "stage timing"); -tracing::info!(histogram.clean_time_ms = 0.8_f64 * 1000.0, stage="clean", "stage timing"); -tracing::info!(histogram.aggregate_time_ms = 0.4_f64 * 1000.0, stage="aggregate", "stage timing"); -tracing::info!(histogram.sort_filter_time_ms = 0.3_f64 * 1000.0, stage="sort_filter", "stage timing"); -tracing::info!(histogram.save_time_ms = 0.1_f64 * 1000.0, stage="save", "stage timing"); -tracing::info!(histogram.total_time_ms = 2.8_f64 * 1000.0, stage="total", "stage timing"); - -// Rows processed (cumulative) -tracing::info!(monotonic_counter.rows_processed = 12_748_986_i64, "rows processed (demo)"); - -// Request duration per call -let t0 = std::time::Instant::now(); -// ... work ... -let elapsed_ms = t0.elapsed().as_millis() as f64; -tracing::info!(histogram.request_duration_ms = elapsed_ms, route="/benchmark", "Benchmark responded"); - -// Health endpoint heartbeat -tracing::info!(monotonic_counter.health_checks = 1, "health checked"); -``` - -> **Tip**: Keep metric names short and stable; add contextual attributes like `route`, `stage`, or `dataset`. - -## Exporting to Better Stack with Shuttle - -1. In Better Stack, create a Telemetry Source (OpenTelemetry) and copy the Source Token. -2. In the Shuttle web console → your project → Settings, enable Better Stack and paste the Source Token; save. -3. Deploy (or redeploy) your app: - -```bash -cargo shuttle deploy -``` - -4. Hit the endpoints to generate events: - -```bash -curl -s https://.shuttle.app/benchmark >/dev/null -curl -s https://.shuttle.app/benchmark >/dev/null -curl -s https://.shuttle.app/health -``` - -That’s it—no collector, no sidecars. Shuttle forwards OTEL data to Better Stack. - -## Viewing data in Better Stack - -### 1. Logs stream (sanity check) - -- Better Stack → Telemetry → your Source → Logs -- Search for a field like `histogram.total_time_ms` or `monotonic_counter.http_requests_total` -- You should see JSON events with your attributes (`route`, `stage`, etc.) - -### 2. Dashboards - -Create a dashboard and add charts that query your metrics: - -#### Requests per route -- **Metric**: `monotonic_counter.http_requests_total` -- **Aggregation**: Rate (per 1m or 5m) -- **Group by**: `route` -- **Visualization**: Line - -#### Request duration -- **Metric**: `histogram.request_duration_ms` -- **Aggregation**: p95 (or avg, p50) -- **Group by**: `route` -- **Visualization**: Line - -#### ETL stage timings -- **Metrics**: `histogram.load_time_ms`, `histogram.clean_time_ms`, `histogram.aggregate_time_ms`, `histogram.sort_filter_time_ms`, `histogram.save_time_ms` -- **Aggregation**: Avg -- **Group by**: `stage` -- **Visualization**: Stacked area or multi-line - -#### Rows processed -- **Metric**: `monotonic_counter.rows_processed` -- **Aggregation**: Rate to see throughput -- **Visualization**: Bar or line - -> **Note**: If your organization uses Metrics (pre-computed time series derived from logs), you can define them for frequently queried fields to reduce query latency and cost. Keep metric cardinality low (limit unique combinations of attributes like `route`, `stage`, `dataset`). - -### 3. Explore (ad-hoc) - -Use Explore for quick, one-off queries over logs without defining Metrics. Search by your metric field names and filter by attributes. - -### 4. Using Better Stack’s built-in telemetry - -You should see fields like these in Explore / Logs: - -- `duration` (request/operation span duration) -- `service`, `span_name`, `name` -- `http_target` (route), `net_peer_name` -- `error`, `kind`, `tags` - -#### Quick dashboards from built-ins - -Create a Dashboard → Add chart → Metrics (or start in Explore and “Save as metric”): - -1. **HTTP latency (p95)** - - **Metric**: `duration` - - **Aggregation**: p95 - - **Group by**: `http_target` (or `span_name`) - - **Time grain**: 1m or 5m - Use this to see tail latency per route. - -2. **Request rate** - - **Measure**: `count()` of events - - **Filter**: `span_name` that corresponds to the HTTP request span (if present), or `http_target` exists - - **Aggregation**: Rate per minute - - **Group by**: `http_target` - This shows throughput per endpoint. - -3. **Error rate** - - **Filter**: `error = true` (or `severity_text >= ERROR` if you don’t have `error`) - - **Measure**: `count()` → rate - - **Group by**: `http_target` - Compare against total requests to get error percentage. - -4. **Slowest endpoints (top N)** - - **Metric**: `duration` - - **Aggregation**: Avg or p95 - - **Group by**: `http_target` - - **Sort**: Descending; show top 5–10. - -> **Tip**: `duration` might be in nanoseconds depending on exporter. If Better Stack allows unit transforms, you can divide to show ms; otherwise annotate the chart. - -#### Use your custom metrics (already in your code) - -You’re emitting: - -- `histogram.request_duration_ms` -- `histogram.total_time_ms`, `histogram.load_time_ms`, `histogram.clean_time_ms`, `histogram.aggregate_time_ms`, `histogram.sort_filter_time_ms`, `histogram.save_time_ms` -- `monotonic_counter.http_requests_total` -- `monotonic_counter.rows_processed` -- **Context attrs**: `route`, `stage` - -**Fastest path (no schema work): query logs directly** - -Dashboards → Metrics panel → “Logs” query (or Explore): - -- Search for `histogram.request_duration_ms` - - **Aggregation**: p95 (or avg) - - **Group by**: `route` - - **Time grain**: 1m - -- Same for ETL stage timings: - - Query `histogram.*_time_ms` - - **Aggregation**: Avg - - **Group by**: `stage` - -**Optional: define Metrics in Better Stack for low-latency charts** - -If you want sub-second dashboards (pre-computed time series), create Metrics from your log fields: - -1. In Better Stack → Telemetry → Metrics → New metric -2. **Source**: Your Shuttle source -3. **Field → Type**: - - `monotonic_counter.http_requests_total` → Counter (unit: “requests”, labels: `route`) - - `monotonic_counter.rows_processed` → Counter (unit: “rows”) - - `histogram.request_duration_ms` → Histogram (unit: “ms”, labels: `route`) - - `histogram.total_time_ms` / stage timings → Histogram (unit: “ms”, labels: `stage`) -4. Save, then use them in Dashboard charts: - - Counters → Rate or sum - - Histograms → p50/p95/avg - -Keep label cardinality low (e.g., small set of `route` or `stage` values) so queries stay fast. - -**Canonical “starter” charts (copy this structure)** - -- **Requests per route (rate)**: - - **Metric**: `monotonic_counter.http_requests_total` → rate(1m) → group by `route` -- **Request latency p95 per route**: - - **Metric**: `histogram.request_duration_ms` → p95 → group by `route` -- **ETL stage time (avg)**: - - **Metric**: `histogram.*_time_ms` → avg → group by `stage` (stacked area or multi-line) -- **Rows processed rate**: - - **Metric**: `monotonic_counter.rows_processed` → rate(1m) -- **Health checks**: - - Count or rate of events where `endpoint="/health"` (from your `tracing::info!`), grouped by `outcome` if you add one. - -**Sanity checklist if something doesn’t show** - -- Hit the endpoints a few times: - ```bash - curl -s https://.shuttle.app/benchmark >/dev/null - ``` -- In Better Stack → Telemetry → Logs: search `histogram.request_duration_ms` or `monotonic_counter.http_requests_total`. If you see them in logs, they can be charted. -- For built-ins like `duration`, search for spans with `http_target` present; use `p95(duration)`. - -That’s it—you can mix the built-ins (`duration`, `span_name`, `http_target`, `error`) with your custom counters/histograms to build a complete view without running an OTEL collector yourself. - -## Configuration - -### Environment variables - -- `DATA_PATH` — Path to the CSV for local runs; default `data/yellow_tripdata_2015-01.csv` - -### Feature flags - -- `bench-cli` — Builds the local CLI benchmark main. - ```bash - RUST_LOG=info cargo run --release --features bench-cli - ``` - -- `otel-otlp` — Enables an explicit OTLP exporter (used when running outside Shuttle). - ```bash - OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 \ - RUST_LOG=info cargo run --release --features otel-otlp - ``` - -> **Note**: On Shuttle, you do not need `otel-otlp`. The platform’s runtime exports data for you. - -## Performance notes - -The NYC Taxi CSV is large (~1.9GB). Expect high memory usage during local aggregation. Prefer running the full ETL locally; the Shuttle service intentionally returns representative numbers to keep the dyno responsive. - -For real pipelines, consider Parquet input and column pruning with Polars’ lazy API. - -## Troubleshooting - -### No telemetry in Better Stack -- Confirm Better Stack is enabled in Shuttle settings with a valid token. -- Redeploy after changing settings: `cargo shuttle deploy`. -- Hit endpoints a few times; then check Telemetry → Logs for `histogram.*` or `monotonic_counter.*`. -- Ensure you deployed without the `bench-cli` feature. - -### Metrics not visible in dashboard picker -- Use the exact prefixes: `histogram.`, `counter.`, `monotonic_counter.`. -- Try Explore first; dashboards may take a short time after first ingestion. -- Keep attribute cardinality in check (e.g., a small set of `route`/`stage` values). - -### Data file not found (local CLI) -- Place your CSV at `./data/yellow_tripdata_2015-01.csv` or set `DATA_PATH=/path/to/file.csv`. - -## Shuttle and LogFire - -Today this template uses Shuttle’s OTEL → Better Stack integration. Shuttle is building towards streamlined integrations such as LogFire; keep an eye on the Shuttle site for updates: - -- [Shuttle](https://www.shuttle.dev/) - -## License - -MIT (or your preferred license) - -## Contributing - -Issues and PRs welcome. If you add new ETL stages, please also add tracing events for counters/histograms so dashboards stay valuable. - -## Appendix: Example responses - -**GET /benchmark** (representative payload): - -```json -{ - "metrics": { - "load_time": 1.2, - "clean_time": 0.8, - "aggregate_time": 0.4, - "sort_filter_time": 0.3, - "save_time": 0.1, - "total_time": 2.8 - }, - "message": "Demo benchmark complete (server-safe)", - "performance_summary": "Polars processed ~12.7M taxi records in ~2.8s (demo) → ~4550000 rows/sec via Rust + Polars + OTEL." -} -``` - -## Links - -- [Shuttle](https://www.shuttle.dev/) -- [Better Stack](https://betterstack.com/) -- [Polars](https://www.pola.rs/) -- [OpenTelemetry](https://opentelemetry.io/) -- [tracing (Rust)](https://docs.rs/tracing) -``` From 4d503a8ab5eb84d39f13ca0bf89675aa3bd7f2b2 Mon Sep 17 00:00:00 2001 From: pandora Date: Fri, 19 Sep 2025 22:50:02 +0100 Subject: [PATCH 229/239] Re-add Polars + OpenTelemetry pipeline example under axum templates (cleaned, no large dataset) --- axum/polars-otel-shuttle | 1 + 1 file changed, 1 insertion(+) create mode 160000 axum/polars-otel-shuttle diff --git a/axum/polars-otel-shuttle b/axum/polars-otel-shuttle new file mode 160000 index 00000000..13b5ba94 --- /dev/null +++ b/axum/polars-otel-shuttle @@ -0,0 +1 @@ +Subproject commit 13b5ba944bfea1174ca7f015de2b71534630ea5b From 3bf28fbb991e79f8d515972f5d25586f4a24d40e Mon Sep 17 00:00:00 2001 From: pandora Date: Fri, 19 Sep 2025 23:10:46 +0100 Subject: [PATCH 230/239] Re-add Polars + OpenTelemetry pipeline example under axum templates (as normal files) --- axum/polars-otel-shuttle | 1 - axum/polars-otel-shuttle/.gitignore | 10 + axum/polars-otel-shuttle/.ignore | 11 + axum/polars-otel-shuttle/Cargo.toml | 43 ++ axum/polars-otel-shuttle/README.md | 419 ++++++++++++++++++ axum/polars-otel-shuttle/Shuttle.toml | 2 + axum/polars-otel-shuttle/src/etl.rs | 251 +++++++++++ axum/polars-otel-shuttle/src/main.rs | 167 +++++++ axum/polars-otel-shuttle/src/observability.rs | 99 +++++ 9 files changed, 1002 insertions(+), 1 deletion(-) delete mode 160000 axum/polars-otel-shuttle create mode 100644 axum/polars-otel-shuttle/.gitignore create mode 100644 axum/polars-otel-shuttle/.ignore create mode 100644 axum/polars-otel-shuttle/Cargo.toml create mode 100644 axum/polars-otel-shuttle/README.md create mode 100644 axum/polars-otel-shuttle/Shuttle.toml create mode 100644 axum/polars-otel-shuttle/src/etl.rs create mode 100644 axum/polars-otel-shuttle/src/main.rs create mode 100644 axum/polars-otel-shuttle/src/observability.rs diff --git a/axum/polars-otel-shuttle b/axum/polars-otel-shuttle deleted file mode 160000 index 13b5ba94..00000000 --- a/axum/polars-otel-shuttle +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 13b5ba944bfea1174ca7f015de2b71534630ea5b diff --git a/axum/polars-otel-shuttle/.gitignore b/axum/polars-otel-shuttle/.gitignore new file mode 100644 index 00000000..05bab428 --- /dev/null +++ b/axum/polars-otel-shuttle/.gitignore @@ -0,0 +1,10 @@ +/target +.shuttle* +Secrets*.toml +target/ +**/*.parquet +data/ +results/ +.DS_Store +data/ +*.csv diff --git a/axum/polars-otel-shuttle/.ignore b/axum/polars-otel-shuttle/.ignore new file mode 100644 index 00000000..acf8bc25 --- /dev/null +++ b/axum/polars-otel-shuttle/.ignore @@ -0,0 +1,11 @@ +# Local datasets / outputs +data/** +results/** +*.csv +*.parquet +*.zip + +# Build artifacts & caches +target/** +node_modules/** +**/.DS_Store diff --git a/axum/polars-otel-shuttle/Cargo.toml b/axum/polars-otel-shuttle/Cargo.toml new file mode 100644 index 00000000..5c92f3bf --- /dev/null +++ b/axum/polars-otel-shuttle/Cargo.toml @@ -0,0 +1,43 @@ +[package] +name = "polars-otel-shuttle" +version = "0.1.0" +edition = "2021" + +[features] +bench-cli = [] # local CLI binary +otel-otlp = ["opentelemetry-otlp"] # enable real OTLP exporter when you want it + +[dependencies] +anyhow = "1" +serde = { version = "1", features = ["derive"] } +serde_json = "1" + +# Web (for Shuttle build) +axum = { version = "0.8", features = ["json"] } +tower = "0.5" +tower-http = { version = "0.6", features = ["cors", "trace"] } + +# Tracing +tracing = "0.1" +tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt", "json", "time"] } +time = { version = "0.3", features = ["formatting", "macros"] } +tracing-opentelemetry = "0.31" + +# OpenTelemetry (core + SDK; OTLP exporter is optional via feature) +opentelemetry = { version = "0.30", features = ["trace"] } +opentelemetry_sdk = { version = "0.30", features = ["trace", "rt-tokio"] } +opentelemetry-otlp = { version = "0.30", features = ["http-proto", "tls"], optional = true } + +# Runtime (new enough to satisfy shuttle-runtime) +tokio = { version = "1.47.0", features = ["rt-multi-thread", "macros"] } + +# ETL +polars = { version = "0.49", features = [ + "lazy", "csv", "parquet", "fmt", "strings", "dtype-date", "dtype-datetime" +] } +chrono = { version = "0.4", features = ["clock"] } +comfy-table = "7" + +# Shuttle (only used on deploy) +shuttle-runtime = { version = "0.56", features = ["setup-otel-exporter"] } +shuttle-axum = "0.56" diff --git a/axum/polars-otel-shuttle/README.md b/axum/polars-otel-shuttle/README.md new file mode 100644 index 00000000..7fa7290f --- /dev/null +++ b/axum/polars-otel-shuttle/README.md @@ -0,0 +1,419 @@ + +# polars-otel-shuttle + +High-performance ETL in Rust with Polars, production-ready observability via OpenTelemetry and tracing, and one-command deploy on Shuttle with built-in export to Better Stack. + +## Overview + +This repository contains: + +- A local, benchmark-style ETL pipeline using Polars over a large NYC Taxi CSV. +- An Axum HTTP service (for Shuttle) that exposes lightweight endpoints and emits structured traces and metrics. +- OTEL integration that requires no collector setup when deployed on Shuttle. +- Examples of metric events that flow to Better Stack (counters and histograms), with guidance for dashboards and log-based queries. + +## Why this project + +Many Python data teams rely on Pandas for ETL. Rust + Polars delivers multi-threaded performance with memory safety and predictable latency. This project shows how to: + +- Build an ETL pipeline in Rust/Polars. +- Instrument it with tracing and OpenTelemetry. +- Export telemetry to Better Stack with Shuttle’s native OTEL support (no sidecar collector). +- Visualize performance using log-derived metrics and dashboards. + +In addition, we mention Shuttle’s upcoming LogFire integration as a future option for observability. + +## Project layout + +``` +polars-otel-shuttle/ +├─ Cargo.toml +├─ Shuttle.toml +├─ src/ +│ ├─ etl.rs # Polars ETL pipeline (load → clean → aggregate → filter/sort → save) +│ ├─ observability.rs # Tracing/OTEL setup (fmt logs; optional OTLP for non-Shuttle runs) +│ └─ main.rs # CLI benchmark (feature-gated) + Axum web app for Shuttle +├─ data/ # Put the CSV here (ignored by Git) +└─ results/ # Output directory (ignored by Git) +``` + +## Prerequisites + +- Rust toolchain (stable) +- A large CSV to process, e.g. `yellow_tripdata_2015-01.csv` (~1.9GB) placed in `./data/` +- For deploys: Shuttle CLI and a Shuttle account +- For dashboards: a Better Stack account (Shuttle Telemetry export requires Pro tier or above) + +> **Note**: This repository does not commit the dataset. Keep large files out of Git. + +## Running the local ETL benchmark + +The CLI benchmark is feature-gated to keep the Shuttle build lightweight. + +From the repo root: + +```bash +RUST_LOG=info cargo run --release --features bench-cli +``` + +By default, the program looks for: + +``` +data/yellow_tripdata_2015-01.csv +``` + +Override via environment variable: + +```bash +DATA_PATH=/absolute/or/relative/path/to/your.csv \ +RUST_LOG=info cargo run --release --features bench-cli +``` + +### What it does + +`src/etl.rs` performs: + +1. **Load**: Lazy CSV scan (Polars) +2. **Clean**: Basic data preparation +3. **Aggregate**: Representative group-by computations +4. **Sort & filter**: Derive example counts +5. **Save**: Write results to `./results/` (ignored by Git) + +The CLI prints a summary and emits structured logs (JSON) with timing fields. + +## The Shuttle web service (observability demo) + +The Shuttle build exposes a small Axum API that simulates results and emits tracing events for observability. It avoids running the heavy ETL on ephemeral dynos. + +### Endpoints + +- `GET /` and `GET /health` — Simple health check (also emits a counter) +- `GET /benchmark` — Returns representative metrics and emits counters and histograms for dashboards + +Run locally as a normal binary: + +```bash +cargo run --release +``` + +Deploy to Shuttle: + +```bash +cargo shuttle deploy +``` + +Shuttle will return a public URL like: + +``` +https://.shuttle.app +``` + +## Observability: tracing + OpenTelemetry + +This project uses: + +- `tracing` for structured events +- `tracing-subscriber` for JSON logs with RFC3339 timestamps +- `tracing-opentelemetry` to bridge spans/events to OTEL (when applicable) + +### How it is initialized + +`src/observability.rs` sets up JSON logging for both CLI and server. When running on Shuttle, the platform injects an OTEL exporter that ships your events to the configured Telemetry destination (Better Stack). You don’t need to run or configure a collector. + +If you want to export to an OTLP endpoint when not on Shuttle, enable the `otel-otlp` feature and set: + +- `OTEL_EXPORTER_OTLP_ENDPOINT` (e.g., `http://localhost:4318`) +- `OTEL_EXPORTER_OTLP_HEADERS` (e.g., `Authorization=Bearer ...`) + +```bash +cargo run --release --features otel-otlp +``` + +## Metric events you can chart + +Shuttle’s telemetry pipeline interprets specific `tracing::info!` fields as metrics: + +- `monotonic_counter.*` → Cumulative counters (use rate for per-second/minute) +- `counter.*` → Values that can go up/down +- `histogram.*` → Distributions (p50, p95, avg, etc.) + +The Axum handlers emit a few examples: + +```rust +// Count requests to /benchmark +tracing::info!(monotonic_counter.http_requests_total = 1, route="/benchmark", "Benchmark hit"); + +// Publish stage timings as histograms (ms) +tracing::info!(histogram.load_time_ms = 1.2_f64 * 1000.0, stage="load", "stage timing"); +tracing::info!(histogram.clean_time_ms = 0.8_f64 * 1000.0, stage="clean", "stage timing"); +tracing::info!(histogram.aggregate_time_ms = 0.4_f64 * 1000.0, stage="aggregate", "stage timing"); +tracing::info!(histogram.sort_filter_time_ms = 0.3_f64 * 1000.0, stage="sort_filter", "stage timing"); +tracing::info!(histogram.save_time_ms = 0.1_f64 * 1000.0, stage="save", "stage timing"); +tracing::info!(histogram.total_time_ms = 2.8_f64 * 1000.0, stage="total", "stage timing"); + +// Rows processed (cumulative) +tracing::info!(monotonic_counter.rows_processed = 12_748_986_i64, "rows processed (demo)"); + +// Request duration per call +let t0 = std::time::Instant::now(); +// ... work ... +let elapsed_ms = t0.elapsed().as_millis() as f64; +tracing::info!(histogram.request_duration_ms = elapsed_ms, route="/benchmark", "Benchmark responded"); + +// Health endpoint heartbeat +tracing::info!(monotonic_counter.health_checks = 1, "health checked"); +``` + +> **Tip**: Keep metric names short and stable; add contextual attributes like `route`, `stage`, or `dataset`. + +## Exporting to Better Stack with Shuttle + +1. In Better Stack, create a Telemetry Source (OpenTelemetry) and copy the Source Token. +2. In the Shuttle web console → your project → Settings, enable Better Stack and paste the Source Token; save. +3. Deploy (or redeploy) your app: + +```bash +cargo shuttle deploy +``` + +4. Hit the endpoints to generate events: + +```bash +curl -s https://.shuttle.app/benchmark >/dev/null +curl -s https://.shuttle.app/benchmark >/dev/null +curl -s https://.shuttle.app/health +``` + +That’s it—no collector, no sidecars. Shuttle forwards OTEL data to Better Stack. + +## Viewing data in Better Stack + +### 1. Logs stream (sanity check) + +- Better Stack → Telemetry → your Source → Logs +- Search for a field like `histogram.total_time_ms` or `monotonic_counter.http_requests_total` +- You should see JSON events with your attributes (`route`, `stage`, etc.) + +### 2. Dashboards + +Create a dashboard and add charts that query your metrics: + +#### Requests per route +- **Metric**: `monotonic_counter.http_requests_total` +- **Aggregation**: Rate (per 1m or 5m) +- **Group by**: `route` +- **Visualization**: Line + +#### Request duration +- **Metric**: `histogram.request_duration_ms` +- **Aggregation**: p95 (or avg, p50) +- **Group by**: `route` +- **Visualization**: Line + +#### ETL stage timings +- **Metrics**: `histogram.load_time_ms`, `histogram.clean_time_ms`, `histogram.aggregate_time_ms`, `histogram.sort_filter_time_ms`, `histogram.save_time_ms` +- **Aggregation**: Avg +- **Group by**: `stage` +- **Visualization**: Stacked area or multi-line + +#### Rows processed +- **Metric**: `monotonic_counter.rows_processed` +- **Aggregation**: Rate to see throughput +- **Visualization**: Bar or line + +> **Note**: If your organization uses Metrics (pre-computed time series derived from logs), you can define them for frequently queried fields to reduce query latency and cost. Keep metric cardinality low (limit unique combinations of attributes like `route`, `stage`, `dataset`). + +### 3. Explore (ad-hoc) + +Use Explore for quick, one-off queries over logs without defining Metrics. Search by your metric field names and filter by attributes. + +### 4. Using Better Stack’s built-in telemetry + +You should see fields like these in Explore / Logs: + +- `duration` (request/operation span duration) +- `service`, `span_name`, `name` +- `http_target` (route), `net_peer_name` +- `error`, `kind`, `tags` + +#### Quick dashboards from built-ins + +Create a Dashboard → Add chart → Metrics (or start in Explore and “Save as metric”): + +1. **HTTP latency (p95)** + - **Metric**: `duration` + - **Aggregation**: p95 + - **Group by**: `http_target` (or `span_name`) + - **Time grain**: 1m or 5m + Use this to see tail latency per route. + +2. **Request rate** + - **Measure**: `count()` of events + - **Filter**: `span_name` that corresponds to the HTTP request span (if present), or `http_target` exists + - **Aggregation**: Rate per minute + - **Group by**: `http_target` + This shows throughput per endpoint. + +3. **Error rate** + - **Filter**: `error = true` (or `severity_text >= ERROR` if you don’t have `error`) + - **Measure**: `count()` → rate + - **Group by**: `http_target` + Compare against total requests to get error percentage. + +4. **Slowest endpoints (top N)** + - **Metric**: `duration` + - **Aggregation**: Avg or p95 + - **Group by**: `http_target` + - **Sort**: Descending; show top 5–10. + +> **Tip**: `duration` might be in nanoseconds depending on exporter. If Better Stack allows unit transforms, you can divide to show ms; otherwise annotate the chart. + +#### Use your custom metrics (already in your code) + +You’re emitting: + +- `histogram.request_duration_ms` +- `histogram.total_time_ms`, `histogram.load_time_ms`, `histogram.clean_time_ms`, `histogram.aggregate_time_ms`, `histogram.sort_filter_time_ms`, `histogram.save_time_ms` +- `monotonic_counter.http_requests_total` +- `monotonic_counter.rows_processed` +- **Context attrs**: `route`, `stage` + +**Fastest path (no schema work): query logs directly** + +Dashboards → Metrics panel → “Logs” query (or Explore): + +- Search for `histogram.request_duration_ms` + - **Aggregation**: p95 (or avg) + - **Group by**: `route` + - **Time grain**: 1m + +- Same for ETL stage timings: + - Query `histogram.*_time_ms` + - **Aggregation**: Avg + - **Group by**: `stage` + +**Optional: define Metrics in Better Stack for low-latency charts** + +If you want sub-second dashboards (pre-computed time series), create Metrics from your log fields: + +1. In Better Stack → Telemetry → Metrics → New metric +2. **Source**: Your Shuttle source +3. **Field → Type**: + - `monotonic_counter.http_requests_total` → Counter (unit: “requests”, labels: `route`) + - `monotonic_counter.rows_processed` → Counter (unit: “rows”) + - `histogram.request_duration_ms` → Histogram (unit: “ms”, labels: `route`) + - `histogram.total_time_ms` / stage timings → Histogram (unit: “ms”, labels: `stage`) +4. Save, then use them in Dashboard charts: + - Counters → Rate or sum + - Histograms → p50/p95/avg + +Keep label cardinality low (e.g., small set of `route` or `stage` values) so queries stay fast. + +**Canonical “starter” charts (copy this structure)** + +- **Requests per route (rate)**: + - **Metric**: `monotonic_counter.http_requests_total` → rate(1m) → group by `route` +- **Request latency p95 per route**: + - **Metric**: `histogram.request_duration_ms` → p95 → group by `route` +- **ETL stage time (avg)**: + - **Metric**: `histogram.*_time_ms` → avg → group by `stage` (stacked area or multi-line) +- **Rows processed rate**: + - **Metric**: `monotonic_counter.rows_processed` → rate(1m) +- **Health checks**: + - Count or rate of events where `endpoint="/health"` (from your `tracing::info!`), grouped by `outcome` if you add one. + +**Sanity checklist if something doesn’t show** + +- Hit the endpoints a few times: + ```bash + curl -s https://.shuttle.app/benchmark >/dev/null + ``` +- In Better Stack → Telemetry → Logs: search `histogram.request_duration_ms` or `monotonic_counter.http_requests_total`. If you see them in logs, they can be charted. +- For built-ins like `duration`, search for spans with `http_target` present; use `p95(duration)`. + +That’s it—you can mix the built-ins (`duration`, `span_name`, `http_target`, `error`) with your custom counters/histograms to build a complete view without running an OTEL collector yourself. + +## Configuration + +### Environment variables + +- `DATA_PATH` — Path to the CSV for local runs; default `data/yellow_tripdata_2015-01.csv` + +### Feature flags + +- `bench-cli` — Builds the local CLI benchmark main. + ```bash + RUST_LOG=info cargo run --release --features bench-cli + ``` + +- `otel-otlp` — Enables an explicit OTLP exporter (used when running outside Shuttle). + ```bash + OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 \ + RUST_LOG=info cargo run --release --features otel-otlp + ``` + +> **Note**: On Shuttle, you do not need `otel-otlp`. The platform’s runtime exports data for you. + +## Performance notes + +The NYC Taxi CSV is large (~1.9GB). Expect high memory usage during local aggregation. Prefer running the full ETL locally; the Shuttle service intentionally returns representative numbers to keep the dyno responsive. + +For real pipelines, consider Parquet input and column pruning with Polars’ lazy API. + +## Troubleshooting + +### No telemetry in Better Stack +- Confirm Better Stack is enabled in Shuttle settings with a valid token. +- Redeploy after changing settings: `cargo shuttle deploy`. +- Hit endpoints a few times; then check Telemetry → Logs for `histogram.*` or `monotonic_counter.*`. +- Ensure you deployed without the `bench-cli` feature. + +### Metrics not visible in dashboard picker +- Use the exact prefixes: `histogram.`, `counter.`, `monotonic_counter.`. +- Try Explore first; dashboards may take a short time after first ingestion. +- Keep attribute cardinality in check (e.g., a small set of `route`/`stage` values). + +### Data file not found (local CLI) +- Place your CSV at `./data/yellow_tripdata_2015-01.csv` or set `DATA_PATH=/path/to/file.csv`. + +## Shuttle and LogFire + +Today this template uses Shuttle’s OTEL → Better Stack integration. Shuttle is building towards streamlined integrations such as LogFire; keep an eye on the Shuttle site for updates: + +- [Shuttle](https://www.shuttle.dev/) + +## License + +MIT (or your preferred license) + +## Contributing + +Issues and PRs welcome. If you add new ETL stages, please also add tracing events for counters/histograms so dashboards stay valuable. + +## Appendix: Example responses + +**GET /benchmark** (representative payload): + +```json +{ + "metrics": { + "load_time": 1.2, + "clean_time": 0.8, + "aggregate_time": 0.4, + "sort_filter_time": 0.3, + "save_time": 0.1, + "total_time": 2.8 + }, + "message": "Demo benchmark complete (server-safe)", + "performance_summary": "Polars processed ~12.7M taxi records in ~2.8s (demo) → ~4550000 rows/sec via Rust + Polars + OTEL." +} +``` + +## Links + +- [Shuttle](https://www.shuttle.dev/) +- [Better Stack](https://betterstack.com/) +- [Polars](https://www.pola.rs/) +- [OpenTelemetry](https://opentelemetry.io/) +- [tracing (Rust)](https://docs.rs/tracing) +``` diff --git a/axum/polars-otel-shuttle/Shuttle.toml b/axum/polars-otel-shuttle/Shuttle.toml new file mode 100644 index 00000000..c858139b --- /dev/null +++ b/axum/polars-otel-shuttle/Shuttle.toml @@ -0,0 +1,2 @@ +name = "polars-otel-shuttle" +# Shuttle uses your #[shuttle_runtime::main] entry point in src/main.rs diff --git a/axum/polars-otel-shuttle/src/etl.rs b/axum/polars-otel-shuttle/src/etl.rs new file mode 100644 index 00000000..effd1a51 --- /dev/null +++ b/axum/polars-otel-shuttle/src/etl.rs @@ -0,0 +1,251 @@ +use polars::prelude::*; +use std::collections::HashMap; +use std::time::Instant; +use tracing::{info, instrument}; + +fn rss_mb() -> f64 { + if let Ok(s) = std::fs::read_to_string("/proc/self/status") { + for line in s.lines() { + if let Some(val) = line.strip_prefix("VmRSS:") { + let kb: f64 = val.split_whitespace().nth(0).unwrap_or("0").parse().unwrap_or(0.0); + return kb / 1024.0; + } + } + } + 0.0 +} + +fn bump_peak(metrics: &mut HashMap, label: &str) { + let m = rss_mb(); + metrics.insert(format!("{}_memory_mb", label), m); + let peak = metrics.get("peak_memory_mb").cloned().unwrap_or(0.0); + if m > peak { + metrics.insert("peak_memory_mb".into(), m); + } +} + +pub struct PolarsETL { + df: Option, + metrics: HashMap, +} + +impl PolarsETL { + pub fn new() -> Self { + Self { df: None, metrics: HashMap::new() } + } + + pub fn get_metrics(&self) -> &HashMap { + &self.metrics + } + + #[instrument(level = "info", skip(self))] + pub fn load_data(&mut self, file_path: &str) -> PolarsResult<&mut Self> { + info!("Loading data: {file_path}"); + let start = Instant::now(); + + let lf = LazyCsvReader::new(file_path) + .with_has_header(true) + .with_infer_schema_length(Some(2000)) + .map_parse_options(|opts| opts.with_try_parse_dates(false)) + .finish()? + .select([ + col("pickup_longitude"), + col("pickup_latitude"), + col("dropoff_longitude"), + col("dropoff_latitude"), + col("trip_distance"), + col("passenger_count"), + col("tpep_pickup_datetime"), + col("tpep_dropoff_datetime"), + col("total_amount"), + ]); + + self.df = Some(lf); + let t = start.elapsed().as_secs_f64(); + self.metrics.insert("load_time".into(), t); + bump_peak(&mut self.metrics, "after_load"); + info!(load_time_s = t, peak_mb = self.metrics.get("peak_memory_mb").cloned().unwrap_or(0.0), "Data scan created"); + Ok(self) + } + + #[instrument(level = "info", skip(self))] + pub fn clean_data(&mut self) -> PolarsResult<&mut Self> { + info!("Cleaning data"); + let start = Instant::now(); + + if let Some(df) = &self.df { + let fmt: PlSmallStr = "%Y-%m-%d %H:%M:%S%.f".into(); + let to_dt_opts = StrptimeOptions { + format: Some(fmt), + strict: false, + exact: false, + cache: true, + ..Default::default() + }; + + let cleaned = df + .clone() + .filter( + col("pickup_longitude").neq(lit(0.0)) + .and(col("pickup_latitude").neq(lit(0.0))) + .and(col("dropoff_longitude").neq(lit(0.0))) + .and(col("dropoff_latitude").neq(lit(0.0))) + .and(col("trip_distance").gt(lit(0.0))) + .and(col("trip_distance").lt(lit(100.0))) + .and(col("passenger_count").gt(lit(0))) + .and(col("passenger_count").lt_eq(lit(6))), + ) + .with_columns([ + col("tpep_pickup_datetime").str().strptime( + DataType::Datetime(TimeUnit::Microseconds, None), + to_dt_opts.clone(), + lit("coerce"), + ), + col("tpep_dropoff_datetime").str().strptime( + DataType::Datetime(TimeUnit::Microseconds, None), + to_dt_opts, + lit("coerce"), + ), + ]) + .with_columns([ + (col("tpep_dropoff_datetime") - col("tpep_pickup_datetime")) + .dt() + .total_minutes() + .alias("trip_duration_minutes"), + ]) + .filter(col("trip_duration_minutes").gt(lit(0)).and(col("trip_duration_minutes").lt(lit(480)))) + .cache(); + + self.df = Some(cleaned); + } + + let t = start.elapsed().as_secs_f64(); + self.metrics.insert("clean_time".into(), t); + bump_peak(&mut self.metrics, "after_clean"); + info!(clean_time_s = t, peak_mb = self.metrics.get("peak_memory_mb").cloned().unwrap_or(0.0), "Cleaned"); + Ok(self) + } + + #[instrument(level = "info", skip(self))] + pub fn aggregate_data(&mut self) -> PolarsResult<&mut Self> { + info!("Aggregating"); + let start = Instant::now(); + + if let Some(df) = &self.df { + let df_feats = df.clone().with_columns([ + col("tpep_pickup_datetime").dt().date().alias("date"), + col("tpep_pickup_datetime").dt().hour().alias("hour"), + col("tpep_pickup_datetime").dt().weekday().alias("weekday"), + ]); + + let _daily = df_feats + .clone() + .group_by([col("date")]) + .agg([ + col("trip_distance").count().alias("trip_count"), + col("trip_distance").mean().alias("avg_trip_distance"), + col("trip_distance").sum().alias("total_trip_distance"), + col("trip_duration_minutes").mean().alias("avg_trip_duration"), + col("trip_duration_minutes").sum().alias("total_trip_duration"), + col("passenger_count").sum().alias("total_passengers"), + col("total_amount").mean().alias("avg_total_amount"), + col("total_amount").sum().alias("total_revenue"), + ]) + .collect()?; + + let _hourly = df_feats + .clone() + .group_by([col("hour")]) + .agg([ + col("trip_distance").count().alias("trip_count"), + col("trip_distance").mean().alias("avg_trip_distance"), + col("trip_duration_minutes").mean().alias("avg_trip_duration"), + col("total_amount").mean().alias("avg_total_amount"), + ]) + .collect()?; + + let _dow = df_feats + .clone() + .group_by([col("weekday")]) + .agg([ + col("trip_distance").count().alias("trip_count"), + col("trip_distance").mean().alias("avg_trip_distance"), + col("total_amount").mean().alias("avg_total_amount"), + ]) + .collect()?; + + let _ = (_daily, _hourly, _dow); + } + + let t = start.elapsed().as_secs_f64(); + self.metrics.insert("aggregate_time".into(), t); + bump_peak(&mut self.metrics, "after_aggregate"); + info!(aggregate_time_s = t, peak_mb = self.metrics.get("peak_memory_mb").cloned().unwrap_or(0.0), "Aggregations done"); + Ok(self) + } + + #[instrument(level = "info", skip(self))] + pub fn sort_and_filter(&mut self) -> PolarsResult<&mut Self> { + info!("Sort & filter counts"); + let start = Instant::now(); + + if let Some(df) = &self.df { + let counts = df + .clone() + .with_columns([ + col("tpep_pickup_datetime").dt().hour().alias("hour"), + col("tpep_pickup_datetime").dt().weekday().alias("weekday"), + ]) + .select([ + col("trip_distance").count().cast(DataType::Int64).alias("rows_after_cleaning"), + col("trip_distance").gt(lit(10.0)).cast(DataType::Int64).sum().alias("long_trips_count"), + col("total_amount").gt(lit(50.0)).cast(DataType::Int64).sum().alias("expensive_trips_count"), + (col("hour").eq(lit(7)).or(col("hour").eq(lit(8))).or(col("hour").eq(lit(9))) + .or(col("hour").eq(lit(17))).or(col("hour").eq(lit(18))).or(col("hour").eq(lit(19)))) + .cast(DataType::Int64).sum().alias("rush_hour_trips_count"), + col("weekday").gt_eq(lit(6)).cast(DataType::Int64).sum().alias("weekend_trips_count"), + (col("trip_distance").gt(lit(5.0)) + .and(col("total_amount").gt(lit(30.0))) + .and(col("passenger_count").gt_eq(lit(2)))) + .cast(DataType::Int64).sum().alias("premium_trips_count"), + ]) + .collect()?; + + let get_i64 = |name: &str| -> PolarsResult { + Ok(counts.column(name)?.i64()?.get(0).unwrap_or(0)) + }; + + self.metrics.insert("rows_after_cleaning".into(), get_i64("rows_after_cleaning")? as f64); + self.metrics.insert("long_trips_count".into(), get_i64("long_trips_count")? as f64); + self.metrics.insert("expensive_trips_count".into(), get_i64("expensive_trips_count")? as f64); + self.metrics.insert("rush_hour_trips_count".into(), get_i64("rush_hour_trips_count")? as f64); + self.metrics.insert("weekend_trips_count".into(), get_i64("weekend_trips_count")? as f64); + self.metrics.insert("premium_trips_count".into(), get_i64("premium_trips_count")? as f64); + + info!( + long = self.metrics["long_trips_count"], + expensive = self.metrics["expensive_trips_count"], + "Counts computed" + ); + } + + let t = start.elapsed().as_secs_f64(); + self.metrics.insert("sort_filter_time".into(), t); + bump_peak(&mut self.metrics, "after_sort_filter"); + info!(sort_filter_time_s = t, peak_mb = self.metrics.get("peak_memory_mb").cloned().unwrap_or(0.0), "Sort & filter done"); + Ok(self) + } + + #[instrument(level = "info", skip(self))] + pub fn save_results(&mut self, output_dir: &str) -> Result<(), Box> { + let start = Instant::now(); + std::fs::create_dir_all(output_dir)?; + let metrics_json = serde_json::to_string_pretty(&self.metrics)?; + std::fs::write(format!("{}/polars_metrics.json", output_dir), metrics_json)?; + let t = start.elapsed().as_secs_f64(); + self.metrics.insert("save_time".into(), t); + bump_peak(&mut self.metrics, "after_save"); + info!(save_time_s = t, "Saved results"); + Ok(()) + } +} diff --git a/axum/polars-otel-shuttle/src/main.rs b/axum/polars-otel-shuttle/src/main.rs new file mode 100644 index 00000000..929bafc3 --- /dev/null +++ b/axum/polars-otel-shuttle/src/main.rs @@ -0,0 +1,167 @@ +mod etl; +mod observability; + +use axum::{routing::get, extract::Query, response::Json, Router, http::StatusCode}; +use etl::PolarsETL; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use std::path::Path; +use std::time::Instant; +use tower_http::{cors::CorsLayer, trace::TraceLayer}; +use tracing::info; + +// +// =============== 1) LOCAL CLI BENCH (feature: bench-cli) =============== +// Build & run locally: cargo run --release --features bench-cli +// +#[cfg(feature = "bench-cli")] +fn main() -> Result<(), Box> { + observability::init_tracing("polars-etl-benchmark-cli"); + + println!("{}", "=".repeat(50)); + println!("🚀 STARTING POLARS ETL BENCHMARK"); + println!("{}", "=".repeat(50)); + + // Check if data file exists (configurable via env) + let data_file = std::env::var("DATA_PATH") + .unwrap_or_else(|_| "data/yellow_tripdata_2015-01.csv".to_string()); + + if !std::path::Path::new(&data_file).exists() { + eprintln!("❌ Data file not found: {}", &data_file); + eprintln!("Tip: put the file at ./data/yellow_tripdata_2015-01.csv or set DATA_PATH="); + return Ok(()); + + } + + + let total_start = Instant::now(); + let mut etl = PolarsETL::new(); + + match etl + .load_data(&data_file)? + .clean_data()? + .aggregate_data()? + .sort_and_filter()? + .save_results("../results") + { + Ok(_) => { + let total_time = total_start.elapsed().as_secs_f64(); + + println!("\n{}", "=".repeat(50)); + println!("🎉 POLARS BENCHMARK COMPLETE!"); + println!("{}", "=".repeat(50)); + println!("⏱️ Total time: {:.2} seconds", total_time); + + println!("\n📈 Key Performance Metrics:"); + let metrics = etl.get_metrics(); + for (key, value) in metrics { + if key.contains("time") { + let formatted_key = key.replace('_', " ") + .split_whitespace() + .map(|w| { + let mut c = w.chars(); + match c.next() { + None => String::new(), + Some(f) => f.to_uppercase().collect::() + c.as_str(), + } + }) + .collect::>() + .join(" "); + println!(" {}: {:.2}s", formatted_key, value); + } + } + println!("{}", "=".repeat(50)); + } + Err(e) => { + println!("❌ Error during Polars benchmark: {}", e); + } + } + + Ok(()) +} + +// +// =============== 2) SHUTTLE WEB APP (default build) ==================== +// Deploy: cargo shuttle deploy +// +#[cfg(not(feature = "bench-cli"))] +#[shuttle_runtime::main] +async fn shuttle_main() -> shuttle_axum::ShuttleAxum { + let app = api_router().layer(CorsLayer::permissive()).layer(TraceLayer::new_for_http()); + tracing::info!(event = "startup", message = "Axum app ready"); + Ok(app.into()) +} + +#[derive(Deserialize)] +struct BenchmarkQuery { + #[serde(default)] + sample_size: Option, +} + +#[derive(Serialize)] +struct BenchmarkResult { + metrics: HashMap, + message: String, + performance_summary: String, +} + +async fn health() -> &'static str { +// emit a cheap heartbeat counter + tracing::info!(monotonic_counter.health_checks = 1, "health checked"); + tracing::info!(endpoint = "/health", status = "ok"); + "ok" +} + +#[tracing::instrument(name = "benchmark", skip_all)] +async fn run_benchmark(_q: Query) -> Result, StatusCode> { + let t0 = Instant::now(); + +// Count requests to this endpoint + tracing::info!(monotonic_counter.http_requests_total = 1, route="/benchmark", "Benchmark hit"); + + tracing::info!(endpoint = "/benchmark", event = "start_demo_benchmark"); + // NOTE: We return representative metrics here (do not run heavy ETL on the Shuttle dyno). + let mut metrics = HashMap::new(); + metrics.insert("load_time".to_string(), 1.2); + metrics.insert("clean_time".to_string(), 0.8); + metrics.insert("aggregate_time".to_string(), 0.4); + metrics.insert("sort_filter_time".to_string(), 0.3); + metrics.insert("save_time".to_string(), 0.1); + metrics.insert("total_time".to_string(), 2.8); + +// Export timings as histograms (ms) so Better Stack can graph them + tracing::info!(histogram.load_time_ms = 1.2_f64 * 1000.0, stage="load", "stage timing"); + tracing::info!(histogram.clean_time_ms = 0.8_f64 * 1000.0, stage="clean", "stage timing"); + tracing::info!(histogram.aggregate_time_ms = 0.4_f64 * 1000.0, stage="aggregate", "stage timing"); + tracing::info!(histogram.sort_filter_time_ms = 0.3_f64 * 1000.0, stage="sort_filter", "stage timing"); + tracing::info!(histogram.save_time_ms = 0.1_f64 * 1000.0, stage="save", "stage timing"); + tracing::info!(histogram.total_time_ms = 2.8_f64 * 1000.0, stage="total", "stage timing"); + + // Rows processed (monotonic counter) + tracing::info!(monotonic_counter.rows_processed = 12_748_986_i64, "rows processed (demo)"); + + // Request duration histogram + let elapsed_ms = t0.elapsed().as_millis() as f64; + tracing::info!(histogram.request_duration_ms = elapsed_ms, route="/benchmark", "Benchmark responded"); + + let rows_per_second = 12_748_986.0 / 2.8; + let summary = format!( + "🚀 Polars processed ~12.7M taxi records in ~2.8s (demo) → ~{:.0} rows/sec via Rust + Polars + OTEL.", + rows_per_second + ); + tracing::info!(endpoint = "/benchmark", event = "end_demo_benchmark", total_time = 2.8); + + Ok(Json(BenchmarkResult { + metrics, + message: "✅ Demo benchmark complete (server-safe)".into(), + performance_summary: summary, + })) +} + +fn api_router() -> Router { + Router::new() + .route("/", get(health)) + .route("/health", get(health)) + .route("/benchmark", get(run_benchmark)) +} + diff --git a/axum/polars-otel-shuttle/src/observability.rs b/axum/polars-otel-shuttle/src/observability.rs new file mode 100644 index 00000000..a3cb3579 --- /dev/null +++ b/axum/polars-otel-shuttle/src/observability.rs @@ -0,0 +1,99 @@ +use opentelemetry::KeyValue; +use opentelemetry_sdk::{trace as sdktrace, Resource}; +use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; + +pub fn init_tracing(service_name: &str) { + // JSON logs with RFC3339 timestamps + let env_filter = + EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")); + + let fmt_layer = tracing_subscriber::fmt::layer() + .with_ansi(false) + .json() + .with_current_span(true) + .with_span_list(true) + .with_target(false) + .with_file(false) + .with_line_number(false) + .with_timer(tracing_subscriber::fmt::time::UtcTime::rfc_3339()); + + // Base registry (logs only) + let mut registry = tracing_subscriber::registry().with(env_filter).with(fmt_layer); + + // If you compile with `--features otel-otlp`, add an OTLP span layer too. + #[cfg(feature = "otel-otlp")] + { + if let Some(layer) = build_otel_layer(service_name) { + registry = registry.with(layer); + } + } + + registry.init(); +} + +#[cfg(feature = "otel-otlp")] +fn build_otel_layer(service_name: &str) -> Option> +where + S: tracing::Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>, +{ + use opentelemetry_otlp::Protocol; + + // Read endpoint/headers from env (works for BetterStack or any OTLP endpoint) + let endpoint = + std::env::var("OTEL_EXPORTER_OTLP_ENDPOINT").unwrap_or_else(|_| "http://localhost:4318".into()); + + // Headers in the standard comma-separated form: k1=v1,k2=v2 + let headers = std::env::var("OTEL_EXPORTER_OTLP_HEADERS").ok(); + let headers_map = parse_headers(headers.as_deref()); + + // Resource (service name etc.) + let resource = Resource::builder() + .with_service_name(service_name.to_string()) + .with_attributes(vec![ + KeyValue::new("telemetry.sdk.language", "rust"), + ]) + .build(); + + // Build an OTLP/HTTP span exporter (0.30 API) + let exporter = opentelemetry_otlp::SpanExporter::builder() + .with_http() + .with_endpoint(endpoint) + .with_protocol(Protocol::HttpBinary) // or HttpProtobuf; works with most collectors + .with_headers(headers_map) + .build() + .ok()?; + + // Tracer provider with batch exporter on Tokio + let provider = sdktrace::TracerProvider::builder() + .with_resource(resource) + .with_batch_exporter(exporter, opentelemetry_sdk::runtime::Tokio) + .build(); + + let tracer = provider.tracer("polars-otel-shuttle"); + + // Install as global provider + opentelemetry::global::set_tracer_provider(provider); + + // Bridge tracing -> OpenTelemetry + Some(tracing_opentelemetry::layer().with_tracer(tracer)) +} + +#[cfg(feature = "otel-otlp")] +fn parse_headers(input: Option<&str>) -> std::collections::HashMap { + let mut map = std::collections::HashMap::new(); + if let Some(s) = input { + for kv in s.split(',') { + if let Some((k, v)) = kv.split_once('=') { + map.insert(k.trim().to_string(), v.trim().to_string()); + } + } + } + map +} + +/// Call this on shutdown if you want to block until spans are exported. +pub fn shutdown_tracing() { + // No-op for opentelemetry 0.30. + // The tracer provider will flush on drop when the process exits. +} + From cd6995029798560211f1b2c7b4bc1a0a226a1b0b Mon Sep 17 00:00:00 2001 From: pandora Date: Tue, 23 Sep 2025 23:22:39 +0100 Subject: [PATCH 231/239] Save current changes before running clippy --fix --- axum/polars-otel-shuttle/src/etl.rs | 138 ++++++++++++++---- axum/polars-otel-shuttle/src/main.rs | 89 ++++++++--- axum/polars-otel-shuttle/src/observability.rs | 22 +-- 3 files changed, 184 insertions(+), 65 deletions(-) diff --git a/axum/polars-otel-shuttle/src/etl.rs b/axum/polars-otel-shuttle/src/etl.rs index effd1a51..ba2a596a 100644 --- a/axum/polars-otel-shuttle/src/etl.rs +++ b/axum/polars-otel-shuttle/src/etl.rs @@ -7,7 +7,12 @@ fn rss_mb() -> f64 { if let Ok(s) = std::fs::read_to_string("/proc/self/status") { for line in s.lines() { if let Some(val) = line.strip_prefix("VmRSS:") { - let kb: f64 = val.split_whitespace().nth(0).unwrap_or("0").parse().unwrap_or(0.0); + let kb: f64 = val + .split_whitespace() + .nth(0) + .unwrap_or("0") + .parse() + .unwrap_or(0.0); return kb / 1024.0; } } @@ -31,7 +36,10 @@ pub struct PolarsETL { impl PolarsETL { pub fn new() -> Self { - Self { df: None, metrics: HashMap::new() } + Self { + df: None, + metrics: HashMap::new(), + } } pub fn get_metrics(&self) -> &HashMap { @@ -64,7 +72,11 @@ impl PolarsETL { let t = start.elapsed().as_secs_f64(); self.metrics.insert("load_time".into(), t); bump_peak(&mut self.metrics, "after_load"); - info!(load_time_s = t, peak_mb = self.metrics.get("peak_memory_mb").cloned().unwrap_or(0.0), "Data scan created"); + info!( + load_time_s = t, + peak_mb = self.metrics.get("peak_memory_mb").cloned().unwrap_or(0.0), + "Data scan created" + ); Ok(self) } @@ -86,7 +98,8 @@ impl PolarsETL { let cleaned = df .clone() .filter( - col("pickup_longitude").neq(lit(0.0)) + col("pickup_longitude") + .neq(lit(0.0)) .and(col("pickup_latitude").neq(lit(0.0))) .and(col("dropoff_longitude").neq(lit(0.0))) .and(col("dropoff_latitude").neq(lit(0.0))) @@ -107,13 +120,17 @@ impl PolarsETL { lit("coerce"), ), ]) - .with_columns([ - (col("tpep_dropoff_datetime") - col("tpep_pickup_datetime")) + .with_columns( + [(col("tpep_dropoff_datetime") - col("tpep_pickup_datetime")) .dt() .total_minutes() - .alias("trip_duration_minutes"), - ]) - .filter(col("trip_duration_minutes").gt(lit(0)).and(col("trip_duration_minutes").lt(lit(480)))) + .alias("trip_duration_minutes")], + ) + .filter( + col("trip_duration_minutes") + .gt(lit(0)) + .and(col("trip_duration_minutes").lt(lit(480))), + ) .cache(); self.df = Some(cleaned); @@ -122,7 +139,11 @@ impl PolarsETL { let t = start.elapsed().as_secs_f64(); self.metrics.insert("clean_time".into(), t); bump_peak(&mut self.metrics, "after_clean"); - info!(clean_time_s = t, peak_mb = self.metrics.get("peak_memory_mb").cloned().unwrap_or(0.0), "Cleaned"); + info!( + clean_time_s = t, + peak_mb = self.metrics.get("peak_memory_mb").cloned().unwrap_or(0.0), + "Cleaned" + ); Ok(self) } @@ -145,8 +166,12 @@ impl PolarsETL { col("trip_distance").count().alias("trip_count"), col("trip_distance").mean().alias("avg_trip_distance"), col("trip_distance").sum().alias("total_trip_distance"), - col("trip_duration_minutes").mean().alias("avg_trip_duration"), - col("trip_duration_minutes").sum().alias("total_trip_duration"), + col("trip_duration_minutes") + .mean() + .alias("avg_trip_duration"), + col("trip_duration_minutes") + .sum() + .alias("total_trip_duration"), col("passenger_count").sum().alias("total_passengers"), col("total_amount").mean().alias("avg_total_amount"), col("total_amount").sum().alias("total_revenue"), @@ -159,7 +184,9 @@ impl PolarsETL { .agg([ col("trip_distance").count().alias("trip_count"), col("trip_distance").mean().alias("avg_trip_distance"), - col("trip_duration_minutes").mean().alias("avg_trip_duration"), + col("trip_duration_minutes") + .mean() + .alias("avg_trip_duration"), col("total_amount").mean().alias("avg_total_amount"), ]) .collect()?; @@ -180,7 +207,11 @@ impl PolarsETL { let t = start.elapsed().as_secs_f64(); self.metrics.insert("aggregate_time".into(), t); bump_peak(&mut self.metrics, "after_aggregate"); - info!(aggregate_time_s = t, peak_mb = self.metrics.get("peak_memory_mb").cloned().unwrap_or(0.0), "Aggregations done"); + info!( + aggregate_time_s = t, + peak_mb = self.metrics.get("peak_memory_mb").cloned().unwrap_or(0.0), + "Aggregations done" + ); Ok(self) } @@ -197,17 +228,42 @@ impl PolarsETL { col("tpep_pickup_datetime").dt().weekday().alias("weekday"), ]) .select([ - col("trip_distance").count().cast(DataType::Int64).alias("rows_after_cleaning"), - col("trip_distance").gt(lit(10.0)).cast(DataType::Int64).sum().alias("long_trips_count"), - col("total_amount").gt(lit(50.0)).cast(DataType::Int64).sum().alias("expensive_trips_count"), - (col("hour").eq(lit(7)).or(col("hour").eq(lit(8))).or(col("hour").eq(lit(9))) - .or(col("hour").eq(lit(17))).or(col("hour").eq(lit(18))).or(col("hour").eq(lit(19)))) - .cast(DataType::Int64).sum().alias("rush_hour_trips_count"), - col("weekday").gt_eq(lit(6)).cast(DataType::Int64).sum().alias("weekend_trips_count"), - (col("trip_distance").gt(lit(5.0)) + col("trip_distance") + .count() + .cast(DataType::Int64) + .alias("rows_after_cleaning"), + col("trip_distance") + .gt(lit(10.0)) + .cast(DataType::Int64) + .sum() + .alias("long_trips_count"), + col("total_amount") + .gt(lit(50.0)) + .cast(DataType::Int64) + .sum() + .alias("expensive_trips_count"), + (col("hour") + .eq(lit(7)) + .or(col("hour").eq(lit(8))) + .or(col("hour").eq(lit(9))) + .or(col("hour").eq(lit(17))) + .or(col("hour").eq(lit(18))) + .or(col("hour").eq(lit(19)))) + .cast(DataType::Int64) + .sum() + .alias("rush_hour_trips_count"), + col("weekday") + .gt_eq(lit(6)) + .cast(DataType::Int64) + .sum() + .alias("weekend_trips_count"), + (col("trip_distance") + .gt(lit(5.0)) .and(col("total_amount").gt(lit(30.0))) .and(col("passenger_count").gt_eq(lit(2)))) - .cast(DataType::Int64).sum().alias("premium_trips_count"), + .cast(DataType::Int64) + .sum() + .alias("premium_trips_count"), ]) .collect()?; @@ -215,12 +271,30 @@ impl PolarsETL { Ok(counts.column(name)?.i64()?.get(0).unwrap_or(0)) }; - self.metrics.insert("rows_after_cleaning".into(), get_i64("rows_after_cleaning")? as f64); - self.metrics.insert("long_trips_count".into(), get_i64("long_trips_count")? as f64); - self.metrics.insert("expensive_trips_count".into(), get_i64("expensive_trips_count")? as f64); - self.metrics.insert("rush_hour_trips_count".into(), get_i64("rush_hour_trips_count")? as f64); - self.metrics.insert("weekend_trips_count".into(), get_i64("weekend_trips_count")? as f64); - self.metrics.insert("premium_trips_count".into(), get_i64("premium_trips_count")? as f64); + self.metrics.insert( + "rows_after_cleaning".into(), + get_i64("rows_after_cleaning")? as f64, + ); + self.metrics.insert( + "long_trips_count".into(), + get_i64("long_trips_count")? as f64, + ); + self.metrics.insert( + "expensive_trips_count".into(), + get_i64("expensive_trips_count")? as f64, + ); + self.metrics.insert( + "rush_hour_trips_count".into(), + get_i64("rush_hour_trips_count")? as f64, + ); + self.metrics.insert( + "weekend_trips_count".into(), + get_i64("weekend_trips_count")? as f64, + ); + self.metrics.insert( + "premium_trips_count".into(), + get_i64("premium_trips_count")? as f64, + ); info!( long = self.metrics["long_trips_count"], @@ -232,7 +306,11 @@ impl PolarsETL { let t = start.elapsed().as_secs_f64(); self.metrics.insert("sort_filter_time".into(), t); bump_peak(&mut self.metrics, "after_sort_filter"); - info!(sort_filter_time_s = t, peak_mb = self.metrics.get("peak_memory_mb").cloned().unwrap_or(0.0), "Sort & filter done"); + info!( + sort_filter_time_s = t, + peak_mb = self.metrics.get("peak_memory_mb").cloned().unwrap_or(0.0), + "Sort & filter done" + ); Ok(self) } diff --git a/axum/polars-otel-shuttle/src/main.rs b/axum/polars-otel-shuttle/src/main.rs index 929bafc3..0cc1283b 100644 --- a/axum/polars-otel-shuttle/src/main.rs +++ b/axum/polars-otel-shuttle/src/main.rs @@ -1,7 +1,7 @@ mod etl; mod observability; -use axum::{routing::get, extract::Query, response::Json, Router, http::StatusCode}; +use axum::{extract::Query, http::StatusCode, response::Json, routing::get, Router}; use etl::PolarsETL; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -24,16 +24,16 @@ fn main() -> Result<(), Box> { // Check if data file exists (configurable via env) let data_file = std::env::var("DATA_PATH") - .unwrap_or_else(|_| "data/yellow_tripdata_2015-01.csv".to_string()); + .unwrap_or_else(|_| "data/yellow_tripdata_2015-01.csv".to_string()); if !std::path::Path::new(&data_file).exists() { - eprintln!("❌ Data file not found: {}", &data_file); - eprintln!("Tip: put the file at ./data/yellow_tripdata_2015-01.csv or set DATA_PATH="); - return Ok(()); - + eprintln!("❌ Data file not found: {}", &data_file); + eprintln!( + "Tip: put the file at ./data/yellow_tripdata_2015-01.csv or set DATA_PATH=" + ); + return Ok(()); } - let total_start = Instant::now(); let mut etl = PolarsETL::new(); @@ -56,7 +56,8 @@ fn main() -> Result<(), Box> { let metrics = etl.get_metrics(); for (key, value) in metrics { if key.contains("time") { - let formatted_key = key.replace('_', " ") + let formatted_key = key + .replace('_', " ") .split_whitespace() .map(|w| { let mut c = w.chars(); @@ -87,7 +88,9 @@ fn main() -> Result<(), Box> { #[cfg(not(feature = "bench-cli"))] #[shuttle_runtime::main] async fn shuttle_main() -> shuttle_axum::ShuttleAxum { - let app = api_router().layer(CorsLayer::permissive()).layer(TraceLayer::new_for_http()); + let app = api_router() + .layer(CorsLayer::permissive()) + .layer(TraceLayer::new_for_http()); tracing::info!(event = "startup", message = "Axum app ready"); Ok(app.into()) } @@ -106,7 +109,7 @@ struct BenchmarkResult { } async fn health() -> &'static str { -// emit a cheap heartbeat counter + // emit a cheap heartbeat counter tracing::info!(monotonic_counter.health_checks = 1, "health checked"); tracing::info!(endpoint = "/health", status = "ok"); "ok" @@ -116,11 +119,15 @@ async fn health() -> &'static str { async fn run_benchmark(_q: Query) -> Result, StatusCode> { let t0 = Instant::now(); -// Count requests to this endpoint - tracing::info!(monotonic_counter.http_requests_total = 1, route="/benchmark", "Benchmark hit"); + // Count requests to this endpoint + tracing::info!( + monotonic_counter.http_requests_total = 1, + route = "/benchmark", + "Benchmark hit" + ); tracing::info!(endpoint = "/benchmark", event = "start_demo_benchmark"); - // NOTE: We return representative metrics here (do not run heavy ETL on the Shuttle dyno). + // NOTE: We return representative metrics here (do not run heavy ETL on the Shuttle dyno). let mut metrics = HashMap::new(); metrics.insert("load_time".to_string(), 1.2); metrics.insert("clean_time".to_string(), 0.8); @@ -129,27 +136,62 @@ async fn run_benchmark(_q: Query) -> Result Router { .route("/health", get(health)) .route("/benchmark", get(run_benchmark)) } - diff --git a/axum/polars-otel-shuttle/src/observability.rs b/axum/polars-otel-shuttle/src/observability.rs index a3cb3579..17d365f8 100644 --- a/axum/polars-otel-shuttle/src/observability.rs +++ b/axum/polars-otel-shuttle/src/observability.rs @@ -4,8 +4,7 @@ use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilte pub fn init_tracing(service_name: &str) { // JSON logs with RFC3339 timestamps - let env_filter = - EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")); + let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")); let fmt_layer = tracing_subscriber::fmt::layer() .with_ansi(false) @@ -18,7 +17,9 @@ pub fn init_tracing(service_name: &str) { .with_timer(tracing_subscriber::fmt::time::UtcTime::rfc_3339()); // Base registry (logs only) - let mut registry = tracing_subscriber::registry().with(env_filter).with(fmt_layer); + let mut registry = tracing_subscriber::registry() + .with(env_filter) + .with(fmt_layer); // If you compile with `--features otel-otlp`, add an OTLP span layer too. #[cfg(feature = "otel-otlp")] @@ -32,15 +33,17 @@ pub fn init_tracing(service_name: &str) { } #[cfg(feature = "otel-otlp")] -fn build_otel_layer(service_name: &str) -> Option> +fn build_otel_layer( + service_name: &str, +) -> Option> where S: tracing::Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>, { use opentelemetry_otlp::Protocol; // Read endpoint/headers from env (works for BetterStack or any OTLP endpoint) - let endpoint = - std::env::var("OTEL_EXPORTER_OTLP_ENDPOINT").unwrap_or_else(|_| "http://localhost:4318".into()); + let endpoint = std::env::var("OTEL_EXPORTER_OTLP_ENDPOINT") + .unwrap_or_else(|_| "http://localhost:4318".into()); // Headers in the standard comma-separated form: k1=v1,k2=v2 let headers = std::env::var("OTEL_EXPORTER_OTLP_HEADERS").ok(); @@ -49,9 +52,7 @@ where // Resource (service name etc.) let resource = Resource::builder() .with_service_name(service_name.to_string()) - .with_attributes(vec![ - KeyValue::new("telemetry.sdk.language", "rust"), - ]) + .with_attributes(vec![KeyValue::new("telemetry.sdk.language", "rust")]) .build(); // Build an OTLP/HTTP span exporter (0.30 API) @@ -94,6 +95,5 @@ fn parse_headers(input: Option<&str>) -> std::collections::HashMap Date: Tue, 23 Sep 2025 23:56:59 +0100 Subject: [PATCH 232/239] Apply cargo fmt and clippy fixes --- axum/polars-otel-shuttle/src/etl.rs | 3 +-- axum/polars-otel-shuttle/src/main.rs | 3 --- axum/polars-otel-shuttle/src/observability.rs | 4 +--- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/axum/polars-otel-shuttle/src/etl.rs b/axum/polars-otel-shuttle/src/etl.rs index ba2a596a..eddaa9b0 100644 --- a/axum/polars-otel-shuttle/src/etl.rs +++ b/axum/polars-otel-shuttle/src/etl.rs @@ -8,8 +8,7 @@ fn rss_mb() -> f64 { for line in s.lines() { if let Some(val) = line.strip_prefix("VmRSS:") { let kb: f64 = val - .split_whitespace() - .nth(0) + .split_whitespace().next() .unwrap_or("0") .parse() .unwrap_or(0.0); diff --git a/axum/polars-otel-shuttle/src/main.rs b/axum/polars-otel-shuttle/src/main.rs index 0cc1283b..361549f9 100644 --- a/axum/polars-otel-shuttle/src/main.rs +++ b/axum/polars-otel-shuttle/src/main.rs @@ -2,13 +2,10 @@ mod etl; mod observability; use axum::{extract::Query, http::StatusCode, response::Json, routing::get, Router}; -use etl::PolarsETL; use serde::{Deserialize, Serialize}; use std::collections::HashMap; -use std::path::Path; use std::time::Instant; use tower_http::{cors::CorsLayer, trace::TraceLayer}; -use tracing::info; // // =============== 1) LOCAL CLI BENCH (feature: bench-cli) =============== diff --git a/axum/polars-otel-shuttle/src/observability.rs b/axum/polars-otel-shuttle/src/observability.rs index 17d365f8..a21c2468 100644 --- a/axum/polars-otel-shuttle/src/observability.rs +++ b/axum/polars-otel-shuttle/src/observability.rs @@ -1,5 +1,3 @@ -use opentelemetry::KeyValue; -use opentelemetry_sdk::{trace as sdktrace, Resource}; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; pub fn init_tracing(service_name: &str) { @@ -17,7 +15,7 @@ pub fn init_tracing(service_name: &str) { .with_timer(tracing_subscriber::fmt::time::UtcTime::rfc_3339()); // Base registry (logs only) - let mut registry = tracing_subscriber::registry() + let registry = tracing_subscriber::registry() .with(env_filter) .with(fmt_layer); From ccc0db43ee73b591ad6ab6c023a701e5930c1c29 Mon Sep 17 00:00:00 2001 From: pandora Date: Wed, 24 Sep 2025 00:31:05 +0100 Subject: [PATCH 233/239] Add polars-otel-shuttle entry to templates.toml --- templates.toml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/templates.toml b/templates.toml index 20ff33b0..97f40368 100644 --- a/templates.toml +++ b/templates.toml @@ -374,6 +374,14 @@ path = "mcp/mcp-sse-oauth" use_cases = ["MCP", "AI", "AI Agents"] tags = ["axum", "mcp", "sse", "oauth"] +[templates.polars-otel-shuttle] +title = "Polars ETL with OpenTelemetry" +description = "An Axum + Polars ETL pipeline instrumented with OpenTelemetry, deployed on Shuttle." +path = "axum/polars-otel-shuttle" +use_cases = ["ETL", "Data Engineering", "Observability"] +tags = ["axum", "polars", "opentelemetry", "etl"] + + ## EXAMPLES ## From 0732c594b97b4f9371da36490b395d5b1e187b51 Mon Sep 17 00:00:00 2001 From: pandora Date: Wed, 24 Sep 2025 01:36:41 +0100 Subject: [PATCH 234/239] WIP: current edits before clippy fixes --- axum/polars-otel-shuttle/src/etl.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/axum/polars-otel-shuttle/src/etl.rs b/axum/polars-otel-shuttle/src/etl.rs index eddaa9b0..1cad02fe 100644 --- a/axum/polars-otel-shuttle/src/etl.rs +++ b/axum/polars-otel-shuttle/src/etl.rs @@ -8,7 +8,8 @@ fn rss_mb() -> f64 { for line in s.lines() { if let Some(val) = line.strip_prefix("VmRSS:") { let kb: f64 = val - .split_whitespace().next() + .split_whitespace() + .next() .unwrap_or("0") .parse() .unwrap_or(0.0); From ce634a2af0d0879c9d130db55ad72fc10511485d Mon Sep 17 00:00:00 2001 From: pandora Date: Wed, 24 Sep 2025 02:11:21 +0100 Subject: [PATCH 235/239] Add polars-otel-shuttle entry to templates.toml --- templates.toml | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/templates.toml b/templates.toml index 97f40368..01b09e47 100644 --- a/templates.toml +++ b/templates.toml @@ -241,6 +241,13 @@ path = "axum/todo-app" use_cases = ["Web app", "Storage"] tags = ["axum", "postgres", "database"] +[templates.axum-polars-otel-shuttle] +title = "Polars ETL with OpenTelemetry" +description = "An Axum + Polars ETL pipeline instrumented with OpenTelemetry, deployed on Shuttle." +path = "axum/polars-otel-shuttle" +use_cases = ["ETL", "Data Engineering", "Observability"] +tags = ["axum", "polars", "opentelemetry", "etl"] + [templates.axum-turso] title = "Turso" description = "Connect to a Turso DB with shuttle-turso" @@ -374,13 +381,6 @@ path = "mcp/mcp-sse-oauth" use_cases = ["MCP", "AI", "AI Agents"] tags = ["axum", "mcp", "sse", "oauth"] -[templates.polars-otel-shuttle] -title = "Polars ETL with OpenTelemetry" -description = "An Axum + Polars ETL pipeline instrumented with OpenTelemetry, deployed on Shuttle." -path = "axum/polars-otel-shuttle" -use_cases = ["ETL", "Data Engineering", "Observability"] -tags = ["axum", "polars", "opentelemetry", "etl"] - ## EXAMPLES ## @@ -479,3 +479,11 @@ use_cases = ["Web app"] tags = ["rocket", "yew"] author = "wiseaidev" repo = "https://github.com/wiseaidev/rocket-yew-starter-pack" + +[community_templates.polars-otel-shuttle] +title = "Polars ETL with OpenTelemetry" +description = "Observable data pipeline using Polars for ETL and OpenTelemetry for monitoring" +use_cases = ["Data Engineering", "ETL", "Observability"] +tags = ["axum", "polars", "opentelemetry", "etl"] +author = "AdepojuJeremy" +repo = "https://github.com/AdepojuJeremy/polars-otel-shuttle" From 8c86ed89177b8d24e813c94d99dd6c910283986e Mon Sep 17 00:00:00 2001 From: pandora Date: Wed, 24 Sep 2025 21:04:18 +0100 Subject: [PATCH 236/239] Save changes before clippy fixes --- axum/polars-otel-shuttle/src/etl.rs | 4 +++- axum/polars-otel-shuttle/src/main.rs | 2 +- axum/polars-otel-shuttle/src/observability.rs | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/axum/polars-otel-shuttle/src/etl.rs b/axum/polars-otel-shuttle/src/etl.rs index 1cad02fe..15b5263c 100644 --- a/axum/polars-otel-shuttle/src/etl.rs +++ b/axum/polars-otel-shuttle/src/etl.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; use std::time::Instant; use tracing::{info, instrument}; +#[allow(dead_code)] fn rss_mb() -> f64 { if let Ok(s) = std::fs::read_to_string("/proc/self/status") { for line in s.lines() { @@ -20,6 +21,7 @@ fn rss_mb() -> f64 { 0.0 } +#[allow(dead_code)] fn bump_peak(metrics: &mut HashMap, label: &str) { let m = rss_mb(); metrics.insert(format!("{}_memory_mb", label), m); @@ -29,6 +31,7 @@ fn bump_peak(metrics: &mut HashMap, label: &str) { } } +#[allow(dead_code)] pub struct PolarsETL { df: Option, metrics: HashMap, @@ -92,7 +95,6 @@ impl PolarsETL { strict: false, exact: false, cache: true, - ..Default::default() }; let cleaned = df diff --git a/axum/polars-otel-shuttle/src/main.rs b/axum/polars-otel-shuttle/src/main.rs index 361549f9..d551ade7 100644 --- a/axum/polars-otel-shuttle/src/main.rs +++ b/axum/polars-otel-shuttle/src/main.rs @@ -95,7 +95,7 @@ async fn shuttle_main() -> shuttle_axum::ShuttleAxum { #[derive(Deserialize)] struct BenchmarkQuery { #[serde(default)] - sample_size: Option, + _sample_size: Option, } #[derive(Serialize)] diff --git a/axum/polars-otel-shuttle/src/observability.rs b/axum/polars-otel-shuttle/src/observability.rs index a21c2468..8bee3156 100644 --- a/axum/polars-otel-shuttle/src/observability.rs +++ b/axum/polars-otel-shuttle/src/observability.rs @@ -1,6 +1,7 @@ use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; -pub fn init_tracing(service_name: &str) { +#[allow(dead_code)] +pub fn init_tracing(_service_name: &str) { // JSON logs with RFC3339 timestamps let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")); @@ -91,6 +92,7 @@ fn parse_headers(input: Option<&str>) -> std::collections::HashMap Date: Wed, 24 Sep 2025 21:08:41 +0100 Subject: [PATCH 237/239] Save changes before clippy fixes --- axum/polars-otel-shuttle/src/etl.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/axum/polars-otel-shuttle/src/etl.rs b/axum/polars-otel-shuttle/src/etl.rs index 15b5263c..1c194dda 100644 --- a/axum/polars-otel-shuttle/src/etl.rs +++ b/axum/polars-otel-shuttle/src/etl.rs @@ -37,6 +37,7 @@ pub struct PolarsETL { metrics: HashMap, } +#[allow(dead_code)] impl PolarsETL { pub fn new() -> Self { Self { From 78c66b05f0df660a07f15e198c450d4ee11e3bc8 Mon Sep 17 00:00:00 2001 From: pandora Date: Wed, 24 Sep 2025 21:27:22 +0100 Subject: [PATCH 238/239] Address maintainer feedback and fix CI issues: - Fix clippy warnings (unused variables, dead code) to resolve CI failures - Remove duplicate template entry from templates.toml - Shorten template description - Remove unnecessary .gitignore and .ignore files - Clean up unused dependencies in Cargo.toml - Make README more concise and focused --- axum/polars-otel-shuttle/.gitignore | 10 ---------- axum/polars-otel-shuttle/.ignore | 11 ----------- templates.toml | 10 ++-------- 3 files changed, 2 insertions(+), 29 deletions(-) delete mode 100644 axum/polars-otel-shuttle/.gitignore delete mode 100644 axum/polars-otel-shuttle/.ignore diff --git a/axum/polars-otel-shuttle/.gitignore b/axum/polars-otel-shuttle/.gitignore deleted file mode 100644 index 05bab428..00000000 --- a/axum/polars-otel-shuttle/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -/target -.shuttle* -Secrets*.toml -target/ -**/*.parquet -data/ -results/ -.DS_Store -data/ -*.csv diff --git a/axum/polars-otel-shuttle/.ignore b/axum/polars-otel-shuttle/.ignore deleted file mode 100644 index acf8bc25..00000000 --- a/axum/polars-otel-shuttle/.ignore +++ /dev/null @@ -1,11 +0,0 @@ -# Local datasets / outputs -data/** -results/** -*.csv -*.parquet -*.zip - -# Build artifacts & caches -target/** -node_modules/** -**/.DS_Store diff --git a/templates.toml b/templates.toml index 01b09e47..e92cc689 100644 --- a/templates.toml +++ b/templates.toml @@ -243,7 +243,7 @@ tags = ["axum", "postgres", "database"] [templates.axum-polars-otel-shuttle] title = "Polars ETL with OpenTelemetry" -description = "An Axum + Polars ETL pipeline instrumented with OpenTelemetry, deployed on Shuttle." +description = "ETL pipeline with Polars and Open Telemetry monitoring" path = "axum/polars-otel-shuttle" use_cases = ["ETL", "Data Engineering", "Observability"] tags = ["axum", "polars", "opentelemetry", "etl"] @@ -480,10 +480,4 @@ tags = ["rocket", "yew"] author = "wiseaidev" repo = "https://github.com/wiseaidev/rocket-yew-starter-pack" -[community_templates.polars-otel-shuttle] -title = "Polars ETL with OpenTelemetry" -description = "Observable data pipeline using Polars for ETL and OpenTelemetry for monitoring" -use_cases = ["Data Engineering", "ETL", "Observability"] -tags = ["axum", "polars", "opentelemetry", "etl"] -author = "AdepojuJeremy" -repo = "https://github.com/AdepojuJeremy/polars-otel-shuttle" + From 498cc891b954503b7be88cf0c0424d61540e6c12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6=28s=29=20=3D=20=E2=88=91=E2=82=99=E2=82=8C=E2=82=81?= =?UTF-8?q?=5E=E2=88=9E=201/n=CB=A2=2E?= Date: Wed, 24 Sep 2025 22:08:09 +0100 Subject: [PATCH 239/239] Update README.md Concise readme --- axum/polars-otel-shuttle/README.md | 422 ++--------------------------- 1 file changed, 29 insertions(+), 393 deletions(-) diff --git a/axum/polars-otel-shuttle/README.md b/axum/polars-otel-shuttle/README.md index 7fa7290f..0c215222 100644 --- a/axum/polars-otel-shuttle/README.md +++ b/axum/polars-otel-shuttle/README.md @@ -1,419 +1,55 @@ +# Polars ETL with OpenTelemetry -# polars-otel-shuttle +An ETL pipeline using Polars for data processing and OpenTelemetry for observability, deployable on Shuttle. -High-performance ETL in Rust with Polars, production-ready observability via OpenTelemetry and tracing, and one-command deploy on Shuttle with built-in export to Better Stack. +## What it does -## Overview +- Processes CSV data with Polars (load → clean → aggregate → filter/sort → save) +- Exposes HTTP endpoints via Axum +- Emits metrics and traces via OpenTelemetry +- Integrates with Better Stack for monitoring (when deployed on Shuttle) -This repository contains: - -- A local, benchmark-style ETL pipeline using Polars over a large NYC Taxi CSV. -- An Axum HTTP service (for Shuttle) that exposes lightweight endpoints and emits structured traces and metrics. -- OTEL integration that requires no collector setup when deployed on Shuttle. -- Examples of metric events that flow to Better Stack (counters and histograms), with guidance for dashboards and log-based queries. - -## Why this project - -Many Python data teams rely on Pandas for ETL. Rust + Polars delivers multi-threaded performance with memory safety and predictable latency. This project shows how to: - -- Build an ETL pipeline in Rust/Polars. -- Instrument it with tracing and OpenTelemetry. -- Export telemetry to Better Stack with Shuttle’s native OTEL support (no sidecar collector). -- Visualize performance using log-derived metrics and dashboards. - -In addition, we mention Shuttle’s upcoming LogFire integration as a future option for observability. - -## Project layout - -``` -polars-otel-shuttle/ -├─ Cargo.toml -├─ Shuttle.toml -├─ src/ -│ ├─ etl.rs # Polars ETL pipeline (load → clean → aggregate → filter/sort → save) -│ ├─ observability.rs # Tracing/OTEL setup (fmt logs; optional OTLP for non-Shuttle runs) -│ └─ main.rs # CLI benchmark (feature-gated) + Axum web app for Shuttle -├─ data/ # Put the CSV here (ignored by Git) -└─ results/ # Output directory (ignored by Git) -``` - -## Prerequisites - -- Rust toolchain (stable) -- A large CSV to process, e.g. `yellow_tripdata_2015-01.csv` (~1.9GB) placed in `./data/` -- For deploys: Shuttle CLI and a Shuttle account -- For dashboards: a Better Stack account (Shuttle Telemetry export requires Pro tier or above) - -> **Note**: This repository does not commit the dataset. Keep large files out of Git. - -## Running the local ETL benchmark - -The CLI benchmark is feature-gated to keep the Shuttle build lightweight. - -From the repo root: +## Running locally +**ETL benchmark:** ```bash RUST_LOG=info cargo run --release --features bench-cli ``` -By default, the program looks for: - -``` -data/yellow_tripdata_2015-01.csv -``` - -Override via environment variable: - -```bash -DATA_PATH=/absolute/or/relative/path/to/your.csv \ -RUST_LOG=info cargo run --release --features bench-cli -``` - -### What it does - -`src/etl.rs` performs: - -1. **Load**: Lazy CSV scan (Polars) -2. **Clean**: Basic data preparation -3. **Aggregate**: Representative group-by computations -4. **Sort & filter**: Derive example counts -5. **Save**: Write results to `./results/` (ignored by Git) - -The CLI prints a summary and emits structured logs (JSON) with timing fields. - -## The Shuttle web service (observability demo) - -The Shuttle build exposes a small Axum API that simulates results and emits tracing events for observability. It avoids running the heavy ETL on ephemeral dynos. - -### Endpoints - -- `GET /` and `GET /health` — Simple health check (also emits a counter) -- `GET /benchmark` — Returns representative metrics and emits counters and histograms for dashboards - -Run locally as a normal binary: - +**Web service:** ```bash cargo run --release ``` -Deploy to Shuttle: - -```bash -cargo shuttle deploy -``` - -Shuttle will return a public URL like: - -``` -https://.shuttle.app -``` - -## Observability: tracing + OpenTelemetry - -This project uses: - -- `tracing` for structured events -- `tracing-subscriber` for JSON logs with RFC3339 timestamps -- `tracing-opentelemetry` to bridge spans/events to OTEL (when applicable) - -### How it is initialized +Place your CSV file at `./data/yellow_tripdata_2015-01.csv` or set `DATA_PATH=/path/to/file.csv`. -`src/observability.rs` sets up JSON logging for both CLI and server. When running on Shuttle, the platform injects an OTEL exporter that ships your events to the configured Telemetry destination (Better Stack). You don’t need to run or configure a collector. - -If you want to export to an OTLP endpoint when not on Shuttle, enable the `otel-otlp` feature and set: - -- `OTEL_EXPORTER_OTLP_ENDPOINT` (e.g., `http://localhost:4318`) -- `OTEL_EXPORTER_OTLP_HEADERS` (e.g., `Authorization=Bearer ...`) +## Deploy to Shuttle ```bash -cargo run --release --features otel-otlp +shuttle deploy ``` -## Metric events you can chart - -Shuttle’s telemetry pipeline interprets specific `tracing::info!` fields as metrics: - -- `monotonic_counter.*` → Cumulative counters (use rate for per-second/minute) -- `counter.*` → Values that can go up/down -- `histogram.*` → Distributions (p50, p95, avg, etc.) +## Endpoints -The Axum handlers emit a few examples: +- `GET /` - Health check +- `GET /health` - Health check with metrics +- `GET /benchmark` - Returns ETL metrics and emits telemetry events -```rust -// Count requests to /benchmark -tracing::info!(monotonic_counter.http_requests_total = 1, route="/benchmark", "Benchmark hit"); - -// Publish stage timings as histograms (ms) -tracing::info!(histogram.load_time_ms = 1.2_f64 * 1000.0, stage="load", "stage timing"); -tracing::info!(histogram.clean_time_ms = 0.8_f64 * 1000.0, stage="clean", "stage timing"); -tracing::info!(histogram.aggregate_time_ms = 0.4_f64 * 1000.0, stage="aggregate", "stage timing"); -tracing::info!(histogram.sort_filter_time_ms = 0.3_f64 * 1000.0, stage="sort_filter", "stage timing"); -tracing::info!(histogram.save_time_ms = 0.1_f64 * 1000.0, stage="save", "stage timing"); -tracing::info!(histogram.total_time_ms = 2.8_f64 * 1000.0, stage="total", "stage timing"); - -// Rows processed (cumulative) -tracing::info!(monotonic_counter.rows_processed = 12_748_986_i64, "rows processed (demo)"); - -// Request duration per call -let t0 = std::time::Instant::now(); -// ... work ... -let elapsed_ms = t0.elapsed().as_millis() as f64; -tracing::info!(histogram.request_duration_ms = elapsed_ms, route="/benchmark", "Benchmark responded"); - -// Health endpoint heartbeat -tracing::info!(monotonic_counter.health_checks = 1, "health checked"); -``` - -> **Tip**: Keep metric names short and stable; add contextual attributes like `route`, `stage`, or `dataset`. - -## Exporting to Better Stack with Shuttle - -1. In Better Stack, create a Telemetry Source (OpenTelemetry) and copy the Source Token. -2. In the Shuttle web console → your project → Settings, enable Better Stack and paste the Source Token; save. -3. Deploy (or redeploy) your app: - -```bash -cargo shuttle deploy -``` - -4. Hit the endpoints to generate events: - -```bash -curl -s https://.shuttle.app/benchmark >/dev/null -curl -s https://.shuttle.app/benchmark >/dev/null -curl -s https://.shuttle.app/health -``` +## Observability -That’s it—no collector, no sidecars. Shuttle forwards OTEL data to Better Stack. +The service emits OpenTelemetry metrics: +- `monotonic_counter.http_requests_total` - Request counts +- `histogram.request_duration_ms` - Request latency +- `histogram.*_time_ms` - ETL stage timings +- `monotonic_counter.rows_processed` - Data throughput -## Viewing data in Better Stack - -### 1. Logs stream (sanity check) - -- Better Stack → Telemetry → your Source → Logs -- Search for a field like `histogram.total_time_ms` or `monotonic_counter.http_requests_total` -- You should see JSON events with your attributes (`route`, `stage`, etc.) - -### 2. Dashboards - -Create a dashboard and add charts that query your metrics: - -#### Requests per route -- **Metric**: `monotonic_counter.http_requests_total` -- **Aggregation**: Rate (per 1m or 5m) -- **Group by**: `route` -- **Visualization**: Line - -#### Request duration -- **Metric**: `histogram.request_duration_ms` -- **Aggregation**: p95 (or avg, p50) -- **Group by**: `route` -- **Visualization**: Line - -#### ETL stage timings -- **Metrics**: `histogram.load_time_ms`, `histogram.clean_time_ms`, `histogram.aggregate_time_ms`, `histogram.sort_filter_time_ms`, `histogram.save_time_ms` -- **Aggregation**: Avg -- **Group by**: `stage` -- **Visualization**: Stacked area or multi-line - -#### Rows processed -- **Metric**: `monotonic_counter.rows_processed` -- **Aggregation**: Rate to see throughput -- **Visualization**: Bar or line - -> **Note**: If your organization uses Metrics (pre-computed time series derived from logs), you can define them for frequently queried fields to reduce query latency and cost. Keep metric cardinality low (limit unique combinations of attributes like `route`, `stage`, `dataset`). - -### 3. Explore (ad-hoc) - -Use Explore for quick, one-off queries over logs without defining Metrics. Search by your metric field names and filter by attributes. - -### 4. Using Better Stack’s built-in telemetry - -You should see fields like these in Explore / Logs: - -- `duration` (request/operation span duration) -- `service`, `span_name`, `name` -- `http_target` (route), `net_peer_name` -- `error`, `kind`, `tags` - -#### Quick dashboards from built-ins - -Create a Dashboard → Add chart → Metrics (or start in Explore and “Save as metric”): - -1. **HTTP latency (p95)** - - **Metric**: `duration` - - **Aggregation**: p95 - - **Group by**: `http_target` (or `span_name`) - - **Time grain**: 1m or 5m - Use this to see tail latency per route. - -2. **Request rate** - - **Measure**: `count()` of events - - **Filter**: `span_name` that corresponds to the HTTP request span (if present), or `http_target` exists - - **Aggregation**: Rate per minute - - **Group by**: `http_target` - This shows throughput per endpoint. - -3. **Error rate** - - **Filter**: `error = true` (or `severity_text >= ERROR` if you don’t have `error`) - - **Measure**: `count()` → rate - - **Group by**: `http_target` - Compare against total requests to get error percentage. - -4. **Slowest endpoints (top N)** - - **Metric**: `duration` - - **Aggregation**: Avg or p95 - - **Group by**: `http_target` - - **Sort**: Descending; show top 5–10. - -> **Tip**: `duration` might be in nanoseconds depending on exporter. If Better Stack allows unit transforms, you can divide to show ms; otherwise annotate the chart. - -#### Use your custom metrics (already in your code) - -You’re emitting: - -- `histogram.request_duration_ms` -- `histogram.total_time_ms`, `histogram.load_time_ms`, `histogram.clean_time_ms`, `histogram.aggregate_time_ms`, `histogram.sort_filter_time_ms`, `histogram.save_time_ms` -- `monotonic_counter.http_requests_total` -- `monotonic_counter.rows_processed` -- **Context attrs**: `route`, `stage` - -**Fastest path (no schema work): query logs directly** - -Dashboards → Metrics panel → “Logs” query (or Explore): - -- Search for `histogram.request_duration_ms` - - **Aggregation**: p95 (or avg) - - **Group by**: `route` - - **Time grain**: 1m - -- Same for ETL stage timings: - - Query `histogram.*_time_ms` - - **Aggregation**: Avg - - **Group by**: `stage` - -**Optional: define Metrics in Better Stack for low-latency charts** - -If you want sub-second dashboards (pre-computed time series), create Metrics from your log fields: - -1. In Better Stack → Telemetry → Metrics → New metric -2. **Source**: Your Shuttle source -3. **Field → Type**: - - `monotonic_counter.http_requests_total` → Counter (unit: “requests”, labels: `route`) - - `monotonic_counter.rows_processed` → Counter (unit: “rows”) - - `histogram.request_duration_ms` → Histogram (unit: “ms”, labels: `route`) - - `histogram.total_time_ms` / stage timings → Histogram (unit: “ms”, labels: `stage`) -4. Save, then use them in Dashboard charts: - - Counters → Rate or sum - - Histograms → p50/p95/avg - -Keep label cardinality low (e.g., small set of `route` or `stage` values) so queries stay fast. - -**Canonical “starter” charts (copy this structure)** - -- **Requests per route (rate)**: - - **Metric**: `monotonic_counter.http_requests_total` → rate(1m) → group by `route` -- **Request latency p95 per route**: - - **Metric**: `histogram.request_duration_ms` → p95 → group by `route` -- **ETL stage time (avg)**: - - **Metric**: `histogram.*_time_ms` → avg → group by `stage` (stacked area or multi-line) -- **Rows processed rate**: - - **Metric**: `monotonic_counter.rows_processed` → rate(1m) -- **Health checks**: - - Count or rate of events where `endpoint="/health"` (from your `tracing::info!`), grouped by `outcome` if you add one. - -**Sanity checklist if something doesn’t show** - -- Hit the endpoints a few times: - ```bash - curl -s https://.shuttle.app/benchmark >/dev/null - ``` -- In Better Stack → Telemetry → Logs: search `histogram.request_duration_ms` or `monotonic_counter.http_requests_total`. If you see them in logs, they can be charted. -- For built-ins like `duration`, search for spans with `http_target` present; use `p95(duration)`. - -That’s it—you can mix the built-ins (`duration`, `span_name`, `http_target`, `error`) with your custom counters/histograms to build a complete view without running an OTEL collector yourself. +When deployed on Shuttle with Better Stack integration enabled, these automatically appear in your telemetry dashboard. ## Configuration -### Environment variables - -- `DATA_PATH` — Path to the CSV for local runs; default `data/yellow_tripdata_2015-01.csv` - -### Feature flags - -- `bench-cli` — Builds the local CLI benchmark main. - ```bash - RUST_LOG=info cargo run --release --features bench-cli - ``` - -- `otel-otlp` — Enables an explicit OTLP exporter (used when running outside Shuttle). - ```bash - OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 \ - RUST_LOG=info cargo run --release --features otel-otlp - ``` - -> **Note**: On Shuttle, you do not need `otel-otlp`. The platform’s runtime exports data for you. - -## Performance notes - -The NYC Taxi CSV is large (~1.9GB). Expect high memory usage during local aggregation. Prefer running the full ETL locally; the Shuttle service intentionally returns representative numbers to keep the dyno responsive. - -For real pipelines, consider Parquet input and column pruning with Polars’ lazy API. - -## Troubleshooting - -### No telemetry in Better Stack -- Confirm Better Stack is enabled in Shuttle settings with a valid token. -- Redeploy after changing settings: `cargo shuttle deploy`. -- Hit endpoints a few times; then check Telemetry → Logs for `histogram.*` or `monotonic_counter.*`. -- Ensure you deployed without the `bench-cli` feature. +**Environment variables:** +- `DATA_PATH` - Path to CSV file (default: `data/yellow_tripdata_2015-01.csv`) -### Metrics not visible in dashboard picker -- Use the exact prefixes: `histogram.`, `counter.`, `monotonic_counter.`. -- Try Explore first; dashboards may take a short time after first ingestion. -- Keep attribute cardinality in check (e.g., a small set of `route`/`stage` values). - -### Data file not found (local CLI) -- Place your CSV at `./data/yellow_tripdata_2015-01.csv` or set `DATA_PATH=/path/to/file.csv`. - -## Shuttle and LogFire - -Today this template uses Shuttle’s OTEL → Better Stack integration. Shuttle is building towards streamlined integrations such as LogFire; keep an eye on the Shuttle site for updates: - -- [Shuttle](https://www.shuttle.dev/) - -## License - -MIT (or your preferred license) - -## Contributing - -Issues and PRs welcome. If you add new ETL stages, please also add tracing events for counters/histograms so dashboards stay valuable. - -## Appendix: Example responses - -**GET /benchmark** (representative payload): - -```json -{ - "metrics": { - "load_time": 1.2, - "clean_time": 0.8, - "aggregate_time": 0.4, - "sort_filter_time": 0.3, - "save_time": 0.1, - "total_time": 2.8 - }, - "message": "Demo benchmark complete (server-safe)", - "performance_summary": "Polars processed ~12.7M taxi records in ~2.8s (demo) → ~4550000 rows/sec via Rust + Polars + OTEL." -} -``` - -## Links - -- [Shuttle](https://www.shuttle.dev/) -- [Better Stack](https://betterstack.com/) -- [Polars](https://www.pola.rs/) -- [OpenTelemetry](https://opentelemetry.io/) -- [tracing (Rust)](https://docs.rs/tracing) -``` +**Features:** +- `bench-cli` - Enables local ETL benchmark +- `otel-otlp` - Enables OTLP export (for non-Shuttle deployments)