├── src ├── infrastructure │ ├── src │ │ ├── migrations │ │ │ ├── .keep │ │ │ ├── 2024-12-24-095227_initial │ │ │ │ ├── down.sql │ │ │ │ └── up.sql │ │ │ └── 00000000000000_diesel_initial_setup │ │ │ │ ├── down.sql │ │ │ │ └── up.sql │ │ ├── errors.rs │ │ ├── lib.rs │ │ ├── config.rs │ │ └── postgres_repositories.rs │ └── Cargo.toml ├── domain │ ├── src │ │ ├── entity.rs │ │ ├── lib.rs │ │ ├── schema.rs │ │ └── entities.rs │ └── Cargo.toml ├── starter │ ├── tests │ │ ├── utils │ │ │ ├── mod.rs │ │ │ └── test_server.rs │ │ ├── integration.rs │ │ └── memory_management_tests.rs │ ├── src │ │ ├── main.rs │ │ └── lib.rs │ └── Cargo.toml ├── presentation │ ├── src │ │ ├── lib.rs │ │ ├── api │ │ │ ├── mod.rs │ │ │ ├── api_doc.rs │ │ │ ├── api_health_check.rs │ │ │ └── app.rs │ │ ├── responses.rs │ │ ├── requests.rs │ │ ├── config.rs │ │ └── errors.rs │ └── Cargo.toml └── application │ ├── src │ ├── repositories.rs │ ├── dtos.rs │ ├── mappers.rs │ ├── lib.rs │ ├── queries.rs │ ├── handlers.rs │ ├── settings.rs │ └── services.rs │ └── Cargo.toml ├── deployment └── docker │ ├── postgres │ └── init.sql │ ├── docker-compose-infrastructure.sh │ ├── docker-compose-all.sh │ ├── docker-compose-app.yaml │ └── docker-compose-infrastructure.yaml ├── .env ├── config.app.toml ├── Dockerfile ├── diesel.toml ├── .dockerignore ├── .editorconfig ├── .github ├── dependabot.yml └── workflows │ ├── build-by-branch.yaml │ └── build-by-tag.yaml ├── LICENSE ├── Cargo.toml ├── .gitignore ├── README.md ├── TODO.md └── Cargo.lock /src/infrastructure/src/migrations/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/domain/src/entity.rs: -------------------------------------------------------------------------------- 1 | pub trait Entity {} 2 | -------------------------------------------------------------------------------- /src/starter/tests/utils/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod test_server; 2 | -------------------------------------------------------------------------------- /deployment/docker/postgres/init.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE rust_template_db; -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | DATABASE_URL=postgres://postgres:postgres@localhost/rust_template_db -------------------------------------------------------------------------------- /src/infrastructure/src/migrations/2024-12-24-095227_initial/down.sql: -------------------------------------------------------------------------------- 1 | -- This file should undo anything in `up.sql` 2 | DROP TABLE IF EXISTS to_do_items; 3 | -------------------------------------------------------------------------------- /src/domain/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod entities; 2 | mod entity; 3 | mod schema; 4 | 5 | pub use entities::ToDoItem; 6 | pub use entity::Entity; 7 | pub use schema::to_do_items; 8 | -------------------------------------------------------------------------------- /src/presentation/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod api; 2 | mod config; 3 | mod errors; 4 | mod requests; 5 | mod responses; 6 | 7 | pub use api::ApiDoc; 8 | pub use config::configure; 9 | -------------------------------------------------------------------------------- /deployment/docker/docker-compose-infrastructure.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export DOCKER_BUILDKIT=1 4 | export COMPOSE_DOCKER_CLI_BUILD=1 5 | docker-compose -f ./docker-compose-infrastructure.yaml "$@" 6 | -------------------------------------------------------------------------------- /config.app.toml: -------------------------------------------------------------------------------- 1 | [service] 2 | http_url = '127.0.0.1:8181' 3 | service_name = 'rust_template_service' 4 | 5 | [database] 6 | database_url = 'postgres://postgres:postgres@localhost:5432/rust_template_db' 7 | -------------------------------------------------------------------------------- /deployment/docker/docker-compose-all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export DOCKER_BUILDKIT=1 4 | export COMPOSE_DOCKER_CLI_BUILD=1 5 | docker-compose -f ./docker-compose-app.yaml -f ./docker-compose-infrastructure.yaml "$@" 6 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gcr.io/distroless/cc-debian12:nonroot 2 | 3 | EXPOSE 8080 4 | 5 | WORKDIR /app 6 | 7 | COPY ./target/release/starter . 8 | COPY config.app.toml . 9 | 10 | USER nonroot 11 | CMD ["./starter"] 12 | -------------------------------------------------------------------------------- /src/infrastructure/src/migrations/2024-12-24-095227_initial/up.sql: -------------------------------------------------------------------------------- 1 | -- Your SQL goes here 2 | CREATE TABLE IF NOT EXISTS to_do_items ( 3 | "id" uuid NOT NULL, 4 | "title" varchar(255), 5 | "note" varchar(255), 6 | CONSTRAINT "PK_ToDoItems" PRIMARY KEY ("id") 7 | ); 8 | -------------------------------------------------------------------------------- /deployment/docker/docker-compose-app.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | rust-template: 3 | build: 4 | context: ./../../ 5 | dockerfile: Dockerfile 6 | ports: 7 | - "0.0.0.0:8080:8080" 8 | networks: 9 | - rust-dev-network 10 | 11 | networks: 12 | rust-dev-network: 13 | -------------------------------------------------------------------------------- /src/infrastructure/src/errors.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | use uuid::Uuid; 3 | 4 | #[derive(Error, Debug)] 5 | pub enum Error { 6 | #[error("item with id {id} not found")] 7 | ItemNotFound { id: Uuid }, 8 | 9 | #[error("internal error: {0}")] 10 | InternalError(String), 11 | } 12 | -------------------------------------------------------------------------------- /src/domain/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "domain" 3 | version = "0.1.2" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | serde.workspace = true 10 | uuid.workspace = true 11 | diesel.workspace = true 12 | -------------------------------------------------------------------------------- /diesel.toml: -------------------------------------------------------------------------------- 1 | # For documentation on how to configure this file, 2 | # see https://diesel.rs/guides/configuring-diesel-cli 3 | 4 | [print_schema] 5 | file = "src/schema.rs" 6 | custom_type_derives = ["diesel::query_builder::QueryId", "Clone"] 7 | 8 | [migrations_directory] 9 | dir = "./src/infrastructure/src/migrations" 10 | -------------------------------------------------------------------------------- /src/domain/src/schema.rs: -------------------------------------------------------------------------------- 1 | use diesel::table; 2 | 3 | // @generated automatically by Diesel CLI. 4 | table! { 5 | to_do_items (id) { 6 | id -> Uuid, 7 | #[max_length = 255] 8 | title -> Nullable, 9 | #[max_length = 255] 10 | note -> Nullable, 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/infrastructure/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod config; 2 | mod errors; 3 | mod postgres_repositories; 4 | 5 | use diesel::{r2d2, PgConnection}; 6 | pub type DbPool = r2d2::Pool>; 7 | 8 | pub use config::configure; 9 | pub use errors::Error; 10 | pub use postgres_repositories::PostgresToDoItemRepository; 11 | -------------------------------------------------------------------------------- /src/presentation/src/api/mod.rs: -------------------------------------------------------------------------------- 1 | mod api_doc; 2 | mod api_health_check; 3 | mod app; 4 | 5 | pub use api_health_check::live; 6 | pub use api_health_check::ready; 7 | pub use api_health_check::startup; 8 | 9 | pub use api_doc::ApiDoc; 10 | 11 | pub use app::create; 12 | pub use app::delete; 13 | pub use app::get_all; 14 | pub use app::get_by_id; 15 | pub use app::update; 16 | -------------------------------------------------------------------------------- /src/starter/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate infrastructure; 2 | extern crate presentation; 3 | 4 | use anyhow::Result; 5 | use starter::run; 6 | #[actix_web::main] 7 | async fn main() -> Result<()> { 8 | dotenv::dotenv().ok(); 9 | env_logger::init_from_env(env_logger::Env::default().filter_or("RUST_LOG", "info")); 10 | run().await?.await?; 11 | 12 | Ok(()) 13 | } 14 | -------------------------------------------------------------------------------- /src/infrastructure/src/migrations/00000000000000_diesel_initial_setup/down.sql: -------------------------------------------------------------------------------- 1 | -- This file was automatically created by Diesel to setup helper functions 2 | -- and other internal bookkeeping. This file is safe to edit, any future 3 | -- changes will be added to existing projects as new migrations. 4 | 5 | DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass); 6 | DROP FUNCTION IF EXISTS diesel_set_updated_at(); 7 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | **/.classpath 2 | **/.dockerignore 3 | **/.env 4 | **/.git 5 | **/.gitignore 6 | **/.project 7 | **/.settings 8 | **/.toolstarget 9 | **/.vs 10 | **/.vscode 11 | **/*.*proj.user 12 | **/*.dbmdl 13 | **/*.jfm 14 | **/azds.yaml 15 | **/bin 16 | **/charts 17 | **/docker-compose* 18 | **/Dockerfile* 19 | **/node_modules 20 | **/npm-debug.log 21 | **/obj 22 | **/secrets.dev.yaml 23 | **/values.dev.yaml 24 | LICENSE 25 | README.md -------------------------------------------------------------------------------- /src/application/src/repositories.rs: -------------------------------------------------------------------------------- 1 | use async_trait::async_trait; 2 | use domain::ToDoItem; 3 | use uuid::Uuid; 4 | 5 | #[async_trait] 6 | pub trait ToDoItemRepository: Send + Sync { 7 | async fn get_all(&self) -> anyhow::Result>; 8 | async fn get_by_id(&self, id: Uuid) -> anyhow::Result; 9 | async fn save(&self, entity: ToDoItem) -> anyhow::Result; 10 | async fn delete(&self, id: Uuid) -> anyhow::Result<()>; 11 | } 12 | -------------------------------------------------------------------------------- /src/presentation/src/responses.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use utoipa::ToSchema; 3 | use uuid::Uuid; 4 | 5 | //TODO We need to implement mapping from entity to response 6 | #[readonly::make] 7 | #[derive(Deserialize, Serialize, ToSchema)] 8 | pub struct ToDoItemResponse { 9 | /// The id of the to-do item 10 | pub id: Uuid, 11 | /// The title of the to-do item 12 | pub title: String, 13 | /// The note of the to-do item 14 | pub note: String, 15 | } 16 | -------------------------------------------------------------------------------- /src/application/src/dtos.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use uuid::Uuid; 3 | 4 | #[readonly::make] 5 | #[derive(Deserialize, Serialize)] 6 | pub struct ToDoItemDto { 7 | pub id: Uuid, 8 | pub title: String, 9 | pub note: String, 10 | } 11 | 12 | impl ToDoItemDto { 13 | pub fn get() -> Self { 14 | Self { 15 | id: Uuid::new_v4(), 16 | title: "Test title".into(), 17 | note: "Test note".into(), 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | end_of_line = lf 9 | charset = utf-8 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | indent_style = space 13 | indent_size = 4 14 | 15 | [*.md] 16 | # double whitespace at end of line 17 | # denotes a line break in Markdown 18 | trim_trailing_whitespace = false 19 | 20 | [*.yml] 21 | indent_size = 2 -------------------------------------------------------------------------------- /src/infrastructure/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "infrastructure" 3 | version = "0.1.1" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | async-trait.workspace = true 10 | actix-web.workspace = true 11 | uuid.workspace = true 12 | anyhow.workspace = true 13 | thiserror.workspace = true 14 | diesel.workspace = true 15 | diesel_migrations.workspace = true 16 | 17 | domain = { path = "../domain" } 18 | application = { path = "../application" } 19 | -------------------------------------------------------------------------------- /src/application/src/mappers.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | use domain::ToDoItem; 3 | use tokio_postgres::Row; 4 | 5 | pub struct ToDoItemMapper {} 6 | 7 | impl ToDoItemMapper { 8 | pub fn from(row: Row) -> ToDoItem { 9 | ToDoItem::new_id(row.get("id"), row.get("title"), row.get("note")) 10 | } 11 | 12 | pub fn from_vec(rows: Vec) -> Vec { 13 | rows.iter() 14 | .map(|row| ToDoItem::new_id(row.get("id"), row.get("title"), row.get("note"))) 15 | .collect::>() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/presentation/src/api/api_doc.rs: -------------------------------------------------------------------------------- 1 | use crate::api::app::__path_create; 2 | use crate::api::app::__path_delete; 3 | use crate::api::app::__path_get_all; 4 | use crate::api::app::__path_get_by_id; 5 | use crate::api::app::__path_update; 6 | use utoipa::OpenApi; 7 | 8 | #[derive(OpenApi)] 9 | #[openapi( 10 | tags( 11 | (name = "todo", description = "Todo management endpoints.") 12 | ), 13 | paths( 14 | get_all, 15 | create, 16 | update, 17 | get_by_id, 18 | delete 19 | ) 20 | )] 21 | pub struct ApiDoc; 22 | -------------------------------------------------------------------------------- /src/presentation/src/requests.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use utoipa::ToSchema; 3 | 4 | #[readonly::make] 5 | #[derive(Deserialize, Serialize, ToSchema)] 6 | pub struct CreateToDoItemRequest { 7 | /// The title of the to-do item 8 | pub title: String, 9 | /// The note of the to-do item 10 | pub note: String, 11 | } 12 | 13 | #[readonly::make] 14 | #[derive(Deserialize, Serialize, ToSchema)] 15 | pub struct UpdateToDoItemRequest { 16 | /// The title of the to-do item 17 | pub title: String, 18 | /// The note of the to-do item 19 | pub note: String, 20 | } 21 | -------------------------------------------------------------------------------- /src/application/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "application" 3 | version = "0.1.2" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | readonly.workspace = true 10 | serde.workspace = true 11 | async-trait.workspace = true 12 | tokio-postgres.workspace = true 13 | uuid.workspace = true 14 | anyhow.workspace = true 15 | config.workspace = true 16 | 17 | domain = { path = "../domain" } 18 | 19 | [dev-dependencies] 20 | serial_test.workspace = true 21 | tokio.workspace = true 22 | async-trait.workspace = true 23 | -------------------------------------------------------------------------------- /src/presentation/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "presentation" 3 | version = "0.2.3" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | actix-web.workspace = true 10 | serde.workspace = true 11 | serde_json.workspace = true 12 | readonly.workspace = true 13 | uuid.workspace = true 14 | utoipa.workspace = true 15 | anyhow.workspace = true 16 | problem_details.workspace = true 17 | http.workspace = true 18 | 19 | application = { path = "../application" } 20 | infrastructure = { path = "../infrastructure" } 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/presentation/src/config.rs: -------------------------------------------------------------------------------- 1 | use crate::api; 2 | use actix_web::web; 3 | 4 | extern crate application; 5 | 6 | pub fn configure(cfg: &mut web::ServiceConfig) { 7 | cfg.service( 8 | web::scope("/to-do-items") 9 | .service(api::get_all) 10 | .service(api::create) 11 | .service(api::get_by_id) 12 | .service(api::update) 13 | .service(api::delete), 14 | ); 15 | cfg.service( 16 | web::scope("/healthz") 17 | .service(api::startup) 18 | .service(api::ready) 19 | .service(api::live), 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /deployment/docker/docker-compose-infrastructure.yaml: -------------------------------------------------------------------------------- 1 | volumes: 2 | postgres-rust: 3 | 4 | services: 5 | 6 | postgres: 7 | image: postgres:16-alpine 8 | environment: 9 | POSTGRES_PASSWORD: postgres 10 | ports: 11 | - "0.0.0.0:5432:5432" 12 | networks: 13 | - rust-dev-network 14 | volumes: 15 | - postgres-rust:/var/lib/postgresql/data 16 | - ./postgres/init.sql:/docker-entrypoint-initdb.d/init.sql 17 | healthcheck: 18 | test: ["CMD-SHELL", "PGPASSWORD=postgres pg_isready -U postgres -h postgres"] 19 | interval: 10s 20 | timeout: 30s 21 | retries: 15 22 | 23 | networks: 24 | rust-dev-network: 25 | -------------------------------------------------------------------------------- /src/application/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod dtos; 2 | mod handlers; 3 | mod mappers; 4 | mod queries; 5 | mod repositories; 6 | mod services; 7 | mod settings; 8 | 9 | pub use crate::settings::Settings; 10 | 11 | pub use crate::repositories::ToDoItemRepository; 12 | 13 | pub use crate::dtos::ToDoItemDto; 14 | 15 | pub use crate::queries::{ 16 | CreateToDoItemQuery, DeleteToDoItemQuery, GetToDoItemQuery, UpdateToDoItemQuery, 17 | }; 18 | 19 | pub use crate::handlers::{ 20 | CreateToDoItemQueryHandler, DeleteToDoItemQueryHandler, GetAllToDoItemQueryHandler, 21 | GetToDoItemQueryHandler, UpdateToDoItemQueryHandler, 22 | }; 23 | 24 | pub use crate::services::{ToDoItemService, ToDoItemServiceBoxed}; 25 | -------------------------------------------------------------------------------- /src/infrastructure/src/config.rs: -------------------------------------------------------------------------------- 1 | use application::Settings; 2 | use diesel::r2d2::{ConnectionManager, Pool}; 3 | use diesel::{prelude::*, r2d2}; 4 | use diesel_migrations::*; 5 | 6 | pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("./src/migrations"); 7 | 8 | type DbPool = r2d2::Pool>; 9 | 10 | pub async fn configure(settings: &Settings) -> anyhow::Result { 11 | let mut connection = PgConnection::establish(settings.database.database_url.as_str())?; 12 | connection.run_pending_migrations(MIGRATIONS).unwrap(); 13 | 14 | let manager = ConnectionManager::::new(settings.database.database_url.as_str()); 15 | Ok(Pool::builder().build(manager)?) 16 | } 17 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "cargo" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | - package-ecosystem: "github-actions" 13 | directory: "/" 14 | schedule: 15 | interval: "weekly" 16 | - package-ecosystem: "docker" 17 | directory: "/" 18 | schedule: 19 | interval: "weekly" 20 | -------------------------------------------------------------------------------- /src/domain/src/entities.rs: -------------------------------------------------------------------------------- 1 | use diesel::prelude::*; 2 | use serde::{Deserialize, Serialize}; 3 | use uuid::Uuid; 4 | 5 | use crate::entity; 6 | use crate::schema::to_do_items; 7 | 8 | #[derive(Queryable, Insertable, AsChangeset, Serialize, Deserialize, PartialEq, Debug, Clone)] 9 | #[diesel(table_name = to_do_items)] 10 | pub struct ToDoItem { 11 | pub id: Uuid, 12 | pub title: Option, 13 | pub note: Option, 14 | } 15 | 16 | impl ToDoItem { 17 | pub fn new(title: String, note: String) -> Self { 18 | Self { 19 | id: Uuid::new_v4(), 20 | title: Some(title), 21 | note: Some(note), 22 | } 23 | } 24 | 25 | pub fn new_id(id: Uuid, title: String, note: String) -> Self { 26 | Self { 27 | id, 28 | title: Some(title), 29 | note: Some(note), 30 | } 31 | } 32 | } 33 | 34 | impl entity::Entity for ToDoItem {} 35 | -------------------------------------------------------------------------------- /src/starter/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "starter" 3 | version = "0.5.6" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | log.workspace = true 10 | env_logger.workspace = true 11 | actix-web.workspace = true 12 | tokio.workspace = true 13 | anyhow.workspace = true 14 | reqwest.workspace = true 15 | dotenv.workspace = true 16 | utoipa.workspace = true 17 | utoipa-actix-web.workspace = true 18 | utoipa-swagger-ui.workspace = true 19 | 20 | application = { path = "../application" } 21 | presentation = { path = "../presentation" } 22 | infrastructure = { path = "../infrastructure" } 23 | 24 | [dev-dependencies] 25 | testcontainers.workspace = true 26 | testcontainers-modules.workspace = true 27 | ctor.workspace = true 28 | serial_test.workspace = true 29 | uuid.workspace = true 30 | async-trait.workspace = true 31 | domain = { path = "../domain" } 32 | -------------------------------------------------------------------------------- /.github/workflows/build-by-branch.yaml: -------------------------------------------------------------------------------- 1 | name: build-by-branch 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - feature/* 8 | - fix/* 9 | paths-ignore: 10 | - "**.md" 11 | pull_request: 12 | branches: 13 | - main 14 | paths-ignore: 15 | - "**.md" 16 | jobs: 17 | build: 18 | runs-on: ubuntu-latest 19 | timeout-minutes: 10 20 | steps: 21 | - name: Checkout 22 | uses: actions/checkout@v5 23 | - name: Cache 24 | uses: actions/cache@v4 25 | with: 26 | path: | 27 | ~/.cargo/registry 28 | ~/.cargo/git 29 | target 30 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} 31 | - name: Install Rust toolchain 32 | uses: dtolnay/rust-toolchain@stable 33 | with: 34 | toolchain: stable 35 | components: rustfmt, clippy 36 | - name: Check code style 37 | run: cargo fmt -- --check 38 | - name: Build 39 | run: cargo build --release --all-features 40 | - name: Check code 41 | run: cargo clippy 42 | - name: Tests 43 | run: cargo test 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 nkz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/application/src/queries.rs: -------------------------------------------------------------------------------- 1 | use uuid::Uuid; 2 | 3 | pub struct GetToDoItemQuery { 4 | pub id: Option, 5 | } 6 | 7 | impl GetToDoItemQuery { 8 | pub fn new(id: Option) -> Self { 9 | GetToDoItemQuery { id } 10 | } 11 | } 12 | 13 | pub struct CreateToDoItemQuery { 14 | pub title: String, 15 | pub note: String, 16 | } 17 | 18 | impl CreateToDoItemQuery { 19 | pub fn new(title: &String, note: &String) -> Self { 20 | CreateToDoItemQuery { 21 | title: title.into(), 22 | note: note.into(), 23 | } 24 | } 25 | } 26 | 27 | pub struct UpdateToDoItemQuery { 28 | pub id: Uuid, 29 | pub title: String, 30 | pub note: String, 31 | } 32 | 33 | impl UpdateToDoItemQuery { 34 | pub fn new(id: Uuid, title: &String, note: &String) -> Self { 35 | UpdateToDoItemQuery { 36 | id, 37 | title: title.into(), 38 | note: note.into(), 39 | } 40 | } 41 | } 42 | 43 | pub struct DeleteToDoItemQuery { 44 | pub id: Uuid, 45 | } 46 | 47 | impl DeleteToDoItemQuery { 48 | pub fn new(id: Uuid) -> Self { 49 | DeleteToDoItemQuery { id } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/presentation/src/api/api_health_check.rs: -------------------------------------------------------------------------------- 1 | use actix_web::{get, Error, HttpRequest, HttpResponse}; 2 | 3 | const OK_STATUS: &str = "Ok"; 4 | 5 | /// Handles the health check for the application startup. 6 | /// 7 | /// This endpoint is used to check if the application is up and running. 8 | /// It returns a response with the current status of the application. 9 | #[get("startup")] 10 | pub async fn startup(_: HttpRequest) -> actix_web::Result { 11 | Ok(HttpResponse::Ok().body(OK_STATUS)) 12 | } 13 | 14 | /// Handles the health check for the application's live status. 15 | /// 16 | /// This endpoint is used to check if the application is currently live and accepting requests. 17 | /// It returns a response with the current status of the application. 18 | #[get("live")] 19 | pub async fn live(_: HttpRequest) -> actix_web::Result { 20 | Ok(HttpResponse::Ok().body(OK_STATUS)) 21 | } 22 | 23 | /// Handles the health check for the application's ready status. 24 | /// 25 | /// This endpoint is used to check if the application is currently ready to handle requests. 26 | /// It returns a response with the current status of the application. 27 | #[get("ready")] 28 | pub async fn ready(_: HttpRequest) -> actix_web::Result { 29 | Ok(HttpResponse::Ok().body(OK_STATUS)) 30 | } 31 | -------------------------------------------------------------------------------- /src/infrastructure/src/migrations/00000000000000_diesel_initial_setup/up.sql: -------------------------------------------------------------------------------- 1 | -- This file was automatically created by Diesel to setup helper functions 2 | -- and other internal bookkeeping. This file is safe to edit, any future 3 | -- changes will be added to existing projects as new migrations. 4 | 5 | 6 | 7 | 8 | -- Sets up a trigger for the given table to automatically set a column called 9 | -- `updated_at` whenever the row is modified (unless `updated_at` was included 10 | -- in the modified columns) 11 | -- 12 | -- # Example 13 | -- 14 | -- ```sql 15 | -- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW()); 16 | -- 17 | -- SELECT diesel_manage_updated_at('users'); 18 | -- ``` 19 | CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$ 20 | BEGIN 21 | EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s 22 | FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl); 23 | END; 24 | $$ LANGUAGE plpgsql; 25 | 26 | CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$ 27 | BEGIN 28 | IF ( 29 | NEW IS DISTINCT FROM OLD AND 30 | NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at 31 | ) THEN 32 | NEW.updated_at := current_timestamp; 33 | END IF; 34 | RETURN NEW; 35 | END; 36 | $$ LANGUAGE plpgsql; 37 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "src/domain", 4 | "src/infrastructure", 5 | "src/application", 6 | "src/presentation", 7 | "src/starter" 8 | ] 9 | resolver = "2" 10 | 11 | [workspace.dependencies] 12 | 13 | # Web 14 | actix-web = "4.11.0" 15 | problem_details = { version = "0.8.0", features = ["actix", "json"] } 16 | http = "1.3.1" 17 | 18 | # OpenAPI 19 | utoipa = { version = "5.4.0", features = ["actix_extras", "uuid"] } 20 | utoipa-actix-web = "0.1.2" 21 | utoipa-swagger-ui = { version = "8.1.1", features = ["actix-web"] } 22 | 23 | # Serialization 24 | serde = { version = "1.0.219", features = ["derive"] } 25 | serde_json = "1.0.145" 26 | 27 | # Async 28 | tokio = { version = "1.47.0", features = ["full"] } 29 | async-trait = "0.1.89" 30 | 31 | # Database and ORM 32 | tokio-postgres = { version = "0.7.13", features = ["with-uuid-1"] } 33 | diesel = { version = "2.2.12", features = ["postgres", "r2d2", "uuid"] } 34 | diesel_migrations = "2.0.0" 35 | 36 | # Logging 37 | log = "0.4.27" 38 | env_logger = "0.11.6" 39 | tracing = "0.1.41" 40 | 41 | # Configuration 42 | dotenv = "0.15.0" 43 | config = "0.15.16" 44 | 45 | # Error Handling 46 | anyhow = "1.0.98" 47 | thiserror = "2.0.12" 48 | 49 | # Testing 50 | testcontainers = "0.23.3" 51 | testcontainers-modules = { version = "0.11.6", features = ["postgres"] } 52 | reqwest = { version = "0.12.22", features = ["json"]} 53 | serial_test = "3.2.0" 54 | 55 | # Misc 56 | ctor = "0.2.9" 57 | uuid = { version = "1.18.1", features = ["v4", "serde"] } 58 | readonly = "0.2.13" 59 | -------------------------------------------------------------------------------- /.github/workflows/build-by-tag.yaml: -------------------------------------------------------------------------------- 1 | name: build-by-tag 2 | 3 | on: 4 | push: 5 | tags: 6 | - '**' # Push events to every tag including hierarchical tags like v1.0/beta 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | timeout-minutes: 5 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v5 15 | - name: Cache 16 | uses: actions/cache@v4 17 | with: 18 | path: | 19 | ~/.cargo/registry 20 | ~/.cargo/git 21 | target 22 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} 23 | - name: Install Rust toolchain 24 | uses: dtolnay/rust-toolchain@stable 25 | with: 26 | toolchain: stable 27 | - name: Build 28 | run: cargo build --release --all-features 29 | - name: Docker meta 30 | id: meta 31 | uses: docker/metadata-action@v5 32 | with: 33 | images: ghcr.io/nkz-soft/rust-microservice-template/rust-microservice-template 34 | - name: Login to Github Packages 35 | uses: docker/login-action@v3 36 | with: 37 | registry: ghcr.io 38 | username: ${{ github.actor }} 39 | password: ${{ secrets.GITHUB_TOKEN }} 40 | - name: Build image and push to GitHub Container Registry 41 | uses: docker/build-push-action@v6 42 | with: 43 | context: . 44 | push: ${{ github.event_name != 'pull_request' }} 45 | tags: ${{ steps.meta.outputs.tags }} 46 | - name: Image digest 47 | run: echo ${{ steps.docker_build.outputs.digest }} 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # This file should only ignore things that are generated during a `x.py` build, 2 | # generated by common IDEs, and optional files controlled by the user that 3 | # affect the build (such as config.toml). 4 | # In particular, things like `mir_dump` should not be listed here; they are only 5 | # created during manual debugging and many people like to clean up instead of 6 | # having git ignore such leftovers. You can use `.git/info/exclude` to 7 | # configure your local ignore list. 8 | 9 | ## File system 10 | .DS_Store 11 | desktop.ini 12 | 13 | ## Editor 14 | *.swp 15 | *.swo 16 | Session.vim 17 | .cproject 18 | .idea 19 | *.iml 20 | .vscode 21 | .project 22 | .favorites.json 23 | .settings/ 24 | .vs/ 25 | 26 | ## Tool 27 | .valgrindrc 28 | .cargo 29 | # Included because it is part of the test case 30 | !/tests/run-make/thumb-none-qemu/example/.cargo 31 | 32 | ## Configuration 33 | /config.toml 34 | /Makefile 35 | config.mk 36 | config.stamp 37 | no_llvm_build 38 | 39 | ## Build 40 | /dl/ 41 | /doc/ 42 | /inst/ 43 | /llvm/ 44 | /mingw-build/ 45 | build/ 46 | !/compiler/rustc_mir_build/src/build/ 47 | /build-rust-analyzer/ 48 | /dist/ 49 | /unicode-downloads 50 | /target 51 | /src/bootstrap/target 52 | /src/tools/x/target 53 | # Created by default with `src/ci/docker/run.sh` 54 | /obj/ 55 | 56 | ## Temporary files 57 | *~ 58 | \#* 59 | \#*\# 60 | .#* 61 | 62 | ## Tags 63 | tags 64 | tags.* 65 | TAGS 66 | TAGS.* 67 | 68 | ## Python 69 | __pycache__/ 70 | *.py[cod] 71 | *$py.class 72 | 73 | ## Node 74 | node_modules 75 | package-lock.json 76 | package.json 77 | 78 | ## Rustdoc GUI tests 79 | tests/rustdoc-gui/src/**.lock 80 | 81 | # JetBrains Rider 82 | .idea/ 83 | *.sln.iml 84 | 85 | # Before adding new lines, see the comment at the top. 86 | -------------------------------------------------------------------------------- /src/infrastructure/src/postgres_repositories.rs: -------------------------------------------------------------------------------- 1 | use crate::errors::Error::ItemNotFound; 2 | use crate::DbPool; 3 | use actix_web::web::Data; 4 | use anyhow::anyhow; 5 | use application::ToDoItemRepository; 6 | use async_trait::async_trait; 7 | use diesel::ExpressionMethods; 8 | use diesel::{OptionalExtension, QueryDsl, RunQueryDsl}; 9 | use domain::to_do_items::dsl::to_do_items; 10 | use domain::to_do_items::id; 11 | use domain::ToDoItem; 12 | use uuid::Uuid; 13 | 14 | pub struct PostgresToDoItemRepository { 15 | pool: Data, 16 | } 17 | 18 | impl PostgresToDoItemRepository { 19 | pub fn new(pool: &Data) -> Self { 20 | Self { pool: pool.clone() } 21 | } 22 | } 23 | 24 | #[async_trait] 25 | impl ToDoItemRepository for PostgresToDoItemRepository { 26 | async fn get_all(&self) -> anyhow::Result> { 27 | let mut connection = self.pool.get()?; 28 | let items = to_do_items.load(&mut connection)?; 29 | Ok(items) 30 | } 31 | 32 | async fn get_by_id(&self, item_id: Uuid) -> anyhow::Result { 33 | let mut connection = self.pool.get()?; 34 | to_do_items 35 | .filter(id.eq(&item_id)) 36 | .first::(&mut connection) 37 | .optional()? 38 | .ok_or(anyhow!(ItemNotFound { id: item_id })) 39 | } 40 | 41 | async fn save(&self, entity: ToDoItem) -> anyhow::Result { 42 | let mut connection = self.pool.get()?; 43 | diesel::insert_into(to_do_items) 44 | .values(&entity) 45 | .on_conflict(id) 46 | .do_update() 47 | .set(&entity) 48 | .execute(&mut connection)?; 49 | Ok(entity.id) 50 | } 51 | 52 | async fn delete(&self, item_id: Uuid) -> anyhow::Result<()> { 53 | let mut connection = self.pool.get()?; 54 | diesel::delete(to_do_items.filter(id.eq(&item_id))).execute(&mut connection)?; 55 | Ok(()) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/starter/src/lib.rs: -------------------------------------------------------------------------------- 1 | use actix_web::dev::Server; 2 | use actix_web::middleware::Logger; 3 | use actix_web::{web, App, HttpServer}; 4 | use anyhow::Result; 5 | use application::{Settings, ToDoItemService}; 6 | use infrastructure::PostgresToDoItemRepository; 7 | use log::{debug, info}; 8 | use std::sync::Arc; 9 | use utoipa::OpenApi; 10 | use utoipa_actix_web::AppExt; 11 | use utoipa_swagger_ui::SwaggerUi; 12 | 13 | pub async fn run() -> Result { 14 | let settings = Settings::default().load()?; 15 | run_internal(&settings).await 16 | } 17 | 18 | pub async fn run_with_config(path: &str) -> Result { 19 | let settings = Settings::with_path(path).load()?; 20 | run_internal(&settings).await 21 | } 22 | 23 | async fn run_internal(settings: &Settings) -> Result { 24 | info!("Starting HTTP server at {}", &settings.service.http_url); 25 | debug!("with configuration: {:?}", &settings); 26 | 27 | let pool = infrastructure::configure(settings).await?; 28 | 29 | // Create repository with Arc for thread safety 30 | let repository = Arc::new(PostgresToDoItemRepository::new(&web::Data::new( 31 | pool.clone(), 32 | ))); 33 | 34 | // Create service with dependency injection 35 | let todo_service = ToDoItemService::new(repository); 36 | 37 | let server = HttpServer::new(move || { 38 | App::new() 39 | .into_utoipa_app() 40 | .openapi(presentation::ApiDoc::openapi()) 41 | .map(|app| app.wrap(Logger::default())) 42 | .map(|app| app.configure(presentation::configure)) 43 | .openapi_service(|api| { 44 | SwaggerUi::new("/swagger-ui/{_:.*}").url("/api-docs/openapi.json", api) 45 | }) 46 | .app_data(web::Data::new(pool.clone())) 47 | .app_data(web::Data::new(todo_service.clone())) 48 | .into_app() 49 | }) 50 | .bind(&settings.service.http_url)? 51 | .run(); 52 | 53 | Ok(server) 54 | } 55 | -------------------------------------------------------------------------------- /src/presentation/src/errors.rs: -------------------------------------------------------------------------------- 1 | use actix_web::web::Json; 2 | use actix_web::{HttpResponse, ResponseError}; 3 | use http::StatusCode as HttpStatusCode; 4 | use infrastructure as errors; 5 | use problem_details::{JsonProblemDetails, ProblemDetails}; 6 | use serde_json::Error as SerdeError; 7 | use std::fmt::{Display, Formatter}; 8 | 9 | #[derive(Debug)] 10 | pub enum HttpError { 11 | Problem(ProblemDetails), 12 | } 13 | 14 | impl Display for HttpError { 15 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 16 | write!(f, "{:?}", self) 17 | } 18 | } 19 | 20 | impl ResponseError for HttpError { 21 | fn error_response(&self) -> HttpResponse { 22 | match self { 23 | HttpError::Problem(problem) => HttpResponse::build(problem.status_code()) 24 | .content_type(JsonProblemDetails::<()>::CONTENT_TYPE) 25 | .json(Json(problem)), 26 | } 27 | } 28 | } 29 | 30 | impl From for HttpError { 31 | fn from(err: SerdeError) -> Self { 32 | HttpError::Problem( 33 | ProblemDetails::new() 34 | .with_status(HttpStatusCode::INTERNAL_SERVER_ERROR) 35 | .with_detail(err.to_string()), 36 | ) 37 | } 38 | } 39 | 40 | impl From for HttpError { 41 | fn from(err: anyhow::Error) -> Self { 42 | if let Some(err) = err.downcast_ref::() { 43 | match err { 44 | errors::Error::ItemNotFound { .. } => HttpError::Problem( 45 | ProblemDetails::new() 46 | .with_status(HttpStatusCode::NOT_FOUND) 47 | .with_detail(err.to_string()), 48 | ), 49 | _ => HttpError::Problem( 50 | ProblemDetails::new() 51 | .with_status(HttpStatusCode::INTERNAL_SERVER_ERROR) 52 | .with_detail(err.to_string()), 53 | ), 54 | } 55 | } else { 56 | HttpError::Problem( 57 | ProblemDetails::new() 58 | .with_status(HttpStatusCode::INTERNAL_SERVER_ERROR) 59 | .with_detail(err.to_string()), 60 | ) 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/starter/tests/utils/test_server.rs: -------------------------------------------------------------------------------- 1 | use ctor::dtor; 2 | use std::time::Duration; 3 | use testcontainers::core::IntoContainerPort; 4 | use testcontainers::{ContainerAsync, ImageExt}; 5 | use testcontainers_modules::postgres::Postgres; 6 | use testcontainers_modules::testcontainers::runners::AsyncRunner; 7 | use tokio::sync::OnceCell; 8 | use tokio::task::JoinHandle; 9 | 10 | const CONFIG_FILE_PATH: &str = "./../../"; 11 | 12 | #[macro_export] 13 | macro_rules! prepare_test_environment { 14 | () => {{ 15 | test_server::init().await; 16 | reqwest::Client::new() 17 | }}; 18 | } 19 | 20 | pub struct Server { 21 | #[allow(dead_code)] 22 | server_handle: JoinHandle<()>, 23 | container: ContainerAsync, 24 | } 25 | 26 | impl Server { 27 | pub async fn start() -> Self { 28 | let container = Postgres::default() 29 | .with_db_name("rust_template_db") 30 | .with_mapped_port(5432, 5432.tcp()) 31 | .with_tag("16-alpine") 32 | .start() 33 | .await 34 | .unwrap(); 35 | 36 | let server_handle = tokio::spawn(async move { 37 | let server = starter::run_with_config(CONFIG_FILE_PATH) 38 | .await 39 | .expect("Failed to bind address"); 40 | let _server_task = tokio::spawn(server); 41 | }); 42 | tokio::time::sleep(Duration::from_secs(1)).await; 43 | Server { 44 | server_handle, 45 | container, 46 | } 47 | } 48 | 49 | pub fn container(&self) -> &ContainerAsync { 50 | &self.container 51 | } 52 | } 53 | 54 | pub(crate) static TEST_SERVER_ONCE: OnceCell = OnceCell::const_new(); 55 | 56 | pub(crate) async fn init() { 57 | TEST_SERVER_ONCE.get_or_init(Server::start).await; 58 | } 59 | 60 | //see https://stackoverflow.com/questions/78969766/how-can-i-call-drop-in-a-tokio-static-oncelock-in-rust 61 | #[dtor] 62 | fn cleanup() { 63 | //This is crazy but it works 64 | let id = TEST_SERVER_ONCE.get().unwrap().container().id(); 65 | 66 | std::process::Command::new("docker") 67 | .arg("kill") 68 | .arg(id) 69 | .output() 70 | .expect("failed to kill container"); 71 | } 72 | -------------------------------------------------------------------------------- /src/application/src/handlers.rs: -------------------------------------------------------------------------------- 1 | use crate::queries::*; 2 | use crate::repositories::*; 3 | use domain::ToDoItem; 4 | use std::sync::Arc; 5 | use uuid::Uuid; 6 | 7 | pub struct GetToDoItemQueryHandler { 8 | repository: Arc, 9 | } 10 | 11 | impl GetToDoItemQueryHandler { 12 | pub fn new(repository: Arc) -> GetToDoItemQueryHandler { 13 | GetToDoItemQueryHandler { repository } 14 | } 15 | 16 | pub async fn execute(&self, query: GetToDoItemQuery) -> anyhow::Result { 17 | self.repository.get_by_id(query.id.unwrap()).await 18 | } 19 | } 20 | 21 | pub struct GetAllToDoItemQueryHandler { 22 | repository: Arc, 23 | } 24 | 25 | impl GetAllToDoItemQueryHandler { 26 | pub fn new( 27 | repository: Arc, 28 | ) -> GetAllToDoItemQueryHandler { 29 | GetAllToDoItemQueryHandler { repository } 30 | } 31 | 32 | pub async fn execute(&self) -> anyhow::Result> { 33 | self.repository.get_all().await 34 | } 35 | } 36 | 37 | pub struct CreateToDoItemQueryHandler { 38 | repository: Arc, 39 | } 40 | 41 | impl CreateToDoItemQueryHandler { 42 | pub fn new( 43 | repository: Arc, 44 | ) -> CreateToDoItemQueryHandler { 45 | CreateToDoItemQueryHandler { repository } 46 | } 47 | 48 | pub async fn execute(&self, query: CreateToDoItemQuery) -> anyhow::Result { 49 | self.repository 50 | .save(ToDoItem::new(query.title, query.note)) 51 | .await 52 | } 53 | } 54 | 55 | pub struct UpdateToDoItemQueryHandler { 56 | repository: Arc, 57 | } 58 | 59 | impl UpdateToDoItemQueryHandler { 60 | pub fn new( 61 | repository: Arc, 62 | ) -> UpdateToDoItemQueryHandler { 63 | UpdateToDoItemQueryHandler { repository } 64 | } 65 | 66 | pub async fn execute(&self, query: UpdateToDoItemQuery) -> anyhow::Result { 67 | self.repository 68 | .save(ToDoItem::new_id(query.id, query.title, query.note)) 69 | .await 70 | } 71 | } 72 | 73 | pub struct DeleteToDoItemQueryHandler { 74 | repository: Arc, 75 | } 76 | 77 | impl DeleteToDoItemQueryHandler { 78 | pub fn new( 79 | repository: Arc, 80 | ) -> DeleteToDoItemQueryHandler { 81 | DeleteToDoItemQueryHandler { repository } 82 | } 83 | 84 | pub async fn execute(&self, query: DeleteToDoItemQuery) -> anyhow::Result<()> { 85 | self.repository.delete(query.id).await 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/application/src/settings.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use config::{Config, ConfigError, Environment, File}; 3 | use serde::{Deserialize, Serialize}; 4 | pub const CONFIG_FILE_NAME: &str = "config.app.toml"; 5 | pub const DEFAULT_ENV_PREFIX_NAME: &str = "MICROSERVICE"; 6 | 7 | #[readonly::make] 8 | #[derive(Serialize, Deserialize, Debug)] 9 | pub struct Settings { 10 | pub service: Service, 11 | pub database: Database, 12 | pub path: Option, 13 | } 14 | 15 | #[readonly::make] 16 | #[derive(Serialize, Deserialize, Debug)] 17 | pub struct Service { 18 | pub http_url: String, 19 | pub service_name: String, 20 | } 21 | 22 | #[readonly::make] 23 | #[derive(Serialize, Deserialize, Debug)] 24 | pub struct Database { 25 | pub database_url: String, 26 | } 27 | 28 | impl Default for Settings { 29 | fn default() -> Self { 30 | Self { 31 | service: Service { 32 | http_url: "127.0.0.1:8080".into(), 33 | service_name: DEFAULT_ENV_PREFIX_NAME.to_string(), 34 | }, 35 | database: Database { 36 | database_url: "postgres://postgres:postgres@localhost:5432/rust_template_db".into(), 37 | }, 38 | path: Some("./".into()), 39 | } 40 | } 41 | } 42 | 43 | impl Settings { 44 | pub fn with_path(path: &str) -> Self { 45 | Self { 46 | path: Some(path.into()), 47 | ..Self::default() 48 | } 49 | } 50 | 51 | pub fn load(&self) -> Result { 52 | let builder = Config::builder(); 53 | let full_path = self.path.clone().unwrap() + CONFIG_FILE_NAME; 54 | builder 55 | .add_source(File::with_name(full_path.as_str()).required(true)) 56 | .add_source( 57 | Environment::default() 58 | .prefix(DEFAULT_ENV_PREFIX_NAME) 59 | .prefix_separator("__") 60 | .separator("__") 61 | .try_parsing(true), 62 | ) 63 | .build()? 64 | .try_deserialize() 65 | } 66 | } 67 | 68 | #[cfg(test)] 69 | mod tests { 70 | use super::*; 71 | use serial_test::serial; 72 | use std::env; 73 | 74 | #[serial] 75 | #[test] 76 | fn default_settings_test() { 77 | let settings = Settings::default(); 78 | assert_eq!(settings.service.http_url, "127.0.0.1:8080"); 79 | assert_eq!(settings.service.service_name, "MICROSERVICE"); 80 | } 81 | 82 | #[serial] 83 | #[test] 84 | fn with_path_settings_test() { 85 | let settings = Settings::with_path("./../../").load().unwrap(); 86 | assert_eq!(settings.service.http_url, "127.0.0.1:8181"); 87 | assert_eq!(settings.service.service_name, "rust_template_service"); 88 | assert_eq!( 89 | settings.database.database_url, 90 | "postgres://postgres:postgres@localhost:5432/rust_template_db" 91 | ); 92 | } 93 | 94 | #[serial] 95 | #[test] 96 | fn with_path_settings_override_env_test() { 97 | env::set_var("MICROSERVICE__SERVICE__HTTP_URL", "localhost:8080"); 98 | env::set_var( 99 | "MICROSERVICE__DATABASE__DATABASE_URL", 100 | "postgres://postgres1:postgres1@localhost:5432/rust_template_db", 101 | ); 102 | let settings = Settings::with_path("./../../").load().unwrap(); 103 | assert_eq!(settings.service.http_url, "localhost:8080"); 104 | assert_eq!( 105 | settings.database.database_url, 106 | "postgres://postgres1:postgres1@localhost:5432/rust_template_db" 107 | ); 108 | env::remove_var("MICROSERVICE__SERVICE__HTTP_URL"); 109 | env::remove_var("MICROSERVICE__DATABASE__DATABASE_URL"); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/presentation/src/api/app.rs: -------------------------------------------------------------------------------- 1 | use actix_web::web::Data; 2 | use actix_web::{delete, post, put}; 3 | use actix_web::{get, http, web, HttpResponse, Result}; 4 | use application::CreateToDoItemQuery; 5 | use application::DeleteToDoItemQuery; 6 | use application::GetToDoItemQuery; 7 | use application::ToDoItemService; 8 | use application::UpdateToDoItemQuery; 9 | use uuid::Uuid; 10 | 11 | use crate::errors::HttpError; 12 | use crate::requests::{CreateToDoItemRequest, UpdateToDoItemRequest}; 13 | use crate::responses::ToDoItemResponse; 14 | 15 | const TODO: &str = "todo"; 16 | 17 | /// Retrieves a list of all to-do items. 18 | #[utoipa::path( 19 | context_path = "/to-do-items", 20 | tag = TODO, 21 | responses( 22 | (status = 200, description = "List current todo items", body = [ToDoItemResponse]) 23 | ) 24 | )] 25 | #[get("")] 26 | pub async fn get_all(service: Data) -> Result { 27 | let handler = service.get_all_handler(); 28 | let data = handler.execute().await?; 29 | 30 | Ok(HttpResponse::Ok() 31 | .content_type(http::header::ContentType::json()) 32 | .body(serde_json::to_string(&data)?)) 33 | } 34 | 35 | /// Retrieves a to-do item by Id. 36 | #[utoipa::path( 37 | context_path = "/to-do-items", 38 | tag = TODO, 39 | responses( 40 | (status = 200, description = "Get todo item by id", body = [ToDoItemResponse]) 41 | ), 42 | params( 43 | ("id" = Uuid, Path, description = "Id of the to-do item") 44 | ), 45 | )] 46 | #[get("/{id}")] 47 | pub async fn get_by_id( 48 | service: Data, 49 | id: web::Path, 50 | ) -> Result { 51 | let handler = service.get_handler(); 52 | let data = handler 53 | .execute(GetToDoItemQuery::new(Some(id.into_inner()))) 54 | .await?; 55 | 56 | Ok(HttpResponse::Ok() 57 | .content_type(http::header::ContentType::json()) 58 | .body(serde_json::to_string(&data)?)) 59 | } 60 | 61 | /// Creates a new to-do item. 62 | #[utoipa::path( 63 | context_path = "/to-do-items", 64 | tag = TODO, 65 | responses( 66 | (status = 200, description = "Create todo item", body = [ToDoItemResponse]) 67 | ), 68 | request_body = CreateToDoItemRequest, 69 | )] 70 | #[post("")] 71 | pub async fn create( 72 | service: Data, 73 | item: web::Json, 74 | ) -> Result { 75 | let handler = service.create_handler(); 76 | 77 | // Fixed bug: was using &item.title for both title and note 78 | let data = handler 79 | .execute(CreateToDoItemQuery::new(&item.title, &item.note)) 80 | .await?; 81 | 82 | Ok(HttpResponse::Ok() 83 | .content_type(http::header::ContentType::json()) 84 | .body(serde_json::to_string(&data)?)) 85 | } 86 | 87 | /// Updates a to-do item by Id. 88 | #[utoipa::path( 89 | context_path = "/to-do-items", 90 | tag = TODO, 91 | responses( 92 | (status = 200, description = "Update todo item", body = [ToDoItemResponse]) 93 | ), 94 | params( 95 | ("id", description = "Id of the to-do item to update") 96 | ), 97 | request_body = UpdateToDoItemRequest, 98 | )] 99 | #[put("/{id}")] 100 | pub async fn update( 101 | service: Data, 102 | id: web::Path, 103 | item: web::Json, 104 | ) -> Result { 105 | let handler = service.update_handler(); 106 | 107 | handler 108 | .execute(UpdateToDoItemQuery::new( 109 | id.into_inner(), 110 | &item.title, 111 | &item.note, 112 | )) 113 | .await?; 114 | 115 | Ok(HttpResponse::from(HttpResponse::Ok())) 116 | } 117 | 118 | /// Deletes a to-do item by Id. 119 | #[utoipa::path( 120 | context_path = "/to-do-items", 121 | tag = TODO, 122 | responses( 123 | (status = 200, description = "Delete todo item", body = [ToDoItemResponse]) 124 | ), 125 | params( 126 | ("id", description = "Id of the to-do item to delete") 127 | ) 128 | )] 129 | #[delete("/{id}")] 130 | pub async fn delete( 131 | service: Data, 132 | id: web::Path, 133 | ) -> Result { 134 | let handler = service.delete_handler(); 135 | 136 | handler 137 | .execute(DeleteToDoItemQuery::new(id.into_inner())) 138 | .await?; 139 | 140 | Ok(HttpResponse::from(HttpResponse::Ok())) 141 | } 142 | -------------------------------------------------------------------------------- /src/starter/tests/integration.rs: -------------------------------------------------------------------------------- 1 | mod utils; 2 | 3 | #[cfg(test)] 4 | mod tests { 5 | use crate::utils::test_server; 6 | use ctor::dtor; 7 | use serial_test::serial; 8 | use std::collections::HashMap; 9 | use uuid::Uuid; 10 | 11 | use crate::{prepare_test_environment, utils::test_server::TEST_SERVER_ONCE}; 12 | 13 | const WEB_SERVER_PATH: &str = "http://localhost:8181/"; 14 | 15 | //see https://stackoverflow.com/questions/78969766/how-can-i-call-drop-in-a-tokio-static-oncelock-in-rust 16 | #[dtor] 17 | fn cleanup() { 18 | //This is crazy but it works 19 | let id = TEST_SERVER_ONCE.get().unwrap().container().id(); 20 | 21 | std::process::Command::new("docker") 22 | .arg("kill") 23 | .arg(id) 24 | .output() 25 | .expect("failed to kill container"); 26 | } 27 | 28 | #[serial] 29 | #[tokio::test] 30 | async fn start_server_and_test() { 31 | let client = prepare_test_environment!(); 32 | assert!(client.get(WEB_SERVER_PATH).send().await.is_ok()); 33 | } 34 | 35 | #[serial] 36 | #[tokio::test] 37 | async fn test_get_all() { 38 | let client = prepare_test_environment!(); 39 | 40 | // Act 41 | let response = client 42 | .get(WEB_SERVER_PATH.to_owned() + "to-do-items") 43 | .send() 44 | .await 45 | .expect("Failed to execute request."); 46 | 47 | // Assert 48 | assert!(response.status().is_success()); 49 | } 50 | 51 | #[serial] 52 | #[tokio::test] 53 | async fn test_get_by_id() { 54 | let client = prepare_test_environment!(); 55 | let mut map_create = HashMap::new(); 56 | map_create.insert("title", "title1"); 57 | map_create.insert("note", "note1"); 58 | 59 | // Act 60 | let id = client 61 | .post(WEB_SERVER_PATH.to_owned() + "to-do-items") 62 | .json(&map_create) 63 | .send() 64 | .await 65 | .expect("Failed to execute request.") 66 | .json::() 67 | .await 68 | .expect("Failed to deserialize response."); 69 | 70 | let response = client 71 | .get(WEB_SERVER_PATH.to_owned() + format!("to-do-items/{id}", id = id).as_str()) 72 | .send() 73 | .await 74 | .expect("Failed to execute request."); 75 | 76 | // Assert 77 | assert!(response.status().is_success()); 78 | } 79 | 80 | #[serial] 81 | #[tokio::test] 82 | async fn test_create() { 83 | let client = prepare_test_environment!(); 84 | let mut map = HashMap::new(); 85 | map.insert("title", "title1"); 86 | map.insert("note", "note1"); 87 | 88 | // Act 89 | let response = client 90 | .post(WEB_SERVER_PATH.to_owned() + "to-do-items") 91 | .json(&map) 92 | .send() 93 | .await 94 | .expect("Failed to execute request."); 95 | 96 | // Assert 97 | assert!(response.status().is_success()); 98 | } 99 | 100 | #[serial] 101 | #[tokio::test] 102 | async fn test_update() { 103 | let client = prepare_test_environment!(); 104 | let mut map_create = HashMap::new(); 105 | map_create.insert("title", "title1"); 106 | map_create.insert("note", "note1"); 107 | 108 | // Act 109 | let id = client 110 | .post(WEB_SERVER_PATH.to_owned() + "to-do-items") 111 | .json(&map_create) 112 | .send() 113 | .await 114 | .expect("Failed to execute request.") 115 | .json::() 116 | .await 117 | .expect("Failed to deserialize response."); 118 | 119 | let mut map_update = HashMap::new(); 120 | map_update.insert("title", String::from("title1")); 121 | map_update.insert("note", String::from("note1")); 122 | 123 | let response = client 124 | .put(WEB_SERVER_PATH.to_owned() + format!("to-do-items/{id}", id = id).as_str()) 125 | .json(&map_update) 126 | .send() 127 | .await 128 | .expect("Failed to execute request."); 129 | 130 | // Assert 131 | assert!(response.status().is_success()); 132 | } 133 | 134 | #[serial] 135 | #[tokio::test] 136 | async fn test_delete() { 137 | let client = prepare_test_environment!(); 138 | let mut map_create = HashMap::new(); 139 | map_create.insert("title", "title1"); 140 | map_create.insert("note", "note1"); 141 | 142 | // Act 143 | let id = client 144 | .post(WEB_SERVER_PATH.to_owned() + "to-do-items") 145 | .json(&map_create) 146 | .send() 147 | .await 148 | .expect("Failed to execute request.") 149 | .json::() 150 | .await 151 | .expect("Failed to deserialize response."); 152 | 153 | let response = client 154 | .delete(WEB_SERVER_PATH.to_owned() + format!("to-do-items/{id}", id = id).as_str()) 155 | .send() 156 | .await 157 | .expect("Failed to execute request."); 158 | 159 | // Assert 160 | assert!(response.status().is_success()); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rust-microservice-template 2 | 3 | ![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/nkz-soft/rust-microservice-template?style=flat-square) 4 | ![license](https://img.shields.io/github/license/nkz-soft/rust-microservice-template?style=flat-square) 5 | ![GitHub Workflow Status (with branch)](https://img.shields.io/github/actions/workflow/status/nkz-soft/rust-microservice-template/build-by-tag.yaml) 6 | 7 | Template for microservice based on Domain Driven Design principles with Rust 8 | 9 | The purpose of this project is to provide a means for building microservices with the last version of Rust that follows basic Domain Driven Design principles 10 | 11 | ### ⭐ Give a star 12 | 13 | If you're using this repository for your learning, samples or your project, please give a star. Thanks :+1: 14 | 15 | ## Table of Contents 16 | 17 | - [Installation](#installation) 18 | - [Architecture](#architecture ) 19 | - [Deployment](#deployment) 20 | - [Plan](#plan) 21 | - [Technologies - Libraries](#technologies-used) 22 | 23 | ## Usage 24 | ### Prerequisites 25 | 26 | Before you can install and configure the microservice, you will need to ensure that you have the following prerequisites installed: 27 | - Docker and Docker Compose 28 | 29 | ### Installation 30 | Once you have all the prerequisites installed, you can follow these steps to install and configure your microservice: 31 | 32 | 1. Clone the repository for your microservice using Git: 33 | ```bash 34 | git clone https://github.com/nkz-soft/rust-microservice-template.git 35 | ``` 36 | 2. Change into the directory for your microservice: 37 | ```bash 38 | cd rust-microservice-template/deployment/docker 39 | ``` 40 | 41 | 3. You can use the included Dockerfile and docker-compose.yml files to build and deploy the microservice. 42 | Simply run the following command in the root directory of your project: 43 | ```bash 44 | ./docker-compose.sh up --build -d 45 | ``` 46 | 4. Verify that the microservice is running correctly by visiting the endpoint in your web browser or using a tool like curl: 47 | ```bash 48 | curl -v http://localhost:8181/to-do-items 49 | ``` 50 | 51 | ### Configuration 52 | To configure the microservice, you will need to modify the configuration file: config.app.toml. 53 | ```toml 54 | [service] 55 | http_url = '127.0.0.1:8181' 56 | service_name = 'rust_template_service' 57 | 58 | [database] 59 | database_url = 'postgres://postgres:postgres@localhost:5432/rust_template_db' 60 | 61 | ``` 62 | You can also configure via environment variables. 63 | ```bash 64 | export MICROSERVICE__SERVICE__HTTP_URL="127.0.0.1:8181" 65 | export MICROSERVICE__SERVICE__SERVICE_NAME="rust_template_service" 66 | export MICROSERVICE__DATABASE__DATABASE_URL="postgres://postgres:postgres@localhost:5432/rust_template_db" 67 | ``` 68 | 69 | ## Architecture 70 | The microservice is divided into three layers: the Domain Layer, the Application Layer, and the Infrastructure Layer. 71 | 72 | ### Domain Layer 73 | The Domain Layer is the heart of the Domain Driven Design (DDD) approach. It contains the business logic and rules that drive the application. 74 | In Rust, the Domain Layer consists of structs, traits, enums, and functions that model the problem domain in a way that is easy to understand and maintain. 75 | 76 | ### Application Layer 77 | The Application Layer is responsible for coordinating the Domain Layer and the Infrastructure Layer. 78 | It translates user requests and external events into actions that the Domain Layer can understand, and communicates the results back to the user or external systems. 79 | 80 | ### Infrastructure Layer 81 | The Infrastructure Layer is responsible for providing the necessary infrastructure to run the application. 82 | This can include things like databases, message queues, and external APIs. 83 | 84 | ### Presentation Layer 85 | The presentation layer is responsible for handling user interactions and presenting information to users. 86 | This layer typically includes user interfaces such as web applications, desktop applications, mobile apps, or APIs. 87 | 88 | ### CQRS 89 | CQRS (Command Query Responsibility Segregation) is a pattern that separates the read and write responsibilities of an application into separate models. 90 | 91 | ## Deployment 92 | 93 | ## Plan 94 | 95 | - [x] New blank microservice solution 96 | - [x] Basic Github actions 97 | - [x] Docker compose 98 | - [x] REST API 99 | - [x] CQRS (Command Query Responsibility Segregation) 100 | - [x] PostgreSQL storage with diesel 101 | - [X] Add support for migrations 102 | - [X] CRUD Operation 103 | - [X] Integration tests 104 | - [X] Configuration 105 | - [X] Configuration file 106 | - [X] Environment variables 107 | - [x] OpenAPI documentation 108 | - [x] Advanced error handling 109 | - [x] Health checks 110 | - [x] Problem details 111 | - [ ] Coming soon :) 112 | 113 | ## Technologies used 114 | 115 | - [Rust](https://github.com/rust-lang/rust): The Rust Programming Language. 116 | - [Actix](https://github.com/actix/actix-web): Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust. 117 | - [rust-postgres](https://github.com/sfackler/rust-postgres): PostgreSQL support for Rust. 118 | - [testcontainers-rs](https://github.com/testcontainers/testcontainers-rs): Testcontainers-rs is the official Rust language fork of http://testcontainers.org. 119 | - [utoipa](https://github.com/juhaku/utoipa): Code first and compile time generated OpenAPI documentation for Rust APIs. 120 | - [diesel](https://github.com/diesel-rs/diesel): Diesel is a Rust ORM and query builder. 121 | - [diesel_migrations](https://github.com/diesel-rs/diesel_migrations): Diesel migrations for Rust. 122 | - [problem_details](https://github.com/frenetisch-applaudierend/problem-details-rs): Problem details for Rust. 123 | 124 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | ## 🏗️ **Architecture & Design Improvements** 2 | 3 | ### 1. **Memory Management & Concurrency** 4 | - **Replace `Rc<>` with `Arc<>`** in handlers - `Rc` is not thread-safe and shouldn't be used in async contexts 5 | - **Use dependency injection container** like `actix-web`'s `Data<>` more consistently 6 | - **Consider using `Box` instead of `Rc`** for better performance 7 | 8 | ### 2. **Error Handling & Resilience** 9 | - **Implement proper error mapping** between layers (don't leak `anyhow::Error` to presentation layer) 10 | - **Add custom error types** for each layer with proper conversion traits 11 | - **Implement retry mechanisms** for database operations 12 | - **Add circuit breaker pattern** for external dependencies 13 | - **Better error responses** with more detailed problem details 14 | 15 | ### 3. **CQRS Implementation** 16 | - **Separate read and write models** more clearly 17 | - **Add event sourcing capabilities** for audit trails 18 | - **Implement proper command/query separation** in the API layer 19 | - **Add command validation** before handlers execute 20 | 21 | ## 🔒 **Security Improvements** 22 | 23 | ### 4. **Authentication & Authorization** 24 | - **Add JWT-based authentication** 25 | - **Implement role-based access control (RBAC)** 26 | - **Add API key authentication** for service-to-service calls 27 | - **Input sanitization** and validation middleware 28 | - **Rate limiting** to prevent abuse 29 | 30 | ### 5. **Input Validation** 31 | - **Add validation attributes** to DTOs using `validator` crate 32 | - **Implement request validation middleware** 33 | - **Add input sanitization** for XSS prevention 34 | - **UUID validation** for path parameters 35 | 36 | ## 📊 **Observability & Monitoring** 37 | 38 | ### 6. **Logging & Tracing** 39 | - **Replace `env_logger` with structured logging** using `tracing` consistently 40 | - **Add distributed tracing** with correlation IDs 41 | - **Implement proper log levels** and structured fields 42 | - **Add request/response logging middleware** 43 | 44 | ### 7. **Metrics & Health Checks** 45 | - **Add Prometheus metrics** for performance monitoring 46 | - **Implement detailed health checks** (database, external services) 47 | - **Add application metrics** (request count, duration, errors) 48 | - **Database connection pool monitoring** 49 | 50 | ## 🗄️ **Database & Persistence** 51 | 52 | ### 8. **Transaction Management** 53 | - **Implement proper database transactions** in handlers 54 | - **Add transaction middleware** for automatic rollback on errors 55 | - **Use database connection pooling** more efficiently 56 | - **Add read replicas support** for better scalability 57 | 58 | ### 9. **Migration & Schema Management** 59 | - **Add migration rollback capabilities** 60 | - **Implement database seeding** for development/testing 61 | - **Add schema validation** in CI/CD pipeline 62 | - **Version control for database changes** 63 | 64 | ## 🚀 **Performance Optimizations** 65 | 66 | ### 10. **Caching Strategy** 67 | - **Implement Redis caching** for frequently accessed data 68 | - **Add HTTP caching headers** for GET endpoints 69 | - **Database query optimization** and indexing 70 | - **Connection pooling optimization** 71 | 72 | ### 11. **Async Improvements** 73 | - **Better async error handling** 74 | - **Optimize database query execution** 75 | - **Add connection timeout configurations** 76 | - **Implement backpressure handling** 77 | 78 | ## 🧪 **Testing Improvements** 79 | 80 | ### 12. **Test Coverage** 81 | - **Add unit tests** for all handlers and repositories 82 | - **Mock external dependencies** in tests 83 | - **Add property-based testing** for domain logic 84 | - **Performance testing** with load tests 85 | 86 | ### 13. **Test Infrastructure** 87 | - **Improve test data setup/teardown** 88 | - **Add test fixtures** and builders 89 | - **Parallel test execution** optimization 90 | - **Add contract testing** for API compatibility 91 | 92 | ## 🔧 **Code Quality & Maintenance** 93 | 94 | ### 14. **Code Issues Found** 95 | - **Bug in create endpoint**: Using `&item.title` for both title and note parameters 96 | - **Missing null checks** in optional fields handling 97 | - **Inconsistent error handling** patterns across handlers 98 | - **Repository pattern could be simplified** 99 | 100 | ### 15. **Code Organization** 101 | - **Add builder patterns** for complex objects 102 | - **Implement factory patterns** for handler creation 103 | - **Better separation of concerns** in presentation layer 104 | - **Extract constants** to configuration files 105 | 106 | ## 📝 **Documentation & Developer Experience** 107 | 108 | ### 16. **API Documentation** 109 | - **Add request/response examples** to OpenAPI specs 110 | - **Better error response documentation** 111 | - **Add API versioning strategy** 112 | - **Interactive API documentation** 113 | 114 | ### 17. **Developer Tooling** 115 | - **Add development scripts** for common tasks 116 | - **Improve Docker development environment** 117 | - **Add code formatting** with `rustfmt` 118 | - **Linting configuration** with `clippy` 119 | 120 | ## 🚀 **Deployment & DevOps** 121 | 122 | ### 18. **Container & Deployment** 123 | - **Multi-stage Docker builds** for smaller images 124 | - **Add health check endpoints** for container orchestration 125 | - **Environment-specific configurations** 126 | - **Add Kubernetes manifests** 127 | 128 | ### 19. **CI/CD Pipeline** 129 | - **Add automated testing** in CI pipeline 130 | - **Database migration validation** 131 | - **Security scanning** for dependencies 132 | - **Performance regression testing** 133 | 134 | ## 🔧 **Configuration Management** 135 | 136 | ### 20. **Enhanced Configuration** 137 | - **Environment-specific configs** (dev, staging, prod) 138 | - **Feature flags** for gradual rollouts 139 | - **Runtime configuration reloading** 140 | - **Configuration validation** at startup 141 | 142 | ## 📦 **Dependency Management** 143 | 144 | ### 21. **Dependencies** 145 | - **Update to latest stable versions** where possible 146 | - **Remove unused dependencies** 147 | - **Add security audit** for dependencies 148 | - **Consider async alternatives** for blocking operations 149 | -------------------------------------------------------------------------------- /src/starter/tests/memory_management_tests.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | use application::{ToDoItemRepository, ToDoItemService}; 4 | use domain::ToDoItem; 5 | use std::sync::{Arc, Mutex}; 6 | use std::time::Duration; 7 | use tokio::time::sleep; 8 | use uuid::Uuid; 9 | 10 | // Mock repository for testing memory patterns 11 | struct TestToDoItemRepository { 12 | items: Arc>>, 13 | operation_count: Arc>, 14 | } 15 | 16 | impl TestToDoItemRepository { 17 | fn new() -> Self { 18 | Self { 19 | items: Arc::new(Mutex::new(Vec::new())), 20 | operation_count: Arc::new(Mutex::new(0)), 21 | } 22 | } 23 | 24 | fn get_operation_count(&self) -> usize { 25 | *self.operation_count.lock().unwrap() 26 | } 27 | 28 | fn reset_count(&self) { 29 | *self.operation_count.lock().unwrap() = 0; 30 | } 31 | } 32 | 33 | #[async_trait::async_trait] 34 | impl ToDoItemRepository for TestToDoItemRepository { 35 | async fn get_all(&self) -> anyhow::Result> { 36 | *self.operation_count.lock().unwrap() += 1; 37 | sleep(Duration::from_millis(10)).await; // Simulate some work 38 | Ok(self.items.lock().unwrap().clone()) 39 | } 40 | 41 | async fn get_by_id(&self, id: Uuid) -> anyhow::Result { 42 | *self.operation_count.lock().unwrap() += 1; 43 | sleep(Duration::from_millis(10)).await; // Simulate some work 44 | self.items 45 | .lock() 46 | .unwrap() 47 | .iter() 48 | .find(|item| item.id == id) 49 | .cloned() 50 | .ok_or_else(|| anyhow::anyhow!("Item not found")) 51 | } 52 | 53 | async fn save(&self, entity: ToDoItem) -> anyhow::Result { 54 | *self.operation_count.lock().unwrap() += 1; 55 | sleep(Duration::from_millis(10)).await; // Simulate some work 56 | let id = entity.id; 57 | 58 | let mut items = self.items.lock().unwrap(); 59 | // Update existing or add new 60 | if let Some(pos) = items.iter().position(|item| item.id == id) { 61 | items[pos] = entity; 62 | } else { 63 | items.push(entity); 64 | } 65 | Ok(id) 66 | } 67 | 68 | async fn delete(&self, id: Uuid) -> anyhow::Result<()> { 69 | *self.operation_count.lock().unwrap() += 1; 70 | sleep(Duration::from_millis(10)).await; // Simulate some work 71 | let mut items = self.items.lock().unwrap(); 72 | items.retain(|item| item.id != id); 73 | Ok(()) 74 | } 75 | } 76 | 77 | #[tokio::test] 78 | async fn test_arc_memory_sharing() { 79 | let repository = Arc::new(TestToDoItemRepository::new()); 80 | let service = ToDoItemService::new(repository.clone()); 81 | 82 | // Create multiple handlers from the same service 83 | let handler1 = service.get_all_handler(); 84 | let handler2 = service.get_all_handler(); 85 | let handler3 = service.get_all_handler(); 86 | 87 | // All handlers should point to the same Arc instance 88 | assert_eq!(Arc::as_ptr(&handler1), Arc::as_ptr(&handler2)); 89 | assert_eq!(Arc::as_ptr(&handler2), Arc::as_ptr(&handler3)); 90 | 91 | // Test that they can be used concurrently 92 | let (result1, result2, result3) = 93 | tokio::join!(handler1.execute(), handler2.execute(), handler3.execute()); 94 | 95 | assert!(result1.is_ok()); 96 | assert!(result2.is_ok()); 97 | assert!(result3.is_ok()); 98 | 99 | // Repository should have been called 3 times 100 | assert_eq!(repository.get_operation_count(), 3); 101 | } 102 | 103 | #[tokio::test] 104 | async fn test_service_cloning_efficiency() { 105 | let repository = Arc::new(TestToDoItemRepository::new()); 106 | let original_service = ToDoItemService::new(repository.clone()); 107 | 108 | // Clone service multiple times 109 | let cloned_services: Vec<_> = (0..100).map(|_| original_service.clone()).collect(); 110 | 111 | // All cloned services should share the same handler instances 112 | let original_handler_ptr = Arc::as_ptr(&original_service.get_all_handler()); 113 | 114 | for cloned_service in &cloned_services { 115 | let cloned_handler_ptr = Arc::as_ptr(&cloned_service.get_all_handler()); 116 | assert_eq!(original_handler_ptr, cloned_handler_ptr); 117 | } 118 | 119 | // Test concurrent execution with cloned services 120 | let mut tasks = vec![]; 121 | for (i, service) in cloned_services.into_iter().enumerate() { 122 | let task = tokio::spawn(async move { 123 | let handler = service.get_all_handler(); 124 | let result = handler.execute().await; 125 | (i, result) 126 | }); 127 | tasks.push(task); 128 | } 129 | 130 | // Wait for all tasks and verify results 131 | for task in tasks { 132 | let (task_id, result) = task.await.unwrap(); 133 | assert!(result.is_ok(), "Task {} failed", task_id); 134 | } 135 | 136 | // All 100 operations should have been recorded 137 | assert_eq!(repository.get_operation_count(), 100); 138 | } 139 | 140 | #[tokio::test] 141 | async fn test_concurrent_handler_access() { 142 | let repository = Arc::new(TestToDoItemRepository::new()); 143 | let service = Arc::new(ToDoItemService::new(repository.clone())); 144 | 145 | // Add test data 146 | let test_item = ToDoItem::new( 147 | "Concurrent Test".to_string(), 148 | "Testing concurrency".to_string(), 149 | ); 150 | repository.items.lock().unwrap().push(test_item); 151 | 152 | // Create many concurrent tasks accessing different handlers 153 | let mut tasks = vec![]; 154 | 155 | for i in 0..50 { 156 | let service_clone = service.clone(); 157 | let task = tokio::spawn(async move { 158 | match i % 4 { 159 | 0 => { 160 | let handler = service_clone.get_all_handler(); 161 | handler.execute().await.map(|items| items.len()) 162 | } 163 | 1 => { 164 | let handler = service_clone.create_handler(); 165 | let query = application::CreateToDoItemQuery::new( 166 | &format!("Task {}", i), 167 | &format!("Note {}", i), 168 | ); 169 | handler.execute(query).await.map(|_| 1) 170 | } 171 | 2 => { 172 | let handler = service_clone.get_all_handler(); 173 | handler.execute().await.map(|items| items.len()) 174 | } 175 | _ => { 176 | let handler = service_clone.get_all_handler(); 177 | handler.execute().await.map(|items| items.len()) 178 | } 179 | } 180 | }); 181 | tasks.push(task); 182 | } 183 | 184 | // Wait for all tasks to complete 185 | let mut success_count = 0; 186 | for task in tasks { 187 | if task.await.unwrap().is_ok() { 188 | success_count += 1; 189 | } 190 | } 191 | 192 | assert_eq!(success_count, 50); 193 | assert!(repository.get_operation_count() > 0); 194 | } 195 | 196 | #[tokio::test] 197 | async fn test_memory_leak_prevention() { 198 | let repository = Arc::new(TestToDoItemRepository::new()); 199 | 200 | // Create many services and let them go out of scope 201 | for _ in 0..1000 { 202 | let service = ToDoItemService::new(repository.clone()); 203 | let handler = service.get_all_handler(); 204 | 205 | // Use the handler briefly 206 | let _ = handler.execute().await; 207 | 208 | // Service and handler should be dropped here 209 | } 210 | 211 | // Repository should still be accessible and functional 212 | assert_eq!(Arc::strong_count(&repository), 1); 213 | assert_eq!(repository.get_operation_count(), 1000); 214 | } 215 | 216 | #[tokio::test] 217 | async fn test_boxed_vs_arc_performance() { 218 | let repository = Arc::new(TestToDoItemRepository::new()); 219 | 220 | // Test Arc-based service 221 | repository.reset_count(); 222 | let arc_service = ToDoItemService::new(repository.clone()); 223 | 224 | let arc_start = std::time::Instant::now(); 225 | for _ in 0..100 { 226 | let handler = arc_service.get_all_handler(); 227 | let _ = handler.execute().await; 228 | } 229 | let arc_duration = arc_start.elapsed(); 230 | let arc_operations = repository.get_operation_count(); 231 | 232 | // Test Box-based service 233 | repository.reset_count(); 234 | let box_service = application::ToDoItemServiceBoxed::new(repository.clone()); 235 | 236 | let box_start = std::time::Instant::now(); 237 | for _ in 0..100 { 238 | let handler = box_service.create_get_all_handler(); 239 | let _ = handler.execute().await; 240 | } 241 | let box_duration = box_start.elapsed(); 242 | let box_operations = repository.get_operation_count(); 243 | 244 | // Both should complete all operations 245 | assert_eq!(arc_operations, 100); 246 | assert_eq!(box_operations, 100); 247 | 248 | // Arc-based should generally be faster due to shared instances 249 | // (though this test might be too small to see significant difference) 250 | println!( 251 | "Arc duration: {:?}, Box duration: {:?}", 252 | arc_duration, box_duration 253 | ); 254 | } 255 | 256 | #[tokio::test] 257 | async fn test_service_send_sync_compliance() { 258 | let repository = Arc::new(TestToDoItemRepository::new()); 259 | let service = ToDoItemService::new(repository); 260 | 261 | // Test that service can be sent across thread boundaries 262 | let service_arc = Arc::new(service); 263 | 264 | let handle = tokio::spawn(async move { 265 | let handler = service_arc.get_all_handler(); 266 | handler.execute().await 267 | }); 268 | 269 | let result = handle.await.unwrap(); 270 | assert!(result.is_ok()); 271 | } 272 | 273 | // Helper function to verify thread safety at compile time 274 | fn _verify_send_sync(_: T) {} 275 | 276 | #[test] 277 | fn test_compile_time_send_sync() { 278 | let repository = Arc::new(TestToDoItemRepository::new()); 279 | let service = ToDoItemService::new(repository.clone()); 280 | 281 | // These should compile without errors, proving Send + Sync compliance 282 | _verify_send_sync(service.clone()); 283 | _verify_send_sync(service.get_handler()); 284 | _verify_send_sync(repository); 285 | } 286 | } 287 | -------------------------------------------------------------------------------- /src/application/src/services.rs: -------------------------------------------------------------------------------- 1 | use crate::handlers::*; 2 | use crate::repositories::ToDoItemRepository; 3 | use std::sync::Arc; 4 | 5 | /// Service container that manages all query handlers with proper dependency injection 6 | #[derive(Clone)] 7 | pub struct ToDoItemService { 8 | get_handler: Arc, 9 | get_all_handler: Arc, 10 | create_handler: Arc, 11 | update_handler: Arc, 12 | delete_handler: Arc, 13 | } 14 | 15 | impl ToDoItemService { 16 | pub fn new(repository: Arc) -> Self { 17 | Self { 18 | get_handler: Arc::new(GetToDoItemQueryHandler::new(repository.clone())), 19 | get_all_handler: Arc::new(GetAllToDoItemQueryHandler::new(repository.clone())), 20 | create_handler: Arc::new(CreateToDoItemQueryHandler::new(repository.clone())), 21 | update_handler: Arc::new(UpdateToDoItemQueryHandler::new(repository.clone())), 22 | delete_handler: Arc::new(DeleteToDoItemQueryHandler::new(repository)), 23 | } 24 | } 25 | 26 | pub fn get_handler(&self) -> Arc { 27 | self.get_handler.clone() 28 | } 29 | 30 | pub fn get_all_handler(&self) -> Arc { 31 | self.get_all_handler.clone() 32 | } 33 | 34 | pub fn create_handler(&self) -> Arc { 35 | self.create_handler.clone() 36 | } 37 | 38 | pub fn update_handler(&self) -> Arc { 39 | self.update_handler.clone() 40 | } 41 | 42 | pub fn delete_handler(&self) -> Arc { 43 | self.delete_handler.clone() 44 | } 45 | } 46 | 47 | // Alternative approach using Box for handlers when cloning is not needed 48 | pub struct ToDoItemServiceBoxed { 49 | repository: Arc, 50 | } 51 | 52 | impl ToDoItemServiceBoxed { 53 | pub fn new(repository: Arc) -> Self { 54 | Self { repository } 55 | } 56 | 57 | pub fn create_get_handler(&self) -> Box { 58 | Box::new(GetToDoItemQueryHandler::new(self.repository.clone())) 59 | } 60 | 61 | pub fn create_get_all_handler(&self) -> Box { 62 | Box::new(GetAllToDoItemQueryHandler::new(self.repository.clone())) 63 | } 64 | 65 | pub fn create_create_handler(&self) -> Box { 66 | Box::new(CreateToDoItemQueryHandler::new(self.repository.clone())) 67 | } 68 | 69 | pub fn create_update_handler(&self) -> Box { 70 | Box::new(UpdateToDoItemQueryHandler::new(self.repository.clone())) 71 | } 72 | 73 | pub fn create_delete_handler(&self) -> Box { 74 | Box::new(DeleteToDoItemQueryHandler::new(self.repository.clone())) 75 | } 76 | } 77 | 78 | #[cfg(test)] 79 | mod tests { 80 | use super::*; 81 | use async_trait::async_trait; 82 | use domain::ToDoItem; 83 | use std::sync::{Arc, Mutex}; 84 | use tokio::task; 85 | use uuid::Uuid; 86 | 87 | // Mock repository for testing 88 | struct MockToDoItemRepository { 89 | items: Arc>>, 90 | call_count: Arc>, 91 | } 92 | 93 | impl MockToDoItemRepository { 94 | fn new() -> Self { 95 | Self { 96 | items: Arc::new(Mutex::new(Vec::new())), 97 | call_count: Arc::new(Mutex::new(0)), 98 | } 99 | } 100 | 101 | fn get_call_count(&self) -> usize { 102 | *self.call_count.lock().unwrap() 103 | } 104 | 105 | fn add_item(&self, item: ToDoItem) { 106 | self.items.lock().unwrap().push(item); 107 | } 108 | } 109 | 110 | #[async_trait] 111 | impl ToDoItemRepository for MockToDoItemRepository { 112 | async fn get_all(&self) -> anyhow::Result> { 113 | *self.call_count.lock().unwrap() += 1; 114 | Ok(self.items.lock().unwrap().clone()) 115 | } 116 | 117 | async fn get_by_id(&self, id: Uuid) -> anyhow::Result { 118 | *self.call_count.lock().unwrap() += 1; 119 | self.items 120 | .lock() 121 | .unwrap() 122 | .iter() 123 | .find(|item| item.id == id) 124 | .cloned() 125 | .ok_or_else(|| anyhow::anyhow!("Item not found")) 126 | } 127 | 128 | async fn save(&self, entity: ToDoItem) -> anyhow::Result { 129 | *self.call_count.lock().unwrap() += 1; 130 | let id = entity.id; 131 | self.items.lock().unwrap().push(entity); 132 | Ok(id) 133 | } 134 | 135 | async fn delete(&self, id: Uuid) -> anyhow::Result<()> { 136 | *self.call_count.lock().unwrap() += 1; 137 | let mut items = self.items.lock().unwrap(); 138 | items.retain(|item| item.id != id); 139 | Ok(()) 140 | } 141 | } 142 | 143 | #[tokio::test] 144 | async fn test_service_creation_with_arc() { 145 | let repository = Arc::new(MockToDoItemRepository::new()); 146 | let service = ToDoItemService::new(repository); 147 | 148 | // Test that handlers are created successfully - handlers are Arc so they don't have is_ok() 149 | let get_handler = service.get_handler(); 150 | let get_all_handler = service.get_all_handler(); 151 | let create_handler = service.create_handler(); 152 | let update_handler = service.update_handler(); 153 | let delete_handler = service.delete_handler(); 154 | 155 | // Verify that we can get handlers without panicking 156 | assert!(Arc::strong_count(&get_handler) >= 1); 157 | assert!(Arc::strong_count(&get_all_handler) >= 1); 158 | assert!(Arc::strong_count(&create_handler) >= 1); 159 | assert!(Arc::strong_count(&update_handler) >= 1); 160 | assert!(Arc::strong_count(&delete_handler) >= 1); 161 | } 162 | 163 | #[tokio::test] 164 | async fn test_service_cloning() { 165 | let repository = Arc::new(MockToDoItemRepository::new()); 166 | let service = ToDoItemService::new(repository); 167 | 168 | // Test that service can be cloned (important for actix-web Data<>) 169 | let cloned_service = service.clone(); 170 | 171 | // Both services should work independently 172 | let handler1 = service.get_all_handler(); 173 | let handler2 = cloned_service.get_all_handler(); 174 | 175 | let result1 = handler1.execute().await; 176 | let result2 = handler2.execute().await; 177 | 178 | assert!(result1.is_ok()); 179 | assert!(result2.is_ok()); 180 | } 181 | 182 | #[tokio::test] 183 | async fn test_concurrent_access() { 184 | let repository = Arc::new(MockToDoItemRepository::new()); 185 | let service = Arc::new(ToDoItemService::new(repository.clone())); 186 | 187 | // Add some test data 188 | repository.add_item(ToDoItem::new("Test 1".to_string(), "Note 1".to_string())); 189 | repository.add_item(ToDoItem::new("Test 2".to_string(), "Note 2".to_string())); 190 | 191 | // Test concurrent access with multiple tasks 192 | let mut handles = vec![]; 193 | 194 | for i in 0..10 { 195 | let service_clone = service.clone(); 196 | let handle = task::spawn(async move { 197 | let handler = service_clone.get_all_handler(); 198 | let result = handler.execute().await; 199 | (i, result) 200 | }); 201 | handles.push(handle); 202 | } 203 | 204 | // Wait for all tasks to complete 205 | for handle in handles { 206 | let (task_id, result) = handle.await.unwrap(); 207 | assert!(result.is_ok(), "Task {} failed", task_id); 208 | assert_eq!(result.unwrap().len(), 2); 209 | } 210 | 211 | // Verify that repository was called 10 times 212 | assert_eq!(repository.get_call_count(), 10); 213 | } 214 | 215 | #[tokio::test] 216 | async fn test_boxed_service_creation() { 217 | let repository = Arc::new(MockToDoItemRepository::new()); 218 | let service = ToDoItemServiceBoxed::new(repository); 219 | 220 | // Test that boxed handlers are created successfully 221 | let get_handler = service.create_get_handler(); 222 | let get_all_handler = service.create_get_all_handler(); 223 | let create_handler = service.create_create_handler(); 224 | let update_handler = service.create_update_handler(); 225 | let delete_handler = service.create_delete_handler(); 226 | 227 | // Verify handlers are boxed correctly 228 | assert_eq!( 229 | std::mem::size_of_val(&*get_handler), 230 | std::mem::size_of::() 231 | ); 232 | assert_eq!( 233 | std::mem::size_of_val(&*get_all_handler), 234 | std::mem::size_of::() 235 | ); 236 | assert_eq!( 237 | std::mem::size_of_val(&*create_handler), 238 | std::mem::size_of::() 239 | ); 240 | assert_eq!( 241 | std::mem::size_of_val(&*update_handler), 242 | std::mem::size_of::() 243 | ); 244 | assert_eq!( 245 | std::mem::size_of_val(&*delete_handler), 246 | std::mem::size_of::() 247 | ); 248 | } 249 | 250 | #[tokio::test] 251 | async fn test_memory_efficiency_arc_vs_box() { 252 | let repository = Arc::new(MockToDoItemRepository::new()); 253 | 254 | // Test Arc-based service 255 | let arc_service = ToDoItemService::new(repository.clone()); 256 | let arc_handler1 = arc_service.get_all_handler(); 257 | let arc_handler2 = arc_service.get_all_handler(); 258 | 259 | // Test Box-based service 260 | let box_service = ToDoItemServiceBoxed::new(repository); 261 | let box_handler1 = box_service.create_get_all_handler(); 262 | let box_handler2 = box_service.create_get_all_handler(); 263 | 264 | // Arc handlers should point to the same memory location (shared) 265 | assert_eq!(Arc::as_ptr(&arc_handler1), Arc::as_ptr(&arc_handler2)); 266 | 267 | // Box handlers should be different instances 268 | assert_ne!(&*box_handler1 as *const _, &*box_handler2 as *const _); 269 | } 270 | 271 | #[tokio::test] 272 | async fn test_send_sync_bounds() { 273 | let repository = Arc::new(MockToDoItemRepository::new()); 274 | let service = Arc::new(ToDoItemService::new(repository)); 275 | 276 | // Test that service can be sent across threads 277 | let handle = task::spawn(async move { 278 | let handler = service.get_all_handler(); 279 | handler.execute().await 280 | }); 281 | 282 | let result = handle.await.unwrap(); 283 | assert!(result.is_ok()); 284 | } 285 | 286 | #[test] 287 | fn test_handler_implementation() { 288 | let repository = Arc::new(MockToDoItemRepository::new()); 289 | let service = ToDoItemService::new(repository); 290 | 291 | // Verify that handlers are properly wrapped in Arc 292 | let handler = service.get_handler(); 293 | // Just verify we can get the handler without panicking 294 | assert!(Arc::strong_count(&handler) >= 1); 295 | } 296 | } 297 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "actix-codec" 7 | version = "0.5.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" 10 | dependencies = [ 11 | "bitflags 2.6.0", 12 | "bytes", 13 | "futures-core", 14 | "futures-sink", 15 | "memchr", 16 | "pin-project-lite", 17 | "tokio", 18 | "tokio-util", 19 | "tracing", 20 | ] 21 | 22 | [[package]] 23 | name = "actix-http" 24 | version = "3.11.0" 25 | source = "registry+https://github.com/rust-lang/crates.io-index" 26 | checksum = "44dfe5c9e0004c623edc65391dfd51daa201e7e30ebd9c9bedf873048ec32bc2" 27 | dependencies = [ 28 | "actix-codec", 29 | "actix-rt", 30 | "actix-service", 31 | "actix-utils", 32 | "base64 0.22.1", 33 | "bitflags 2.6.0", 34 | "brotli", 35 | "bytes", 36 | "bytestring", 37 | "derive_more", 38 | "encoding_rs", 39 | "flate2", 40 | "foldhash", 41 | "futures-core", 42 | "h2 0.3.26", 43 | "http 0.2.12", 44 | "httparse", 45 | "httpdate", 46 | "itoa", 47 | "language-tags", 48 | "local-channel", 49 | "mime", 50 | "percent-encoding", 51 | "pin-project-lite", 52 | "rand", 53 | "sha1", 54 | "smallvec", 55 | "tokio", 56 | "tokio-util", 57 | "tracing", 58 | "zstd", 59 | ] 60 | 61 | [[package]] 62 | name = "actix-macros" 63 | version = "0.2.4" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" 66 | dependencies = [ 67 | "quote", 68 | "syn", 69 | ] 70 | 71 | [[package]] 72 | name = "actix-router" 73 | version = "0.5.3" 74 | source = "registry+https://github.com/rust-lang/crates.io-index" 75 | checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" 76 | dependencies = [ 77 | "bytestring", 78 | "cfg-if", 79 | "http 0.2.12", 80 | "regex", 81 | "regex-lite", 82 | "serde", 83 | "tracing", 84 | ] 85 | 86 | [[package]] 87 | name = "actix-rt" 88 | version = "2.10.0" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208" 91 | dependencies = [ 92 | "futures-core", 93 | "tokio", 94 | ] 95 | 96 | [[package]] 97 | name = "actix-server" 98 | version = "2.6.0" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | checksum = "a65064ea4a457eaf07f2fba30b4c695bf43b721790e9530d26cb6f9019ff7502" 101 | dependencies = [ 102 | "actix-rt", 103 | "actix-service", 104 | "actix-utils", 105 | "futures-core", 106 | "futures-util", 107 | "mio", 108 | "socket2 0.5.10", 109 | "tokio", 110 | "tracing", 111 | ] 112 | 113 | [[package]] 114 | name = "actix-service" 115 | version = "2.0.2" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" 118 | dependencies = [ 119 | "futures-core", 120 | "paste", 121 | "pin-project-lite", 122 | ] 123 | 124 | [[package]] 125 | name = "actix-utils" 126 | version = "3.0.1" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" 129 | dependencies = [ 130 | "local-waker", 131 | "pin-project-lite", 132 | ] 133 | 134 | [[package]] 135 | name = "actix-web" 136 | version = "4.11.0" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | checksum = "a597b77b5c6d6a1e1097fddde329a83665e25c5437c696a3a9a4aa514a614dea" 139 | dependencies = [ 140 | "actix-codec", 141 | "actix-http", 142 | "actix-macros", 143 | "actix-router", 144 | "actix-rt", 145 | "actix-server", 146 | "actix-service", 147 | "actix-utils", 148 | "actix-web-codegen", 149 | "bytes", 150 | "bytestring", 151 | "cfg-if", 152 | "cookie", 153 | "derive_more", 154 | "encoding_rs", 155 | "foldhash", 156 | "futures-core", 157 | "futures-util", 158 | "impl-more", 159 | "itoa", 160 | "language-tags", 161 | "log", 162 | "mime", 163 | "once_cell", 164 | "pin-project-lite", 165 | "regex", 166 | "regex-lite", 167 | "serde", 168 | "serde_json", 169 | "serde_urlencoded", 170 | "smallvec", 171 | "socket2 0.5.10", 172 | "time", 173 | "tracing", 174 | "url", 175 | ] 176 | 177 | [[package]] 178 | name = "actix-web-codegen" 179 | version = "4.3.0" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | checksum = "f591380e2e68490b5dfaf1dd1aa0ebe78d84ba7067078512b4ea6e4492d622b8" 182 | dependencies = [ 183 | "actix-router", 184 | "proc-macro2", 185 | "quote", 186 | "syn", 187 | ] 188 | 189 | [[package]] 190 | name = "addr2line" 191 | version = "0.21.0" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" 194 | dependencies = [ 195 | "gimli", 196 | ] 197 | 198 | [[package]] 199 | name = "adler" 200 | version = "1.0.2" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 203 | 204 | [[package]] 205 | name = "adler2" 206 | version = "2.0.0" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 209 | 210 | [[package]] 211 | name = "aho-corasick" 212 | version = "1.1.3" 213 | source = "registry+https://github.com/rust-lang/crates.io-index" 214 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 215 | dependencies = [ 216 | "memchr", 217 | ] 218 | 219 | [[package]] 220 | name = "alloc-no-stdlib" 221 | version = "2.0.4" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" 224 | 225 | [[package]] 226 | name = "alloc-stdlib" 227 | version = "0.2.2" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" 230 | dependencies = [ 231 | "alloc-no-stdlib", 232 | ] 233 | 234 | [[package]] 235 | name = "android-tzdata" 236 | version = "0.1.1" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" 239 | 240 | [[package]] 241 | name = "android_system_properties" 242 | version = "0.1.5" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 245 | dependencies = [ 246 | "libc", 247 | ] 248 | 249 | [[package]] 250 | name = "anstream" 251 | version = "0.6.18" 252 | source = "registry+https://github.com/rust-lang/crates.io-index" 253 | checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" 254 | dependencies = [ 255 | "anstyle", 256 | "anstyle-parse", 257 | "anstyle-query", 258 | "anstyle-wincon", 259 | "colorchoice", 260 | "is_terminal_polyfill", 261 | "utf8parse", 262 | ] 263 | 264 | [[package]] 265 | name = "anstyle" 266 | version = "1.0.10" 267 | source = "registry+https://github.com/rust-lang/crates.io-index" 268 | checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" 269 | 270 | [[package]] 271 | name = "anstyle-parse" 272 | version = "0.2.6" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" 275 | dependencies = [ 276 | "utf8parse", 277 | ] 278 | 279 | [[package]] 280 | name = "anstyle-query" 281 | version = "1.1.2" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" 284 | dependencies = [ 285 | "windows-sys 0.59.0", 286 | ] 287 | 288 | [[package]] 289 | name = "anstyle-wincon" 290 | version = "3.0.6" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" 293 | dependencies = [ 294 | "anstyle", 295 | "windows-sys 0.59.0", 296 | ] 297 | 298 | [[package]] 299 | name = "anyhow" 300 | version = "1.0.98" 301 | source = "registry+https://github.com/rust-lang/crates.io-index" 302 | checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" 303 | 304 | [[package]] 305 | name = "application" 306 | version = "0.1.2" 307 | dependencies = [ 308 | "anyhow", 309 | "async-trait", 310 | "config", 311 | "domain", 312 | "readonly", 313 | "serde", 314 | "serial_test", 315 | "tokio", 316 | "tokio-postgres", 317 | "uuid", 318 | ] 319 | 320 | [[package]] 321 | name = "arbitrary" 322 | version = "1.4.1" 323 | source = "registry+https://github.com/rust-lang/crates.io-index" 324 | checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" 325 | dependencies = [ 326 | "derive_arbitrary", 327 | ] 328 | 329 | [[package]] 330 | name = "arraydeque" 331 | version = "0.5.1" 332 | source = "registry+https://github.com/rust-lang/crates.io-index" 333 | checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" 334 | 335 | [[package]] 336 | name = "async-trait" 337 | version = "0.1.89" 338 | source = "registry+https://github.com/rust-lang/crates.io-index" 339 | checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" 340 | dependencies = [ 341 | "proc-macro2", 342 | "quote", 343 | "syn", 344 | ] 345 | 346 | [[package]] 347 | name = "atomic-waker" 348 | version = "1.1.2" 349 | source = "registry+https://github.com/rust-lang/crates.io-index" 350 | checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" 351 | 352 | [[package]] 353 | name = "autocfg" 354 | version = "1.4.0" 355 | source = "registry+https://github.com/rust-lang/crates.io-index" 356 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 357 | 358 | [[package]] 359 | name = "backtrace" 360 | version = "0.3.71" 361 | source = "registry+https://github.com/rust-lang/crates.io-index" 362 | checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" 363 | dependencies = [ 364 | "addr2line", 365 | "cc", 366 | "cfg-if", 367 | "libc", 368 | "miniz_oxide 0.7.4", 369 | "object", 370 | "rustc-demangle", 371 | ] 372 | 373 | [[package]] 374 | name = "base64" 375 | version = "0.21.7" 376 | source = "registry+https://github.com/rust-lang/crates.io-index" 377 | checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" 378 | 379 | [[package]] 380 | name = "base64" 381 | version = "0.22.1" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 384 | 385 | [[package]] 386 | name = "bitflags" 387 | version = "1.3.2" 388 | source = "registry+https://github.com/rust-lang/crates.io-index" 389 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 390 | 391 | [[package]] 392 | name = "bitflags" 393 | version = "2.6.0" 394 | source = "registry+https://github.com/rust-lang/crates.io-index" 395 | checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" 396 | dependencies = [ 397 | "serde", 398 | ] 399 | 400 | [[package]] 401 | name = "block-buffer" 402 | version = "0.10.4" 403 | source = "registry+https://github.com/rust-lang/crates.io-index" 404 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 405 | dependencies = [ 406 | "generic-array", 407 | ] 408 | 409 | [[package]] 410 | name = "bollard" 411 | version = "0.18.1" 412 | source = "registry+https://github.com/rust-lang/crates.io-index" 413 | checksum = "97ccca1260af6a459d75994ad5acc1651bcabcbdbc41467cc9786519ab854c30" 414 | dependencies = [ 415 | "base64 0.22.1", 416 | "bollard-stubs", 417 | "bytes", 418 | "futures-core", 419 | "futures-util", 420 | "hex", 421 | "home", 422 | "http 1.3.1", 423 | "http-body-util", 424 | "hyper", 425 | "hyper-named-pipe", 426 | "hyper-rustls", 427 | "hyper-util", 428 | "hyperlocal", 429 | "log", 430 | "pin-project-lite", 431 | "rustls", 432 | "rustls-native-certs", 433 | "rustls-pemfile", 434 | "rustls-pki-types", 435 | "serde", 436 | "serde_derive", 437 | "serde_json", 438 | "serde_repr", 439 | "serde_urlencoded", 440 | "thiserror 2.0.12", 441 | "tokio", 442 | "tokio-util", 443 | "tower-service", 444 | "url", 445 | "winapi", 446 | ] 447 | 448 | [[package]] 449 | name = "bollard-stubs" 450 | version = "1.47.1-rc.27.3.1" 451 | source = "registry+https://github.com/rust-lang/crates.io-index" 452 | checksum = "3f179cfbddb6e77a5472703d4b30436bff32929c0aa8a9008ecf23d1d3cdd0da" 453 | dependencies = [ 454 | "serde", 455 | "serde_repr", 456 | "serde_with", 457 | ] 458 | 459 | [[package]] 460 | name = "brotli" 461 | version = "8.0.1" 462 | source = "registry+https://github.com/rust-lang/crates.io-index" 463 | checksum = "9991eea70ea4f293524138648e41ee89b0b2b12ddef3b255effa43c8056e0e0d" 464 | dependencies = [ 465 | "alloc-no-stdlib", 466 | "alloc-stdlib", 467 | "brotli-decompressor", 468 | ] 469 | 470 | [[package]] 471 | name = "brotli-decompressor" 472 | version = "5.0.0" 473 | source = "registry+https://github.com/rust-lang/crates.io-index" 474 | checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" 475 | dependencies = [ 476 | "alloc-no-stdlib", 477 | "alloc-stdlib", 478 | ] 479 | 480 | [[package]] 481 | name = "bumpalo" 482 | version = "3.16.0" 483 | source = "registry+https://github.com/rust-lang/crates.io-index" 484 | checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" 485 | 486 | [[package]] 487 | name = "byteorder" 488 | version = "1.5.0" 489 | source = "registry+https://github.com/rust-lang/crates.io-index" 490 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 491 | 492 | [[package]] 493 | name = "bytes" 494 | version = "1.8.0" 495 | source = "registry+https://github.com/rust-lang/crates.io-index" 496 | checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" 497 | 498 | [[package]] 499 | name = "bytestring" 500 | version = "1.3.1" 501 | source = "registry+https://github.com/rust-lang/crates.io-index" 502 | checksum = "74d80203ea6b29df88012294f62733de21cfeab47f17b41af3a38bc30a03ee72" 503 | dependencies = [ 504 | "bytes", 505 | ] 506 | 507 | [[package]] 508 | name = "cc" 509 | version = "1.1.34" 510 | source = "registry+https://github.com/rust-lang/crates.io-index" 511 | checksum = "67b9470d453346108f93a59222a9a1a5724db32d0a4727b7ab7ace4b4d822dc9" 512 | dependencies = [ 513 | "jobserver", 514 | "libc", 515 | "shlex", 516 | ] 517 | 518 | [[package]] 519 | name = "cfg-if" 520 | version = "1.0.0" 521 | source = "registry+https://github.com/rust-lang/crates.io-index" 522 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 523 | 524 | [[package]] 525 | name = "chrono" 526 | version = "0.4.38" 527 | source = "registry+https://github.com/rust-lang/crates.io-index" 528 | checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" 529 | dependencies = [ 530 | "android-tzdata", 531 | "iana-time-zone", 532 | "num-traits", 533 | "serde", 534 | "windows-targets 0.52.6", 535 | ] 536 | 537 | [[package]] 538 | name = "colorchoice" 539 | version = "1.0.3" 540 | source = "registry+https://github.com/rust-lang/crates.io-index" 541 | checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" 542 | 543 | [[package]] 544 | name = "config" 545 | version = "0.15.16" 546 | source = "registry+https://github.com/rust-lang/crates.io-index" 547 | checksum = "cef036f0ecf99baef11555578630e2cca559909b4c50822dbba828c252d21c49" 548 | dependencies = [ 549 | "async-trait", 550 | "convert_case", 551 | "json5", 552 | "pathdiff", 553 | "ron", 554 | "rust-ini", 555 | "serde-untagged", 556 | "serde_core", 557 | "serde_json", 558 | "toml 0.9.7", 559 | "winnow 0.7.13", 560 | "yaml-rust2", 561 | ] 562 | 563 | [[package]] 564 | name = "const-random" 565 | version = "0.1.18" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" 568 | dependencies = [ 569 | "const-random-macro", 570 | ] 571 | 572 | [[package]] 573 | name = "const-random-macro" 574 | version = "0.1.16" 575 | source = "registry+https://github.com/rust-lang/crates.io-index" 576 | checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" 577 | dependencies = [ 578 | "getrandom 0.2.15", 579 | "once_cell", 580 | "tiny-keccak", 581 | ] 582 | 583 | [[package]] 584 | name = "convert_case" 585 | version = "0.6.0" 586 | source = "registry+https://github.com/rust-lang/crates.io-index" 587 | checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" 588 | dependencies = [ 589 | "unicode-segmentation", 590 | ] 591 | 592 | [[package]] 593 | name = "cookie" 594 | version = "0.16.2" 595 | source = "registry+https://github.com/rust-lang/crates.io-index" 596 | checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" 597 | dependencies = [ 598 | "percent-encoding", 599 | "time", 600 | "version_check", 601 | ] 602 | 603 | [[package]] 604 | name = "core-foundation" 605 | version = "0.9.4" 606 | source = "registry+https://github.com/rust-lang/crates.io-index" 607 | checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" 608 | dependencies = [ 609 | "core-foundation-sys", 610 | "libc", 611 | ] 612 | 613 | [[package]] 614 | name = "core-foundation" 615 | version = "0.10.0" 616 | source = "registry+https://github.com/rust-lang/crates.io-index" 617 | checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" 618 | dependencies = [ 619 | "core-foundation-sys", 620 | "libc", 621 | ] 622 | 623 | [[package]] 624 | name = "core-foundation-sys" 625 | version = "0.8.7" 626 | source = "registry+https://github.com/rust-lang/crates.io-index" 627 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 628 | 629 | [[package]] 630 | name = "cpufeatures" 631 | version = "0.2.14" 632 | source = "registry+https://github.com/rust-lang/crates.io-index" 633 | checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" 634 | dependencies = [ 635 | "libc", 636 | ] 637 | 638 | [[package]] 639 | name = "crc32fast" 640 | version = "1.4.2" 641 | source = "registry+https://github.com/rust-lang/crates.io-index" 642 | checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" 643 | dependencies = [ 644 | "cfg-if", 645 | ] 646 | 647 | [[package]] 648 | name = "crossbeam-utils" 649 | version = "0.8.20" 650 | source = "registry+https://github.com/rust-lang/crates.io-index" 651 | checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" 652 | 653 | [[package]] 654 | name = "crunchy" 655 | version = "0.2.2" 656 | source = "registry+https://github.com/rust-lang/crates.io-index" 657 | checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" 658 | 659 | [[package]] 660 | name = "crypto-common" 661 | version = "0.1.6" 662 | source = "registry+https://github.com/rust-lang/crates.io-index" 663 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 664 | dependencies = [ 665 | "generic-array", 666 | "typenum", 667 | ] 668 | 669 | [[package]] 670 | name = "ctor" 671 | version = "0.2.9" 672 | source = "registry+https://github.com/rust-lang/crates.io-index" 673 | checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" 674 | dependencies = [ 675 | "quote", 676 | "syn", 677 | ] 678 | 679 | [[package]] 680 | name = "darling" 681 | version = "0.20.10" 682 | source = "registry+https://github.com/rust-lang/crates.io-index" 683 | checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" 684 | dependencies = [ 685 | "darling_core", 686 | "darling_macro", 687 | ] 688 | 689 | [[package]] 690 | name = "darling_core" 691 | version = "0.20.10" 692 | source = "registry+https://github.com/rust-lang/crates.io-index" 693 | checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" 694 | dependencies = [ 695 | "fnv", 696 | "ident_case", 697 | "proc-macro2", 698 | "quote", 699 | "strsim", 700 | "syn", 701 | ] 702 | 703 | [[package]] 704 | name = "darling_macro" 705 | version = "0.20.10" 706 | source = "registry+https://github.com/rust-lang/crates.io-index" 707 | checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" 708 | dependencies = [ 709 | "darling_core", 710 | "quote", 711 | "syn", 712 | ] 713 | 714 | [[package]] 715 | name = "deranged" 716 | version = "0.3.11" 717 | source = "registry+https://github.com/rust-lang/crates.io-index" 718 | checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" 719 | dependencies = [ 720 | "powerfmt", 721 | "serde", 722 | ] 723 | 724 | [[package]] 725 | name = "derive_arbitrary" 726 | version = "1.4.1" 727 | source = "registry+https://github.com/rust-lang/crates.io-index" 728 | checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" 729 | dependencies = [ 730 | "proc-macro2", 731 | "quote", 732 | "syn", 733 | ] 734 | 735 | [[package]] 736 | name = "derive_more" 737 | version = "2.0.1" 738 | source = "registry+https://github.com/rust-lang/crates.io-index" 739 | checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" 740 | dependencies = [ 741 | "derive_more-impl", 742 | ] 743 | 744 | [[package]] 745 | name = "derive_more-impl" 746 | version = "2.0.1" 747 | source = "registry+https://github.com/rust-lang/crates.io-index" 748 | checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" 749 | dependencies = [ 750 | "proc-macro2", 751 | "quote", 752 | "syn", 753 | "unicode-xid", 754 | ] 755 | 756 | [[package]] 757 | name = "diesel" 758 | version = "2.2.12" 759 | source = "registry+https://github.com/rust-lang/crates.io-index" 760 | checksum = "229850a212cd9b84d4f0290ad9d294afc0ae70fccaa8949dbe8b43ffafa1e20c" 761 | dependencies = [ 762 | "bitflags 2.6.0", 763 | "byteorder", 764 | "diesel_derives", 765 | "itoa", 766 | "pq-sys", 767 | "r2d2", 768 | "uuid", 769 | ] 770 | 771 | [[package]] 772 | name = "diesel_derives" 773 | version = "2.2.3" 774 | source = "registry+https://github.com/rust-lang/crates.io-index" 775 | checksum = "e7f2c3de51e2ba6bf2a648285696137aaf0f5f487bcbea93972fe8a364e131a4" 776 | dependencies = [ 777 | "diesel_table_macro_syntax", 778 | "dsl_auto_type", 779 | "proc-macro2", 780 | "quote", 781 | "syn", 782 | ] 783 | 784 | [[package]] 785 | name = "diesel_migrations" 786 | version = "2.2.0" 787 | source = "registry+https://github.com/rust-lang/crates.io-index" 788 | checksum = "8a73ce704bad4231f001bff3314d91dce4aba0770cee8b233991859abc15c1f6" 789 | dependencies = [ 790 | "diesel", 791 | "migrations_internals", 792 | "migrations_macros", 793 | ] 794 | 795 | [[package]] 796 | name = "diesel_table_macro_syntax" 797 | version = "0.2.0" 798 | source = "registry+https://github.com/rust-lang/crates.io-index" 799 | checksum = "209c735641a413bc68c4923a9d6ad4bcb3ca306b794edaa7eb0b3228a99ffb25" 800 | dependencies = [ 801 | "syn", 802 | ] 803 | 804 | [[package]] 805 | name = "digest" 806 | version = "0.10.7" 807 | source = "registry+https://github.com/rust-lang/crates.io-index" 808 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 809 | dependencies = [ 810 | "block-buffer", 811 | "crypto-common", 812 | "subtle", 813 | ] 814 | 815 | [[package]] 816 | name = "displaydoc" 817 | version = "0.2.5" 818 | source = "registry+https://github.com/rust-lang/crates.io-index" 819 | checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 820 | dependencies = [ 821 | "proc-macro2", 822 | "quote", 823 | "syn", 824 | ] 825 | 826 | [[package]] 827 | name = "dlv-list" 828 | version = "0.5.2" 829 | source = "registry+https://github.com/rust-lang/crates.io-index" 830 | checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" 831 | dependencies = [ 832 | "const-random", 833 | ] 834 | 835 | [[package]] 836 | name = "docker_credential" 837 | version = "1.3.1" 838 | source = "registry+https://github.com/rust-lang/crates.io-index" 839 | checksum = "31951f49556e34d90ed28342e1df7e1cb7a229c4cab0aecc627b5d91edd41d07" 840 | dependencies = [ 841 | "base64 0.21.7", 842 | "serde", 843 | "serde_json", 844 | ] 845 | 846 | [[package]] 847 | name = "domain" 848 | version = "0.1.2" 849 | dependencies = [ 850 | "diesel", 851 | "serde", 852 | "uuid", 853 | ] 854 | 855 | [[package]] 856 | name = "dotenv" 857 | version = "0.15.0" 858 | source = "registry+https://github.com/rust-lang/crates.io-index" 859 | checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" 860 | 861 | [[package]] 862 | name = "dsl_auto_type" 863 | version = "0.1.2" 864 | source = "registry+https://github.com/rust-lang/crates.io-index" 865 | checksum = "c5d9abe6314103864cc2d8901b7ae224e0ab1a103a0a416661b4097b0779b607" 866 | dependencies = [ 867 | "darling", 868 | "either", 869 | "heck", 870 | "proc-macro2", 871 | "quote", 872 | "syn", 873 | ] 874 | 875 | [[package]] 876 | name = "either" 877 | version = "1.13.0" 878 | source = "registry+https://github.com/rust-lang/crates.io-index" 879 | checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" 880 | 881 | [[package]] 882 | name = "encoding_rs" 883 | version = "0.8.34" 884 | source = "registry+https://github.com/rust-lang/crates.io-index" 885 | checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" 886 | dependencies = [ 887 | "cfg-if", 888 | ] 889 | 890 | [[package]] 891 | name = "env_filter" 892 | version = "0.1.2" 893 | source = "registry+https://github.com/rust-lang/crates.io-index" 894 | checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" 895 | dependencies = [ 896 | "log", 897 | "regex", 898 | ] 899 | 900 | [[package]] 901 | name = "env_logger" 902 | version = "0.11.6" 903 | source = "registry+https://github.com/rust-lang/crates.io-index" 904 | checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" 905 | dependencies = [ 906 | "anstream", 907 | "anstyle", 908 | "env_filter", 909 | "humantime", 910 | "log", 911 | ] 912 | 913 | [[package]] 914 | name = "equivalent" 915 | version = "1.0.1" 916 | source = "registry+https://github.com/rust-lang/crates.io-index" 917 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 918 | 919 | [[package]] 920 | name = "erased-serde" 921 | version = "0.4.8" 922 | source = "registry+https://github.com/rust-lang/crates.io-index" 923 | checksum = "259d404d09818dec19332e31d94558aeb442fea04c817006456c24b5460bbd4b" 924 | dependencies = [ 925 | "serde", 926 | "serde_core", 927 | "typeid", 928 | ] 929 | 930 | [[package]] 931 | name = "errno" 932 | version = "0.3.9" 933 | source = "registry+https://github.com/rust-lang/crates.io-index" 934 | checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" 935 | dependencies = [ 936 | "libc", 937 | "windows-sys 0.52.0", 938 | ] 939 | 940 | [[package]] 941 | name = "etcetera" 942 | version = "0.8.0" 943 | source = "registry+https://github.com/rust-lang/crates.io-index" 944 | checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" 945 | dependencies = [ 946 | "cfg-if", 947 | "home", 948 | "windows-sys 0.48.0", 949 | ] 950 | 951 | [[package]] 952 | name = "fallible-iterator" 953 | version = "0.2.0" 954 | source = "registry+https://github.com/rust-lang/crates.io-index" 955 | checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" 956 | 957 | [[package]] 958 | name = "fastrand" 959 | version = "2.1.1" 960 | source = "registry+https://github.com/rust-lang/crates.io-index" 961 | checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" 962 | 963 | [[package]] 964 | name = "filetime" 965 | version = "0.2.23" 966 | source = "registry+https://github.com/rust-lang/crates.io-index" 967 | checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" 968 | dependencies = [ 969 | "cfg-if", 970 | "libc", 971 | "redox_syscall 0.4.1", 972 | "windows-sys 0.52.0", 973 | ] 974 | 975 | [[package]] 976 | name = "flate2" 977 | version = "1.0.34" 978 | source = "registry+https://github.com/rust-lang/crates.io-index" 979 | checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" 980 | dependencies = [ 981 | "crc32fast", 982 | "miniz_oxide 0.8.0", 983 | ] 984 | 985 | [[package]] 986 | name = "fnv" 987 | version = "1.0.7" 988 | source = "registry+https://github.com/rust-lang/crates.io-index" 989 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 990 | 991 | [[package]] 992 | name = "foldhash" 993 | version = "0.1.5" 994 | source = "registry+https://github.com/rust-lang/crates.io-index" 995 | checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" 996 | 997 | [[package]] 998 | name = "foreign-types" 999 | version = "0.3.2" 1000 | source = "registry+https://github.com/rust-lang/crates.io-index" 1001 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 1002 | dependencies = [ 1003 | "foreign-types-shared", 1004 | ] 1005 | 1006 | [[package]] 1007 | name = "foreign-types-shared" 1008 | version = "0.1.1" 1009 | source = "registry+https://github.com/rust-lang/crates.io-index" 1010 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 1011 | 1012 | [[package]] 1013 | name = "form_urlencoded" 1014 | version = "1.2.1" 1015 | source = "registry+https://github.com/rust-lang/crates.io-index" 1016 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 1017 | dependencies = [ 1018 | "percent-encoding", 1019 | ] 1020 | 1021 | [[package]] 1022 | name = "futures" 1023 | version = "0.3.31" 1024 | source = "registry+https://github.com/rust-lang/crates.io-index" 1025 | checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" 1026 | dependencies = [ 1027 | "futures-channel", 1028 | "futures-core", 1029 | "futures-executor", 1030 | "futures-io", 1031 | "futures-sink", 1032 | "futures-task", 1033 | "futures-util", 1034 | ] 1035 | 1036 | [[package]] 1037 | name = "futures-channel" 1038 | version = "0.3.31" 1039 | source = "registry+https://github.com/rust-lang/crates.io-index" 1040 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 1041 | dependencies = [ 1042 | "futures-core", 1043 | "futures-sink", 1044 | ] 1045 | 1046 | [[package]] 1047 | name = "futures-core" 1048 | version = "0.3.31" 1049 | source = "registry+https://github.com/rust-lang/crates.io-index" 1050 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 1051 | 1052 | [[package]] 1053 | name = "futures-executor" 1054 | version = "0.3.31" 1055 | source = "registry+https://github.com/rust-lang/crates.io-index" 1056 | checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" 1057 | dependencies = [ 1058 | "futures-core", 1059 | "futures-task", 1060 | "futures-util", 1061 | ] 1062 | 1063 | [[package]] 1064 | name = "futures-io" 1065 | version = "0.3.31" 1066 | source = "registry+https://github.com/rust-lang/crates.io-index" 1067 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 1068 | 1069 | [[package]] 1070 | name = "futures-macro" 1071 | version = "0.3.31" 1072 | source = "registry+https://github.com/rust-lang/crates.io-index" 1073 | checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" 1074 | dependencies = [ 1075 | "proc-macro2", 1076 | "quote", 1077 | "syn", 1078 | ] 1079 | 1080 | [[package]] 1081 | name = "futures-sink" 1082 | version = "0.3.31" 1083 | source = "registry+https://github.com/rust-lang/crates.io-index" 1084 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 1085 | 1086 | [[package]] 1087 | name = "futures-task" 1088 | version = "0.3.31" 1089 | source = "registry+https://github.com/rust-lang/crates.io-index" 1090 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 1091 | 1092 | [[package]] 1093 | name = "futures-util" 1094 | version = "0.3.31" 1095 | source = "registry+https://github.com/rust-lang/crates.io-index" 1096 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 1097 | dependencies = [ 1098 | "futures-channel", 1099 | "futures-core", 1100 | "futures-io", 1101 | "futures-macro", 1102 | "futures-sink", 1103 | "futures-task", 1104 | "memchr", 1105 | "pin-project-lite", 1106 | "pin-utils", 1107 | "slab", 1108 | ] 1109 | 1110 | [[package]] 1111 | name = "generic-array" 1112 | version = "0.14.7" 1113 | source = "registry+https://github.com/rust-lang/crates.io-index" 1114 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 1115 | dependencies = [ 1116 | "typenum", 1117 | "version_check", 1118 | ] 1119 | 1120 | [[package]] 1121 | name = "getrandom" 1122 | version = "0.2.15" 1123 | source = "registry+https://github.com/rust-lang/crates.io-index" 1124 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 1125 | dependencies = [ 1126 | "cfg-if", 1127 | "libc", 1128 | "wasi 0.11.0+wasi-snapshot-preview1", 1129 | ] 1130 | 1131 | [[package]] 1132 | name = "getrandom" 1133 | version = "0.3.1" 1134 | source = "registry+https://github.com/rust-lang/crates.io-index" 1135 | checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" 1136 | dependencies = [ 1137 | "cfg-if", 1138 | "libc", 1139 | "wasi 0.13.3+wasi-0.2.2", 1140 | "windows-targets 0.52.6", 1141 | ] 1142 | 1143 | [[package]] 1144 | name = "gimli" 1145 | version = "0.28.1" 1146 | source = "registry+https://github.com/rust-lang/crates.io-index" 1147 | checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" 1148 | 1149 | [[package]] 1150 | name = "h2" 1151 | version = "0.3.26" 1152 | source = "registry+https://github.com/rust-lang/crates.io-index" 1153 | checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" 1154 | dependencies = [ 1155 | "bytes", 1156 | "fnv", 1157 | "futures-core", 1158 | "futures-sink", 1159 | "futures-util", 1160 | "http 0.2.12", 1161 | "indexmap 2.6.0", 1162 | "slab", 1163 | "tokio", 1164 | "tokio-util", 1165 | "tracing", 1166 | ] 1167 | 1168 | [[package]] 1169 | name = "h2" 1170 | version = "0.4.6" 1171 | source = "registry+https://github.com/rust-lang/crates.io-index" 1172 | checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" 1173 | dependencies = [ 1174 | "atomic-waker", 1175 | "bytes", 1176 | "fnv", 1177 | "futures-core", 1178 | "futures-sink", 1179 | "http 1.3.1", 1180 | "indexmap 2.6.0", 1181 | "slab", 1182 | "tokio", 1183 | "tokio-util", 1184 | "tracing", 1185 | ] 1186 | 1187 | [[package]] 1188 | name = "hashbrown" 1189 | version = "0.12.3" 1190 | source = "registry+https://github.com/rust-lang/crates.io-index" 1191 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 1192 | 1193 | [[package]] 1194 | name = "hashbrown" 1195 | version = "0.14.5" 1196 | source = "registry+https://github.com/rust-lang/crates.io-index" 1197 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 1198 | 1199 | [[package]] 1200 | name = "hashbrown" 1201 | version = "0.15.1" 1202 | source = "registry+https://github.com/rust-lang/crates.io-index" 1203 | checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" 1204 | dependencies = [ 1205 | "foldhash", 1206 | ] 1207 | 1208 | [[package]] 1209 | name = "hashlink" 1210 | version = "0.10.0" 1211 | source = "registry+https://github.com/rust-lang/crates.io-index" 1212 | checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" 1213 | dependencies = [ 1214 | "hashbrown 0.15.1", 1215 | ] 1216 | 1217 | [[package]] 1218 | name = "heck" 1219 | version = "0.5.0" 1220 | source = "registry+https://github.com/rust-lang/crates.io-index" 1221 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 1222 | 1223 | [[package]] 1224 | name = "hermit-abi" 1225 | version = "0.3.9" 1226 | source = "registry+https://github.com/rust-lang/crates.io-index" 1227 | checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" 1228 | 1229 | [[package]] 1230 | name = "hex" 1231 | version = "0.4.3" 1232 | source = "registry+https://github.com/rust-lang/crates.io-index" 1233 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 1234 | 1235 | [[package]] 1236 | name = "hmac" 1237 | version = "0.12.1" 1238 | source = "registry+https://github.com/rust-lang/crates.io-index" 1239 | checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" 1240 | dependencies = [ 1241 | "digest", 1242 | ] 1243 | 1244 | [[package]] 1245 | name = "home" 1246 | version = "0.5.9" 1247 | source = "registry+https://github.com/rust-lang/crates.io-index" 1248 | checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" 1249 | dependencies = [ 1250 | "windows-sys 0.52.0", 1251 | ] 1252 | 1253 | [[package]] 1254 | name = "http" 1255 | version = "0.2.12" 1256 | source = "registry+https://github.com/rust-lang/crates.io-index" 1257 | checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" 1258 | dependencies = [ 1259 | "bytes", 1260 | "fnv", 1261 | "itoa", 1262 | ] 1263 | 1264 | [[package]] 1265 | name = "http" 1266 | version = "1.3.1" 1267 | source = "registry+https://github.com/rust-lang/crates.io-index" 1268 | checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" 1269 | dependencies = [ 1270 | "bytes", 1271 | "fnv", 1272 | "itoa", 1273 | ] 1274 | 1275 | [[package]] 1276 | name = "http-body" 1277 | version = "1.0.1" 1278 | source = "registry+https://github.com/rust-lang/crates.io-index" 1279 | checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 1280 | dependencies = [ 1281 | "bytes", 1282 | "http 1.3.1", 1283 | ] 1284 | 1285 | [[package]] 1286 | name = "http-body-util" 1287 | version = "0.1.2" 1288 | source = "registry+https://github.com/rust-lang/crates.io-index" 1289 | checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" 1290 | dependencies = [ 1291 | "bytes", 1292 | "futures-util", 1293 | "http 1.3.1", 1294 | "http-body", 1295 | "pin-project-lite", 1296 | ] 1297 | 1298 | [[package]] 1299 | name = "http-serde" 1300 | version = "2.1.1" 1301 | source = "registry+https://github.com/rust-lang/crates.io-index" 1302 | checksum = "0f056c8559e3757392c8d091e796416e4649d8e49e88b8d76df6c002f05027fd" 1303 | dependencies = [ 1304 | "http 1.3.1", 1305 | "serde", 1306 | ] 1307 | 1308 | [[package]] 1309 | name = "httparse" 1310 | version = "1.9.5" 1311 | source = "registry+https://github.com/rust-lang/crates.io-index" 1312 | checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" 1313 | 1314 | [[package]] 1315 | name = "httpdate" 1316 | version = "1.0.3" 1317 | source = "registry+https://github.com/rust-lang/crates.io-index" 1318 | checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 1319 | 1320 | [[package]] 1321 | name = "humantime" 1322 | version = "2.1.0" 1323 | source = "registry+https://github.com/rust-lang/crates.io-index" 1324 | checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" 1325 | 1326 | [[package]] 1327 | name = "hyper" 1328 | version = "1.6.0" 1329 | source = "registry+https://github.com/rust-lang/crates.io-index" 1330 | checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" 1331 | dependencies = [ 1332 | "bytes", 1333 | "futures-channel", 1334 | "futures-util", 1335 | "h2 0.4.6", 1336 | "http 1.3.1", 1337 | "http-body", 1338 | "httparse", 1339 | "httpdate", 1340 | "itoa", 1341 | "pin-project-lite", 1342 | "smallvec", 1343 | "tokio", 1344 | "want", 1345 | ] 1346 | 1347 | [[package]] 1348 | name = "hyper-named-pipe" 1349 | version = "0.1.0" 1350 | source = "registry+https://github.com/rust-lang/crates.io-index" 1351 | checksum = "73b7d8abf35697b81a825e386fc151e0d503e8cb5fcb93cc8669c376dfd6f278" 1352 | dependencies = [ 1353 | "hex", 1354 | "hyper", 1355 | "hyper-util", 1356 | "pin-project-lite", 1357 | "tokio", 1358 | "tower-service", 1359 | "winapi", 1360 | ] 1361 | 1362 | [[package]] 1363 | name = "hyper-rustls" 1364 | version = "0.27.3" 1365 | source = "registry+https://github.com/rust-lang/crates.io-index" 1366 | checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" 1367 | dependencies = [ 1368 | "futures-util", 1369 | "http 1.3.1", 1370 | "hyper", 1371 | "hyper-util", 1372 | "rustls", 1373 | "rustls-pki-types", 1374 | "tokio", 1375 | "tokio-rustls", 1376 | "tower-service", 1377 | ] 1378 | 1379 | [[package]] 1380 | name = "hyper-tls" 1381 | version = "0.6.0" 1382 | source = "registry+https://github.com/rust-lang/crates.io-index" 1383 | checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" 1384 | dependencies = [ 1385 | "bytes", 1386 | "http-body-util", 1387 | "hyper", 1388 | "hyper-util", 1389 | "native-tls", 1390 | "tokio", 1391 | "tokio-native-tls", 1392 | "tower-service", 1393 | ] 1394 | 1395 | [[package]] 1396 | name = "hyper-util" 1397 | version = "0.1.13" 1398 | source = "registry+https://github.com/rust-lang/crates.io-index" 1399 | checksum = "b1c293b6b3d21eca78250dc7dbebd6b9210ec5530e038cbfe0661b5c47ab06e8" 1400 | dependencies = [ 1401 | "base64 0.22.1", 1402 | "bytes", 1403 | "futures-channel", 1404 | "futures-core", 1405 | "futures-util", 1406 | "http 1.3.1", 1407 | "http-body", 1408 | "hyper", 1409 | "ipnet", 1410 | "libc", 1411 | "percent-encoding", 1412 | "pin-project-lite", 1413 | "socket2 0.5.10", 1414 | "system-configuration", 1415 | "tokio", 1416 | "tower-service", 1417 | "tracing", 1418 | "windows-registry", 1419 | ] 1420 | 1421 | [[package]] 1422 | name = "hyperlocal" 1423 | version = "0.9.1" 1424 | source = "registry+https://github.com/rust-lang/crates.io-index" 1425 | checksum = "986c5ce3b994526b3cd75578e62554abd09f0899d6206de48b3e96ab34ccc8c7" 1426 | dependencies = [ 1427 | "hex", 1428 | "http-body-util", 1429 | "hyper", 1430 | "hyper-util", 1431 | "pin-project-lite", 1432 | "tokio", 1433 | "tower-service", 1434 | ] 1435 | 1436 | [[package]] 1437 | name = "iana-time-zone" 1438 | version = "0.1.60" 1439 | source = "registry+https://github.com/rust-lang/crates.io-index" 1440 | checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" 1441 | dependencies = [ 1442 | "android_system_properties", 1443 | "core-foundation-sys", 1444 | "iana-time-zone-haiku", 1445 | "js-sys", 1446 | "wasm-bindgen", 1447 | "windows-core", 1448 | ] 1449 | 1450 | [[package]] 1451 | name = "iana-time-zone-haiku" 1452 | version = "0.1.2" 1453 | source = "registry+https://github.com/rust-lang/crates.io-index" 1454 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 1455 | dependencies = [ 1456 | "cc", 1457 | ] 1458 | 1459 | [[package]] 1460 | name = "icu_collections" 1461 | version = "1.5.0" 1462 | source = "registry+https://github.com/rust-lang/crates.io-index" 1463 | checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" 1464 | dependencies = [ 1465 | "displaydoc", 1466 | "yoke", 1467 | "zerofrom", 1468 | "zerovec", 1469 | ] 1470 | 1471 | [[package]] 1472 | name = "icu_locid" 1473 | version = "1.5.0" 1474 | source = "registry+https://github.com/rust-lang/crates.io-index" 1475 | checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" 1476 | dependencies = [ 1477 | "displaydoc", 1478 | "litemap", 1479 | "tinystr", 1480 | "writeable", 1481 | "zerovec", 1482 | ] 1483 | 1484 | [[package]] 1485 | name = "icu_locid_transform" 1486 | version = "1.5.0" 1487 | source = "registry+https://github.com/rust-lang/crates.io-index" 1488 | checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" 1489 | dependencies = [ 1490 | "displaydoc", 1491 | "icu_locid", 1492 | "icu_locid_transform_data", 1493 | "icu_provider", 1494 | "tinystr", 1495 | "zerovec", 1496 | ] 1497 | 1498 | [[package]] 1499 | name = "icu_locid_transform_data" 1500 | version = "1.5.0" 1501 | source = "registry+https://github.com/rust-lang/crates.io-index" 1502 | checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" 1503 | 1504 | [[package]] 1505 | name = "icu_normalizer" 1506 | version = "1.5.0" 1507 | source = "registry+https://github.com/rust-lang/crates.io-index" 1508 | checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" 1509 | dependencies = [ 1510 | "displaydoc", 1511 | "icu_collections", 1512 | "icu_normalizer_data", 1513 | "icu_properties", 1514 | "icu_provider", 1515 | "smallvec", 1516 | "utf16_iter", 1517 | "utf8_iter", 1518 | "write16", 1519 | "zerovec", 1520 | ] 1521 | 1522 | [[package]] 1523 | name = "icu_normalizer_data" 1524 | version = "1.5.0" 1525 | source = "registry+https://github.com/rust-lang/crates.io-index" 1526 | checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" 1527 | 1528 | [[package]] 1529 | name = "icu_properties" 1530 | version = "1.5.1" 1531 | source = "registry+https://github.com/rust-lang/crates.io-index" 1532 | checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" 1533 | dependencies = [ 1534 | "displaydoc", 1535 | "icu_collections", 1536 | "icu_locid_transform", 1537 | "icu_properties_data", 1538 | "icu_provider", 1539 | "tinystr", 1540 | "zerovec", 1541 | ] 1542 | 1543 | [[package]] 1544 | name = "icu_properties_data" 1545 | version = "1.5.0" 1546 | source = "registry+https://github.com/rust-lang/crates.io-index" 1547 | checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" 1548 | 1549 | [[package]] 1550 | name = "icu_provider" 1551 | version = "1.5.0" 1552 | source = "registry+https://github.com/rust-lang/crates.io-index" 1553 | checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" 1554 | dependencies = [ 1555 | "displaydoc", 1556 | "icu_locid", 1557 | "icu_provider_macros", 1558 | "stable_deref_trait", 1559 | "tinystr", 1560 | "writeable", 1561 | "yoke", 1562 | "zerofrom", 1563 | "zerovec", 1564 | ] 1565 | 1566 | [[package]] 1567 | name = "icu_provider_macros" 1568 | version = "1.5.0" 1569 | source = "registry+https://github.com/rust-lang/crates.io-index" 1570 | checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" 1571 | dependencies = [ 1572 | "proc-macro2", 1573 | "quote", 1574 | "syn", 1575 | ] 1576 | 1577 | [[package]] 1578 | name = "ident_case" 1579 | version = "1.0.1" 1580 | source = "registry+https://github.com/rust-lang/crates.io-index" 1581 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 1582 | 1583 | [[package]] 1584 | name = "idna" 1585 | version = "1.0.3" 1586 | source = "registry+https://github.com/rust-lang/crates.io-index" 1587 | checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" 1588 | dependencies = [ 1589 | "idna_adapter", 1590 | "smallvec", 1591 | "utf8_iter", 1592 | ] 1593 | 1594 | [[package]] 1595 | name = "idna_adapter" 1596 | version = "1.2.0" 1597 | source = "registry+https://github.com/rust-lang/crates.io-index" 1598 | checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" 1599 | dependencies = [ 1600 | "icu_normalizer", 1601 | "icu_properties", 1602 | ] 1603 | 1604 | [[package]] 1605 | name = "impl-more" 1606 | version = "0.1.8" 1607 | source = "registry+https://github.com/rust-lang/crates.io-index" 1608 | checksum = "aae21c3177a27788957044151cc2800043d127acaa460a47ebb9b84dfa2c6aa0" 1609 | 1610 | [[package]] 1611 | name = "indexmap" 1612 | version = "1.9.3" 1613 | source = "registry+https://github.com/rust-lang/crates.io-index" 1614 | checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" 1615 | dependencies = [ 1616 | "autocfg", 1617 | "hashbrown 0.12.3", 1618 | "serde", 1619 | ] 1620 | 1621 | [[package]] 1622 | name = "indexmap" 1623 | version = "2.6.0" 1624 | source = "registry+https://github.com/rust-lang/crates.io-index" 1625 | checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" 1626 | dependencies = [ 1627 | "equivalent", 1628 | "hashbrown 0.15.1", 1629 | "serde", 1630 | ] 1631 | 1632 | [[package]] 1633 | name = "infrastructure" 1634 | version = "0.1.1" 1635 | dependencies = [ 1636 | "actix-web", 1637 | "anyhow", 1638 | "application", 1639 | "async-trait", 1640 | "diesel", 1641 | "diesel_migrations", 1642 | "domain", 1643 | "thiserror 2.0.12", 1644 | "uuid", 1645 | ] 1646 | 1647 | [[package]] 1648 | name = "io-uring" 1649 | version = "0.7.8" 1650 | source = "registry+https://github.com/rust-lang/crates.io-index" 1651 | checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013" 1652 | dependencies = [ 1653 | "bitflags 2.6.0", 1654 | "cfg-if", 1655 | "libc", 1656 | ] 1657 | 1658 | [[package]] 1659 | name = "ipnet" 1660 | version = "2.10.1" 1661 | source = "registry+https://github.com/rust-lang/crates.io-index" 1662 | checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" 1663 | 1664 | [[package]] 1665 | name = "iri-string" 1666 | version = "0.7.8" 1667 | source = "registry+https://github.com/rust-lang/crates.io-index" 1668 | checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" 1669 | dependencies = [ 1670 | "memchr", 1671 | "serde", 1672 | ] 1673 | 1674 | [[package]] 1675 | name = "is_terminal_polyfill" 1676 | version = "1.70.1" 1677 | source = "registry+https://github.com/rust-lang/crates.io-index" 1678 | checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" 1679 | 1680 | [[package]] 1681 | name = "itoa" 1682 | version = "1.0.11" 1683 | source = "registry+https://github.com/rust-lang/crates.io-index" 1684 | checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" 1685 | 1686 | [[package]] 1687 | name = "jobserver" 1688 | version = "0.1.32" 1689 | source = "registry+https://github.com/rust-lang/crates.io-index" 1690 | checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" 1691 | dependencies = [ 1692 | "libc", 1693 | ] 1694 | 1695 | [[package]] 1696 | name = "js-sys" 1697 | version = "0.3.77" 1698 | source = "registry+https://github.com/rust-lang/crates.io-index" 1699 | checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 1700 | dependencies = [ 1701 | "once_cell", 1702 | "wasm-bindgen", 1703 | ] 1704 | 1705 | [[package]] 1706 | name = "json5" 1707 | version = "0.4.1" 1708 | source = "registry+https://github.com/rust-lang/crates.io-index" 1709 | checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" 1710 | dependencies = [ 1711 | "pest", 1712 | "pest_derive", 1713 | "serde", 1714 | ] 1715 | 1716 | [[package]] 1717 | name = "language-tags" 1718 | version = "0.3.2" 1719 | source = "registry+https://github.com/rust-lang/crates.io-index" 1720 | checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" 1721 | 1722 | [[package]] 1723 | name = "libc" 1724 | version = "0.2.172" 1725 | source = "registry+https://github.com/rust-lang/crates.io-index" 1726 | checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" 1727 | 1728 | [[package]] 1729 | name = "linux-raw-sys" 1730 | version = "0.4.13" 1731 | source = "registry+https://github.com/rust-lang/crates.io-index" 1732 | checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" 1733 | 1734 | [[package]] 1735 | name = "litemap" 1736 | version = "0.7.3" 1737 | source = "registry+https://github.com/rust-lang/crates.io-index" 1738 | checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" 1739 | 1740 | [[package]] 1741 | name = "local-channel" 1742 | version = "0.1.5" 1743 | source = "registry+https://github.com/rust-lang/crates.io-index" 1744 | checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" 1745 | dependencies = [ 1746 | "futures-core", 1747 | "futures-sink", 1748 | "local-waker", 1749 | ] 1750 | 1751 | [[package]] 1752 | name = "local-waker" 1753 | version = "0.1.4" 1754 | source = "registry+https://github.com/rust-lang/crates.io-index" 1755 | checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" 1756 | 1757 | [[package]] 1758 | name = "lock_api" 1759 | version = "0.4.12" 1760 | source = "registry+https://github.com/rust-lang/crates.io-index" 1761 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" 1762 | dependencies = [ 1763 | "autocfg", 1764 | "scopeguard", 1765 | ] 1766 | 1767 | [[package]] 1768 | name = "lockfree-object-pool" 1769 | version = "0.1.6" 1770 | source = "registry+https://github.com/rust-lang/crates.io-index" 1771 | checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" 1772 | 1773 | [[package]] 1774 | name = "log" 1775 | version = "0.4.27" 1776 | source = "registry+https://github.com/rust-lang/crates.io-index" 1777 | checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" 1778 | 1779 | [[package]] 1780 | name = "md-5" 1781 | version = "0.10.6" 1782 | source = "registry+https://github.com/rust-lang/crates.io-index" 1783 | checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" 1784 | dependencies = [ 1785 | "cfg-if", 1786 | "digest", 1787 | ] 1788 | 1789 | [[package]] 1790 | name = "memchr" 1791 | version = "2.7.4" 1792 | source = "registry+https://github.com/rust-lang/crates.io-index" 1793 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 1794 | 1795 | [[package]] 1796 | name = "migrations_internals" 1797 | version = "2.2.0" 1798 | source = "registry+https://github.com/rust-lang/crates.io-index" 1799 | checksum = "fd01039851e82f8799046eabbb354056283fb265c8ec0996af940f4e85a380ff" 1800 | dependencies = [ 1801 | "serde", 1802 | "toml 0.8.19", 1803 | ] 1804 | 1805 | [[package]] 1806 | name = "migrations_macros" 1807 | version = "2.2.0" 1808 | source = "registry+https://github.com/rust-lang/crates.io-index" 1809 | checksum = "ffb161cc72176cb37aa47f1fc520d3ef02263d67d661f44f05d05a079e1237fd" 1810 | dependencies = [ 1811 | "migrations_internals", 1812 | "proc-macro2", 1813 | "quote", 1814 | ] 1815 | 1816 | [[package]] 1817 | name = "mime" 1818 | version = "0.3.17" 1819 | source = "registry+https://github.com/rust-lang/crates.io-index" 1820 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 1821 | 1822 | [[package]] 1823 | name = "mime_guess" 1824 | version = "2.0.5" 1825 | source = "registry+https://github.com/rust-lang/crates.io-index" 1826 | checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" 1827 | dependencies = [ 1828 | "mime", 1829 | "unicase", 1830 | ] 1831 | 1832 | [[package]] 1833 | name = "miniz_oxide" 1834 | version = "0.7.4" 1835 | source = "registry+https://github.com/rust-lang/crates.io-index" 1836 | checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" 1837 | dependencies = [ 1838 | "adler", 1839 | ] 1840 | 1841 | [[package]] 1842 | name = "miniz_oxide" 1843 | version = "0.8.0" 1844 | source = "registry+https://github.com/rust-lang/crates.io-index" 1845 | checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" 1846 | dependencies = [ 1847 | "adler2", 1848 | ] 1849 | 1850 | [[package]] 1851 | name = "mio" 1852 | version = "1.0.2" 1853 | source = "registry+https://github.com/rust-lang/crates.io-index" 1854 | checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" 1855 | dependencies = [ 1856 | "hermit-abi", 1857 | "libc", 1858 | "log", 1859 | "wasi 0.11.0+wasi-snapshot-preview1", 1860 | "windows-sys 0.52.0", 1861 | ] 1862 | 1863 | [[package]] 1864 | name = "native-tls" 1865 | version = "0.2.12" 1866 | source = "registry+https://github.com/rust-lang/crates.io-index" 1867 | checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" 1868 | dependencies = [ 1869 | "libc", 1870 | "log", 1871 | "openssl", 1872 | "openssl-probe", 1873 | "openssl-sys", 1874 | "schannel", 1875 | "security-framework 2.10.0", 1876 | "security-framework-sys", 1877 | "tempfile", 1878 | ] 1879 | 1880 | [[package]] 1881 | name = "num-conv" 1882 | version = "0.1.0" 1883 | source = "registry+https://github.com/rust-lang/crates.io-index" 1884 | checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" 1885 | 1886 | [[package]] 1887 | name = "num-traits" 1888 | version = "0.2.19" 1889 | source = "registry+https://github.com/rust-lang/crates.io-index" 1890 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 1891 | dependencies = [ 1892 | "autocfg", 1893 | ] 1894 | 1895 | [[package]] 1896 | name = "object" 1897 | version = "0.32.2" 1898 | source = "registry+https://github.com/rust-lang/crates.io-index" 1899 | checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" 1900 | dependencies = [ 1901 | "memchr", 1902 | ] 1903 | 1904 | [[package]] 1905 | name = "once_cell" 1906 | version = "1.21.3" 1907 | source = "registry+https://github.com/rust-lang/crates.io-index" 1908 | checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 1909 | 1910 | [[package]] 1911 | name = "openssl" 1912 | version = "0.10.66" 1913 | source = "registry+https://github.com/rust-lang/crates.io-index" 1914 | checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" 1915 | dependencies = [ 1916 | "bitflags 2.6.0", 1917 | "cfg-if", 1918 | "foreign-types", 1919 | "libc", 1920 | "once_cell", 1921 | "openssl-macros", 1922 | "openssl-sys", 1923 | ] 1924 | 1925 | [[package]] 1926 | name = "openssl-macros" 1927 | version = "0.1.1" 1928 | source = "registry+https://github.com/rust-lang/crates.io-index" 1929 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 1930 | dependencies = [ 1931 | "proc-macro2", 1932 | "quote", 1933 | "syn", 1934 | ] 1935 | 1936 | [[package]] 1937 | name = "openssl-probe" 1938 | version = "0.1.5" 1939 | source = "registry+https://github.com/rust-lang/crates.io-index" 1940 | checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" 1941 | 1942 | [[package]] 1943 | name = "openssl-sys" 1944 | version = "0.9.103" 1945 | source = "registry+https://github.com/rust-lang/crates.io-index" 1946 | checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" 1947 | dependencies = [ 1948 | "cc", 1949 | "libc", 1950 | "pkg-config", 1951 | "vcpkg", 1952 | ] 1953 | 1954 | [[package]] 1955 | name = "ordered-multimap" 1956 | version = "0.7.3" 1957 | source = "registry+https://github.com/rust-lang/crates.io-index" 1958 | checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" 1959 | dependencies = [ 1960 | "dlv-list", 1961 | "hashbrown 0.14.5", 1962 | ] 1963 | 1964 | [[package]] 1965 | name = "parking_lot" 1966 | version = "0.12.3" 1967 | source = "registry+https://github.com/rust-lang/crates.io-index" 1968 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" 1969 | dependencies = [ 1970 | "lock_api", 1971 | "parking_lot_core", 1972 | ] 1973 | 1974 | [[package]] 1975 | name = "parking_lot_core" 1976 | version = "0.9.10" 1977 | source = "registry+https://github.com/rust-lang/crates.io-index" 1978 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" 1979 | dependencies = [ 1980 | "cfg-if", 1981 | "libc", 1982 | "redox_syscall 0.5.7", 1983 | "smallvec", 1984 | "windows-targets 0.52.6", 1985 | ] 1986 | 1987 | [[package]] 1988 | name = "parse-display" 1989 | version = "0.9.1" 1990 | source = "registry+https://github.com/rust-lang/crates.io-index" 1991 | checksum = "914a1c2265c98e2446911282c6ac86d8524f495792c38c5bd884f80499c7538a" 1992 | dependencies = [ 1993 | "parse-display-derive", 1994 | "regex", 1995 | "regex-syntax", 1996 | ] 1997 | 1998 | [[package]] 1999 | name = "parse-display-derive" 2000 | version = "0.9.1" 2001 | source = "registry+https://github.com/rust-lang/crates.io-index" 2002 | checksum = "2ae7800a4c974efd12df917266338e79a7a74415173caf7e70aa0a0707345281" 2003 | dependencies = [ 2004 | "proc-macro2", 2005 | "quote", 2006 | "regex", 2007 | "regex-syntax", 2008 | "structmeta", 2009 | "syn", 2010 | ] 2011 | 2012 | [[package]] 2013 | name = "paste" 2014 | version = "1.0.15" 2015 | source = "registry+https://github.com/rust-lang/crates.io-index" 2016 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 2017 | 2018 | [[package]] 2019 | name = "pathdiff" 2020 | version = "0.2.2" 2021 | source = "registry+https://github.com/rust-lang/crates.io-index" 2022 | checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361" 2023 | 2024 | [[package]] 2025 | name = "percent-encoding" 2026 | version = "2.3.1" 2027 | source = "registry+https://github.com/rust-lang/crates.io-index" 2028 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 2029 | 2030 | [[package]] 2031 | name = "pest" 2032 | version = "2.7.14" 2033 | source = "registry+https://github.com/rust-lang/crates.io-index" 2034 | checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" 2035 | dependencies = [ 2036 | "memchr", 2037 | "thiserror 1.0.68", 2038 | "ucd-trie", 2039 | ] 2040 | 2041 | [[package]] 2042 | name = "pest_derive" 2043 | version = "2.7.14" 2044 | source = "registry+https://github.com/rust-lang/crates.io-index" 2045 | checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" 2046 | dependencies = [ 2047 | "pest", 2048 | "pest_generator", 2049 | ] 2050 | 2051 | [[package]] 2052 | name = "pest_generator" 2053 | version = "2.7.14" 2054 | source = "registry+https://github.com/rust-lang/crates.io-index" 2055 | checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" 2056 | dependencies = [ 2057 | "pest", 2058 | "pest_meta", 2059 | "proc-macro2", 2060 | "quote", 2061 | "syn", 2062 | ] 2063 | 2064 | [[package]] 2065 | name = "pest_meta" 2066 | version = "2.7.14" 2067 | source = "registry+https://github.com/rust-lang/crates.io-index" 2068 | checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" 2069 | dependencies = [ 2070 | "once_cell", 2071 | "pest", 2072 | "sha2", 2073 | ] 2074 | 2075 | [[package]] 2076 | name = "phf" 2077 | version = "0.11.2" 2078 | source = "registry+https://github.com/rust-lang/crates.io-index" 2079 | checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" 2080 | dependencies = [ 2081 | "phf_shared", 2082 | ] 2083 | 2084 | [[package]] 2085 | name = "phf_shared" 2086 | version = "0.11.2" 2087 | source = "registry+https://github.com/rust-lang/crates.io-index" 2088 | checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" 2089 | dependencies = [ 2090 | "siphasher", 2091 | ] 2092 | 2093 | [[package]] 2094 | name = "pin-project-lite" 2095 | version = "0.2.15" 2096 | source = "registry+https://github.com/rust-lang/crates.io-index" 2097 | checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" 2098 | 2099 | [[package]] 2100 | name = "pin-utils" 2101 | version = "0.1.0" 2102 | source = "registry+https://github.com/rust-lang/crates.io-index" 2103 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 2104 | 2105 | [[package]] 2106 | name = "pkg-config" 2107 | version = "0.3.30" 2108 | source = "registry+https://github.com/rust-lang/crates.io-index" 2109 | checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" 2110 | 2111 | [[package]] 2112 | name = "postgres-protocol" 2113 | version = "0.6.8" 2114 | source = "registry+https://github.com/rust-lang/crates.io-index" 2115 | checksum = "76ff0abab4a9b844b93ef7b81f1efc0a366062aaef2cd702c76256b5dc075c54" 2116 | dependencies = [ 2117 | "base64 0.22.1", 2118 | "byteorder", 2119 | "bytes", 2120 | "fallible-iterator", 2121 | "hmac", 2122 | "md-5", 2123 | "memchr", 2124 | "rand", 2125 | "sha2", 2126 | "stringprep", 2127 | ] 2128 | 2129 | [[package]] 2130 | name = "postgres-types" 2131 | version = "0.2.9" 2132 | source = "registry+https://github.com/rust-lang/crates.io-index" 2133 | checksum = "613283563cd90e1dfc3518d548caee47e0e725455ed619881f5cf21f36de4b48" 2134 | dependencies = [ 2135 | "bytes", 2136 | "fallible-iterator", 2137 | "postgres-protocol", 2138 | "uuid", 2139 | ] 2140 | 2141 | [[package]] 2142 | name = "powerfmt" 2143 | version = "0.2.0" 2144 | source = "registry+https://github.com/rust-lang/crates.io-index" 2145 | checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" 2146 | 2147 | [[package]] 2148 | name = "ppv-lite86" 2149 | version = "0.2.20" 2150 | source = "registry+https://github.com/rust-lang/crates.io-index" 2151 | checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" 2152 | dependencies = [ 2153 | "zerocopy 0.7.35", 2154 | ] 2155 | 2156 | [[package]] 2157 | name = "pq-sys" 2158 | version = "0.6.3" 2159 | source = "registry+https://github.com/rust-lang/crates.io-index" 2160 | checksum = "f6cc05d7ea95200187117196eee9edd0644424911821aeb28a18ce60ea0b8793" 2161 | dependencies = [ 2162 | "vcpkg", 2163 | ] 2164 | 2165 | [[package]] 2166 | name = "presentation" 2167 | version = "0.2.3" 2168 | dependencies = [ 2169 | "actix-web", 2170 | "anyhow", 2171 | "application", 2172 | "http 1.3.1", 2173 | "infrastructure", 2174 | "problem_details", 2175 | "readonly", 2176 | "serde", 2177 | "serde_json", 2178 | "utoipa", 2179 | "uuid", 2180 | ] 2181 | 2182 | [[package]] 2183 | name = "problem_details" 2184 | version = "0.8.0" 2185 | source = "registry+https://github.com/rust-lang/crates.io-index" 2186 | checksum = "777f7cf33eca7f41687a047c133ec7df9a03b13757a2666062d8b9cfa446e397" 2187 | dependencies = [ 2188 | "actix-web", 2189 | "http 1.3.1", 2190 | "http-serde", 2191 | "serde", 2192 | "serde_json", 2193 | ] 2194 | 2195 | [[package]] 2196 | name = "proc-macro2" 2197 | version = "1.0.92" 2198 | source = "registry+https://github.com/rust-lang/crates.io-index" 2199 | checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" 2200 | dependencies = [ 2201 | "unicode-ident", 2202 | ] 2203 | 2204 | [[package]] 2205 | name = "quote" 2206 | version = "1.0.37" 2207 | source = "registry+https://github.com/rust-lang/crates.io-index" 2208 | checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" 2209 | dependencies = [ 2210 | "proc-macro2", 2211 | ] 2212 | 2213 | [[package]] 2214 | name = "r2d2" 2215 | version = "0.8.10" 2216 | source = "registry+https://github.com/rust-lang/crates.io-index" 2217 | checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" 2218 | dependencies = [ 2219 | "log", 2220 | "parking_lot", 2221 | "scheduled-thread-pool", 2222 | ] 2223 | 2224 | [[package]] 2225 | name = "rand" 2226 | version = "0.9.0" 2227 | source = "registry+https://github.com/rust-lang/crates.io-index" 2228 | checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" 2229 | dependencies = [ 2230 | "rand_chacha", 2231 | "rand_core", 2232 | "zerocopy 0.8.14", 2233 | ] 2234 | 2235 | [[package]] 2236 | name = "rand_chacha" 2237 | version = "0.9.0" 2238 | source = "registry+https://github.com/rust-lang/crates.io-index" 2239 | checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" 2240 | dependencies = [ 2241 | "ppv-lite86", 2242 | "rand_core", 2243 | ] 2244 | 2245 | [[package]] 2246 | name = "rand_core" 2247 | version = "0.9.0" 2248 | source = "registry+https://github.com/rust-lang/crates.io-index" 2249 | checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" 2250 | dependencies = [ 2251 | "getrandom 0.3.1", 2252 | "zerocopy 0.8.14", 2253 | ] 2254 | 2255 | [[package]] 2256 | name = "readonly" 2257 | version = "0.2.13" 2258 | source = "registry+https://github.com/rust-lang/crates.io-index" 2259 | checksum = "f2a62d85ed81ca5305dc544bd42c8804c5060b78ffa5ad3c64b0fb6a8c13d062" 2260 | dependencies = [ 2261 | "proc-macro2", 2262 | "quote", 2263 | "syn", 2264 | ] 2265 | 2266 | [[package]] 2267 | name = "redox_syscall" 2268 | version = "0.3.5" 2269 | source = "registry+https://github.com/rust-lang/crates.io-index" 2270 | checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" 2271 | dependencies = [ 2272 | "bitflags 1.3.2", 2273 | ] 2274 | 2275 | [[package]] 2276 | name = "redox_syscall" 2277 | version = "0.4.1" 2278 | source = "registry+https://github.com/rust-lang/crates.io-index" 2279 | checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" 2280 | dependencies = [ 2281 | "bitflags 1.3.2", 2282 | ] 2283 | 2284 | [[package]] 2285 | name = "redox_syscall" 2286 | version = "0.5.7" 2287 | source = "registry+https://github.com/rust-lang/crates.io-index" 2288 | checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" 2289 | dependencies = [ 2290 | "bitflags 2.6.0", 2291 | ] 2292 | 2293 | [[package]] 2294 | name = "regex" 2295 | version = "1.11.1" 2296 | source = "registry+https://github.com/rust-lang/crates.io-index" 2297 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 2298 | dependencies = [ 2299 | "aho-corasick", 2300 | "memchr", 2301 | "regex-automata", 2302 | "regex-syntax", 2303 | ] 2304 | 2305 | [[package]] 2306 | name = "regex-automata" 2307 | version = "0.4.8" 2308 | source = "registry+https://github.com/rust-lang/crates.io-index" 2309 | checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" 2310 | dependencies = [ 2311 | "aho-corasick", 2312 | "memchr", 2313 | "regex-syntax", 2314 | ] 2315 | 2316 | [[package]] 2317 | name = "regex-lite" 2318 | version = "0.1.6" 2319 | source = "registry+https://github.com/rust-lang/crates.io-index" 2320 | checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" 2321 | 2322 | [[package]] 2323 | name = "regex-syntax" 2324 | version = "0.8.5" 2325 | source = "registry+https://github.com/rust-lang/crates.io-index" 2326 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 2327 | 2328 | [[package]] 2329 | name = "reqwest" 2330 | version = "0.12.22" 2331 | source = "registry+https://github.com/rust-lang/crates.io-index" 2332 | checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531" 2333 | dependencies = [ 2334 | "base64 0.22.1", 2335 | "bytes", 2336 | "encoding_rs", 2337 | "futures-core", 2338 | "h2 0.4.6", 2339 | "http 1.3.1", 2340 | "http-body", 2341 | "http-body-util", 2342 | "hyper", 2343 | "hyper-rustls", 2344 | "hyper-tls", 2345 | "hyper-util", 2346 | "js-sys", 2347 | "log", 2348 | "mime", 2349 | "native-tls", 2350 | "percent-encoding", 2351 | "pin-project-lite", 2352 | "rustls-pki-types", 2353 | "serde", 2354 | "serde_json", 2355 | "serde_urlencoded", 2356 | "sync_wrapper", 2357 | "tokio", 2358 | "tokio-native-tls", 2359 | "tower", 2360 | "tower-http", 2361 | "tower-service", 2362 | "url", 2363 | "wasm-bindgen", 2364 | "wasm-bindgen-futures", 2365 | "web-sys", 2366 | ] 2367 | 2368 | [[package]] 2369 | name = "ring" 2370 | version = "0.17.8" 2371 | source = "registry+https://github.com/rust-lang/crates.io-index" 2372 | checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" 2373 | dependencies = [ 2374 | "cc", 2375 | "cfg-if", 2376 | "getrandom 0.2.15", 2377 | "libc", 2378 | "spin", 2379 | "untrusted", 2380 | "windows-sys 0.52.0", 2381 | ] 2382 | 2383 | [[package]] 2384 | name = "ron" 2385 | version = "0.8.1" 2386 | source = "registry+https://github.com/rust-lang/crates.io-index" 2387 | checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" 2388 | dependencies = [ 2389 | "base64 0.21.7", 2390 | "bitflags 2.6.0", 2391 | "serde", 2392 | "serde_derive", 2393 | ] 2394 | 2395 | [[package]] 2396 | name = "rust-embed" 2397 | version = "8.5.0" 2398 | source = "registry+https://github.com/rust-lang/crates.io-index" 2399 | checksum = "fa66af4a4fdd5e7ebc276f115e895611a34739a9c1c01028383d612d550953c0" 2400 | dependencies = [ 2401 | "rust-embed-impl", 2402 | "rust-embed-utils", 2403 | "walkdir", 2404 | ] 2405 | 2406 | [[package]] 2407 | name = "rust-embed-impl" 2408 | version = "8.5.0" 2409 | source = "registry+https://github.com/rust-lang/crates.io-index" 2410 | checksum = "6125dbc8867951125eec87294137f4e9c2c96566e61bf72c45095a7c77761478" 2411 | dependencies = [ 2412 | "proc-macro2", 2413 | "quote", 2414 | "rust-embed-utils", 2415 | "syn", 2416 | "walkdir", 2417 | ] 2418 | 2419 | [[package]] 2420 | name = "rust-embed-utils" 2421 | version = "8.5.0" 2422 | source = "registry+https://github.com/rust-lang/crates.io-index" 2423 | checksum = "2e5347777e9aacb56039b0e1f28785929a8a3b709e87482e7442c72e7c12529d" 2424 | dependencies = [ 2425 | "sha2", 2426 | "walkdir", 2427 | ] 2428 | 2429 | [[package]] 2430 | name = "rust-ini" 2431 | version = "0.21.1" 2432 | source = "registry+https://github.com/rust-lang/crates.io-index" 2433 | checksum = "4e310ef0e1b6eeb79169a1171daf9abcb87a2e17c03bee2c4bb100b55c75409f" 2434 | dependencies = [ 2435 | "cfg-if", 2436 | "ordered-multimap", 2437 | "trim-in-place", 2438 | ] 2439 | 2440 | [[package]] 2441 | name = "rustc-demangle" 2442 | version = "0.1.24" 2443 | source = "registry+https://github.com/rust-lang/crates.io-index" 2444 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 2445 | 2446 | [[package]] 2447 | name = "rustix" 2448 | version = "0.38.34" 2449 | source = "registry+https://github.com/rust-lang/crates.io-index" 2450 | checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" 2451 | dependencies = [ 2452 | "bitflags 2.6.0", 2453 | "errno", 2454 | "libc", 2455 | "linux-raw-sys", 2456 | "windows-sys 0.52.0", 2457 | ] 2458 | 2459 | [[package]] 2460 | name = "rustls" 2461 | version = "0.23.16" 2462 | source = "registry+https://github.com/rust-lang/crates.io-index" 2463 | checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" 2464 | dependencies = [ 2465 | "once_cell", 2466 | "ring", 2467 | "rustls-pki-types", 2468 | "rustls-webpki", 2469 | "subtle", 2470 | "zeroize", 2471 | ] 2472 | 2473 | [[package]] 2474 | name = "rustls-native-certs" 2475 | version = "0.8.1" 2476 | source = "registry+https://github.com/rust-lang/crates.io-index" 2477 | checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" 2478 | dependencies = [ 2479 | "openssl-probe", 2480 | "rustls-pki-types", 2481 | "schannel", 2482 | "security-framework 3.2.0", 2483 | ] 2484 | 2485 | [[package]] 2486 | name = "rustls-pemfile" 2487 | version = "2.2.0" 2488 | source = "registry+https://github.com/rust-lang/crates.io-index" 2489 | checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" 2490 | dependencies = [ 2491 | "rustls-pki-types", 2492 | ] 2493 | 2494 | [[package]] 2495 | name = "rustls-pki-types" 2496 | version = "1.10.0" 2497 | source = "registry+https://github.com/rust-lang/crates.io-index" 2498 | checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" 2499 | 2500 | [[package]] 2501 | name = "rustls-webpki" 2502 | version = "0.102.8" 2503 | source = "registry+https://github.com/rust-lang/crates.io-index" 2504 | checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" 2505 | dependencies = [ 2506 | "ring", 2507 | "rustls-pki-types", 2508 | "untrusted", 2509 | ] 2510 | 2511 | [[package]] 2512 | name = "rustversion" 2513 | version = "1.0.20" 2514 | source = "registry+https://github.com/rust-lang/crates.io-index" 2515 | checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" 2516 | 2517 | [[package]] 2518 | name = "ryu" 2519 | version = "1.0.18" 2520 | source = "registry+https://github.com/rust-lang/crates.io-index" 2521 | checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" 2522 | 2523 | [[package]] 2524 | name = "same-file" 2525 | version = "1.0.6" 2526 | source = "registry+https://github.com/rust-lang/crates.io-index" 2527 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 2528 | dependencies = [ 2529 | "winapi-util", 2530 | ] 2531 | 2532 | [[package]] 2533 | name = "scc" 2534 | version = "2.1.4" 2535 | source = "registry+https://github.com/rust-lang/crates.io-index" 2536 | checksum = "a4465c22496331e20eb047ff46e7366455bc01c0c02015c4a376de0b2cd3a1af" 2537 | dependencies = [ 2538 | "sdd", 2539 | ] 2540 | 2541 | [[package]] 2542 | name = "schannel" 2543 | version = "0.1.26" 2544 | source = "registry+https://github.com/rust-lang/crates.io-index" 2545 | checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" 2546 | dependencies = [ 2547 | "windows-sys 0.59.0", 2548 | ] 2549 | 2550 | [[package]] 2551 | name = "scheduled-thread-pool" 2552 | version = "0.2.7" 2553 | source = "registry+https://github.com/rust-lang/crates.io-index" 2554 | checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" 2555 | dependencies = [ 2556 | "parking_lot", 2557 | ] 2558 | 2559 | [[package]] 2560 | name = "scopeguard" 2561 | version = "1.2.0" 2562 | source = "registry+https://github.com/rust-lang/crates.io-index" 2563 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 2564 | 2565 | [[package]] 2566 | name = "sdd" 2567 | version = "1.7.0" 2568 | source = "registry+https://github.com/rust-lang/crates.io-index" 2569 | checksum = "85f05a494052771fc5bd0619742363b5e24e5ad72ab3111ec2e27925b8edc5f3" 2570 | 2571 | [[package]] 2572 | name = "security-framework" 2573 | version = "2.10.0" 2574 | source = "registry+https://github.com/rust-lang/crates.io-index" 2575 | checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" 2576 | dependencies = [ 2577 | "bitflags 1.3.2", 2578 | "core-foundation 0.9.4", 2579 | "core-foundation-sys", 2580 | "libc", 2581 | "security-framework-sys", 2582 | ] 2583 | 2584 | [[package]] 2585 | name = "security-framework" 2586 | version = "3.2.0" 2587 | source = "registry+https://github.com/rust-lang/crates.io-index" 2588 | checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" 2589 | dependencies = [ 2590 | "bitflags 2.6.0", 2591 | "core-foundation 0.10.0", 2592 | "core-foundation-sys", 2593 | "libc", 2594 | "security-framework-sys", 2595 | ] 2596 | 2597 | [[package]] 2598 | name = "security-framework-sys" 2599 | version = "2.14.0" 2600 | source = "registry+https://github.com/rust-lang/crates.io-index" 2601 | checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" 2602 | dependencies = [ 2603 | "core-foundation-sys", 2604 | "libc", 2605 | ] 2606 | 2607 | [[package]] 2608 | name = "serde" 2609 | version = "1.0.226" 2610 | source = "registry+https://github.com/rust-lang/crates.io-index" 2611 | checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd" 2612 | dependencies = [ 2613 | "serde_core", 2614 | "serde_derive", 2615 | ] 2616 | 2617 | [[package]] 2618 | name = "serde-untagged" 2619 | version = "0.1.9" 2620 | source = "registry+https://github.com/rust-lang/crates.io-index" 2621 | checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058" 2622 | dependencies = [ 2623 | "erased-serde", 2624 | "serde", 2625 | "serde_core", 2626 | "typeid", 2627 | ] 2628 | 2629 | [[package]] 2630 | name = "serde_core" 2631 | version = "1.0.226" 2632 | source = "registry+https://github.com/rust-lang/crates.io-index" 2633 | checksum = "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e966a4" 2634 | dependencies = [ 2635 | "serde_derive", 2636 | ] 2637 | 2638 | [[package]] 2639 | name = "serde_derive" 2640 | version = "1.0.226" 2641 | source = "registry+https://github.com/rust-lang/crates.io-index" 2642 | checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33" 2643 | dependencies = [ 2644 | "proc-macro2", 2645 | "quote", 2646 | "syn", 2647 | ] 2648 | 2649 | [[package]] 2650 | name = "serde_json" 2651 | version = "1.0.145" 2652 | source = "registry+https://github.com/rust-lang/crates.io-index" 2653 | checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" 2654 | dependencies = [ 2655 | "itoa", 2656 | "memchr", 2657 | "ryu", 2658 | "serde", 2659 | "serde_core", 2660 | ] 2661 | 2662 | [[package]] 2663 | name = "serde_repr" 2664 | version = "0.1.19" 2665 | source = "registry+https://github.com/rust-lang/crates.io-index" 2666 | checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" 2667 | dependencies = [ 2668 | "proc-macro2", 2669 | "quote", 2670 | "syn", 2671 | ] 2672 | 2673 | [[package]] 2674 | name = "serde_spanned" 2675 | version = "0.6.8" 2676 | source = "registry+https://github.com/rust-lang/crates.io-index" 2677 | checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" 2678 | dependencies = [ 2679 | "serde", 2680 | ] 2681 | 2682 | [[package]] 2683 | name = "serde_spanned" 2684 | version = "1.0.2" 2685 | source = "registry+https://github.com/rust-lang/crates.io-index" 2686 | checksum = "5417783452c2be558477e104686f7de5dae53dba813c28435e0e70f82d9b04ee" 2687 | dependencies = [ 2688 | "serde_core", 2689 | ] 2690 | 2691 | [[package]] 2692 | name = "serde_urlencoded" 2693 | version = "0.7.1" 2694 | source = "registry+https://github.com/rust-lang/crates.io-index" 2695 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 2696 | dependencies = [ 2697 | "form_urlencoded", 2698 | "itoa", 2699 | "ryu", 2700 | "serde", 2701 | ] 2702 | 2703 | [[package]] 2704 | name = "serde_with" 2705 | version = "3.8.1" 2706 | source = "registry+https://github.com/rust-lang/crates.io-index" 2707 | checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" 2708 | dependencies = [ 2709 | "base64 0.22.1", 2710 | "chrono", 2711 | "hex", 2712 | "indexmap 1.9.3", 2713 | "indexmap 2.6.0", 2714 | "serde", 2715 | "serde_derive", 2716 | "serde_json", 2717 | "serde_with_macros", 2718 | "time", 2719 | ] 2720 | 2721 | [[package]] 2722 | name = "serde_with_macros" 2723 | version = "3.8.1" 2724 | source = "registry+https://github.com/rust-lang/crates.io-index" 2725 | checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" 2726 | dependencies = [ 2727 | "darling", 2728 | "proc-macro2", 2729 | "quote", 2730 | "syn", 2731 | ] 2732 | 2733 | [[package]] 2734 | name = "serial_test" 2735 | version = "3.2.0" 2736 | source = "registry+https://github.com/rust-lang/crates.io-index" 2737 | checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" 2738 | dependencies = [ 2739 | "futures", 2740 | "log", 2741 | "once_cell", 2742 | "parking_lot", 2743 | "scc", 2744 | "serial_test_derive", 2745 | ] 2746 | 2747 | [[package]] 2748 | name = "serial_test_derive" 2749 | version = "3.2.0" 2750 | source = "registry+https://github.com/rust-lang/crates.io-index" 2751 | checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" 2752 | dependencies = [ 2753 | "proc-macro2", 2754 | "quote", 2755 | "syn", 2756 | ] 2757 | 2758 | [[package]] 2759 | name = "sha1" 2760 | version = "0.10.6" 2761 | source = "registry+https://github.com/rust-lang/crates.io-index" 2762 | checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" 2763 | dependencies = [ 2764 | "cfg-if", 2765 | "cpufeatures", 2766 | "digest", 2767 | ] 2768 | 2769 | [[package]] 2770 | name = "sha2" 2771 | version = "0.10.8" 2772 | source = "registry+https://github.com/rust-lang/crates.io-index" 2773 | checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" 2774 | dependencies = [ 2775 | "cfg-if", 2776 | "cpufeatures", 2777 | "digest", 2778 | ] 2779 | 2780 | [[package]] 2781 | name = "shlex" 2782 | version = "1.3.0" 2783 | source = "registry+https://github.com/rust-lang/crates.io-index" 2784 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 2785 | 2786 | [[package]] 2787 | name = "signal-hook-registry" 2788 | version = "1.4.1" 2789 | source = "registry+https://github.com/rust-lang/crates.io-index" 2790 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" 2791 | dependencies = [ 2792 | "libc", 2793 | ] 2794 | 2795 | [[package]] 2796 | name = "simd-adler32" 2797 | version = "0.3.7" 2798 | source = "registry+https://github.com/rust-lang/crates.io-index" 2799 | checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" 2800 | 2801 | [[package]] 2802 | name = "siphasher" 2803 | version = "0.3.11" 2804 | source = "registry+https://github.com/rust-lang/crates.io-index" 2805 | checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" 2806 | 2807 | [[package]] 2808 | name = "slab" 2809 | version = "0.4.9" 2810 | source = "registry+https://github.com/rust-lang/crates.io-index" 2811 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 2812 | dependencies = [ 2813 | "autocfg", 2814 | ] 2815 | 2816 | [[package]] 2817 | name = "smallvec" 2818 | version = "1.13.2" 2819 | source = "registry+https://github.com/rust-lang/crates.io-index" 2820 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 2821 | 2822 | [[package]] 2823 | name = "socket2" 2824 | version = "0.5.10" 2825 | source = "registry+https://github.com/rust-lang/crates.io-index" 2826 | checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" 2827 | dependencies = [ 2828 | "libc", 2829 | "windows-sys 0.52.0", 2830 | ] 2831 | 2832 | [[package]] 2833 | name = "socket2" 2834 | version = "0.6.0" 2835 | source = "registry+https://github.com/rust-lang/crates.io-index" 2836 | checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" 2837 | dependencies = [ 2838 | "libc", 2839 | "windows-sys 0.59.0", 2840 | ] 2841 | 2842 | [[package]] 2843 | name = "spin" 2844 | version = "0.9.8" 2845 | source = "registry+https://github.com/rust-lang/crates.io-index" 2846 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 2847 | 2848 | [[package]] 2849 | name = "stable_deref_trait" 2850 | version = "1.2.0" 2851 | source = "registry+https://github.com/rust-lang/crates.io-index" 2852 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 2853 | 2854 | [[package]] 2855 | name = "starter" 2856 | version = "0.5.6" 2857 | dependencies = [ 2858 | "actix-web", 2859 | "anyhow", 2860 | "application", 2861 | "async-trait", 2862 | "ctor", 2863 | "domain", 2864 | "dotenv", 2865 | "env_logger", 2866 | "infrastructure", 2867 | "log", 2868 | "presentation", 2869 | "reqwest", 2870 | "serial_test", 2871 | "testcontainers", 2872 | "testcontainers-modules", 2873 | "tokio", 2874 | "utoipa", 2875 | "utoipa-actix-web", 2876 | "utoipa-swagger-ui", 2877 | "uuid", 2878 | ] 2879 | 2880 | [[package]] 2881 | name = "stringprep" 2882 | version = "0.1.5" 2883 | source = "registry+https://github.com/rust-lang/crates.io-index" 2884 | checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" 2885 | dependencies = [ 2886 | "unicode-bidi", 2887 | "unicode-normalization", 2888 | "unicode-properties", 2889 | ] 2890 | 2891 | [[package]] 2892 | name = "strsim" 2893 | version = "0.11.1" 2894 | source = "registry+https://github.com/rust-lang/crates.io-index" 2895 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 2896 | 2897 | [[package]] 2898 | name = "structmeta" 2899 | version = "0.3.0" 2900 | source = "registry+https://github.com/rust-lang/crates.io-index" 2901 | checksum = "2e1575d8d40908d70f6fd05537266b90ae71b15dbbe7a8b7dffa2b759306d329" 2902 | dependencies = [ 2903 | "proc-macro2", 2904 | "quote", 2905 | "structmeta-derive", 2906 | "syn", 2907 | ] 2908 | 2909 | [[package]] 2910 | name = "structmeta-derive" 2911 | version = "0.3.0" 2912 | source = "registry+https://github.com/rust-lang/crates.io-index" 2913 | checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc" 2914 | dependencies = [ 2915 | "proc-macro2", 2916 | "quote", 2917 | "syn", 2918 | ] 2919 | 2920 | [[package]] 2921 | name = "subtle" 2922 | version = "2.6.1" 2923 | source = "registry+https://github.com/rust-lang/crates.io-index" 2924 | checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 2925 | 2926 | [[package]] 2927 | name = "syn" 2928 | version = "2.0.90" 2929 | source = "registry+https://github.com/rust-lang/crates.io-index" 2930 | checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" 2931 | dependencies = [ 2932 | "proc-macro2", 2933 | "quote", 2934 | "unicode-ident", 2935 | ] 2936 | 2937 | [[package]] 2938 | name = "sync_wrapper" 2939 | version = "1.0.1" 2940 | source = "registry+https://github.com/rust-lang/crates.io-index" 2941 | checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" 2942 | dependencies = [ 2943 | "futures-core", 2944 | ] 2945 | 2946 | [[package]] 2947 | name = "synstructure" 2948 | version = "0.13.1" 2949 | source = "registry+https://github.com/rust-lang/crates.io-index" 2950 | checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" 2951 | dependencies = [ 2952 | "proc-macro2", 2953 | "quote", 2954 | "syn", 2955 | ] 2956 | 2957 | [[package]] 2958 | name = "system-configuration" 2959 | version = "0.6.1" 2960 | source = "registry+https://github.com/rust-lang/crates.io-index" 2961 | checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" 2962 | dependencies = [ 2963 | "bitflags 2.6.0", 2964 | "core-foundation 0.9.4", 2965 | "system-configuration-sys", 2966 | ] 2967 | 2968 | [[package]] 2969 | name = "system-configuration-sys" 2970 | version = "0.6.0" 2971 | source = "registry+https://github.com/rust-lang/crates.io-index" 2972 | checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" 2973 | dependencies = [ 2974 | "core-foundation-sys", 2975 | "libc", 2976 | ] 2977 | 2978 | [[package]] 2979 | name = "tempfile" 2980 | version = "3.10.1" 2981 | source = "registry+https://github.com/rust-lang/crates.io-index" 2982 | checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" 2983 | dependencies = [ 2984 | "cfg-if", 2985 | "fastrand", 2986 | "rustix", 2987 | "windows-sys 0.52.0", 2988 | ] 2989 | 2990 | [[package]] 2991 | name = "testcontainers" 2992 | version = "0.23.3" 2993 | source = "registry+https://github.com/rust-lang/crates.io-index" 2994 | checksum = "59a4f01f39bb10fc2a5ab23eb0d888b1e2bb168c157f61a1b98e6c501c639c74" 2995 | dependencies = [ 2996 | "async-trait", 2997 | "bollard", 2998 | "bollard-stubs", 2999 | "bytes", 3000 | "docker_credential", 3001 | "either", 3002 | "etcetera", 3003 | "futures", 3004 | "log", 3005 | "memchr", 3006 | "parse-display", 3007 | "pin-project-lite", 3008 | "serde", 3009 | "serde_json", 3010 | "serde_with", 3011 | "thiserror 2.0.12", 3012 | "tokio", 3013 | "tokio-stream", 3014 | "tokio-tar", 3015 | "tokio-util", 3016 | "url", 3017 | ] 3018 | 3019 | [[package]] 3020 | name = "testcontainers-modules" 3021 | version = "0.11.6" 3022 | source = "registry+https://github.com/rust-lang/crates.io-index" 3023 | checksum = "4d43ed4e8f58424c3a2c6c56dbea6643c3c23e8666a34df13c54f0a184e6c707" 3024 | dependencies = [ 3025 | "testcontainers", 3026 | ] 3027 | 3028 | [[package]] 3029 | name = "thiserror" 3030 | version = "1.0.68" 3031 | source = "registry+https://github.com/rust-lang/crates.io-index" 3032 | checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" 3033 | dependencies = [ 3034 | "thiserror-impl 1.0.68", 3035 | ] 3036 | 3037 | [[package]] 3038 | name = "thiserror" 3039 | version = "2.0.12" 3040 | source = "registry+https://github.com/rust-lang/crates.io-index" 3041 | checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" 3042 | dependencies = [ 3043 | "thiserror-impl 2.0.12", 3044 | ] 3045 | 3046 | [[package]] 3047 | name = "thiserror-impl" 3048 | version = "1.0.68" 3049 | source = "registry+https://github.com/rust-lang/crates.io-index" 3050 | checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" 3051 | dependencies = [ 3052 | "proc-macro2", 3053 | "quote", 3054 | "syn", 3055 | ] 3056 | 3057 | [[package]] 3058 | name = "thiserror-impl" 3059 | version = "2.0.12" 3060 | source = "registry+https://github.com/rust-lang/crates.io-index" 3061 | checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" 3062 | dependencies = [ 3063 | "proc-macro2", 3064 | "quote", 3065 | "syn", 3066 | ] 3067 | 3068 | [[package]] 3069 | name = "time" 3070 | version = "0.3.36" 3071 | source = "registry+https://github.com/rust-lang/crates.io-index" 3072 | checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" 3073 | dependencies = [ 3074 | "deranged", 3075 | "itoa", 3076 | "num-conv", 3077 | "powerfmt", 3078 | "serde", 3079 | "time-core", 3080 | "time-macros", 3081 | ] 3082 | 3083 | [[package]] 3084 | name = "time-core" 3085 | version = "0.1.2" 3086 | source = "registry+https://github.com/rust-lang/crates.io-index" 3087 | checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" 3088 | 3089 | [[package]] 3090 | name = "time-macros" 3091 | version = "0.2.18" 3092 | source = "registry+https://github.com/rust-lang/crates.io-index" 3093 | checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" 3094 | dependencies = [ 3095 | "num-conv", 3096 | "time-core", 3097 | ] 3098 | 3099 | [[package]] 3100 | name = "tiny-keccak" 3101 | version = "2.0.2" 3102 | source = "registry+https://github.com/rust-lang/crates.io-index" 3103 | checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" 3104 | dependencies = [ 3105 | "crunchy", 3106 | ] 3107 | 3108 | [[package]] 3109 | name = "tinystr" 3110 | version = "0.7.6" 3111 | source = "registry+https://github.com/rust-lang/crates.io-index" 3112 | checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" 3113 | dependencies = [ 3114 | "displaydoc", 3115 | "zerovec", 3116 | ] 3117 | 3118 | [[package]] 3119 | name = "tinyvec" 3120 | version = "1.8.0" 3121 | source = "registry+https://github.com/rust-lang/crates.io-index" 3122 | checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" 3123 | dependencies = [ 3124 | "tinyvec_macros", 3125 | ] 3126 | 3127 | [[package]] 3128 | name = "tinyvec_macros" 3129 | version = "0.1.1" 3130 | source = "registry+https://github.com/rust-lang/crates.io-index" 3131 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 3132 | 3133 | [[package]] 3134 | name = "tokio" 3135 | version = "1.47.1" 3136 | source = "registry+https://github.com/rust-lang/crates.io-index" 3137 | checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" 3138 | dependencies = [ 3139 | "backtrace", 3140 | "bytes", 3141 | "io-uring", 3142 | "libc", 3143 | "mio", 3144 | "parking_lot", 3145 | "pin-project-lite", 3146 | "signal-hook-registry", 3147 | "slab", 3148 | "socket2 0.6.0", 3149 | "tokio-macros", 3150 | "windows-sys 0.59.0", 3151 | ] 3152 | 3153 | [[package]] 3154 | name = "tokio-macros" 3155 | version = "2.5.0" 3156 | source = "registry+https://github.com/rust-lang/crates.io-index" 3157 | checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" 3158 | dependencies = [ 3159 | "proc-macro2", 3160 | "quote", 3161 | "syn", 3162 | ] 3163 | 3164 | [[package]] 3165 | name = "tokio-native-tls" 3166 | version = "0.3.1" 3167 | source = "registry+https://github.com/rust-lang/crates.io-index" 3168 | checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" 3169 | dependencies = [ 3170 | "native-tls", 3171 | "tokio", 3172 | ] 3173 | 3174 | [[package]] 3175 | name = "tokio-postgres" 3176 | version = "0.7.13" 3177 | source = "registry+https://github.com/rust-lang/crates.io-index" 3178 | checksum = "6c95d533c83082bb6490e0189acaa0bbeef9084e60471b696ca6988cd0541fb0" 3179 | dependencies = [ 3180 | "async-trait", 3181 | "byteorder", 3182 | "bytes", 3183 | "fallible-iterator", 3184 | "futures-channel", 3185 | "futures-util", 3186 | "log", 3187 | "parking_lot", 3188 | "percent-encoding", 3189 | "phf", 3190 | "pin-project-lite", 3191 | "postgres-protocol", 3192 | "postgres-types", 3193 | "rand", 3194 | "socket2 0.5.10", 3195 | "tokio", 3196 | "tokio-util", 3197 | "whoami", 3198 | ] 3199 | 3200 | [[package]] 3201 | name = "tokio-rustls" 3202 | version = "0.26.0" 3203 | source = "registry+https://github.com/rust-lang/crates.io-index" 3204 | checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" 3205 | dependencies = [ 3206 | "rustls", 3207 | "rustls-pki-types", 3208 | "tokio", 3209 | ] 3210 | 3211 | [[package]] 3212 | name = "tokio-stream" 3213 | version = "0.1.15" 3214 | source = "registry+https://github.com/rust-lang/crates.io-index" 3215 | checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" 3216 | dependencies = [ 3217 | "futures-core", 3218 | "pin-project-lite", 3219 | "tokio", 3220 | ] 3221 | 3222 | [[package]] 3223 | name = "tokio-tar" 3224 | version = "0.3.1" 3225 | source = "registry+https://github.com/rust-lang/crates.io-index" 3226 | checksum = "9d5714c010ca3e5c27114c1cdeb9d14641ace49874aa5626d7149e47aedace75" 3227 | dependencies = [ 3228 | "filetime", 3229 | "futures-core", 3230 | "libc", 3231 | "redox_syscall 0.3.5", 3232 | "tokio", 3233 | "tokio-stream", 3234 | "xattr", 3235 | ] 3236 | 3237 | [[package]] 3238 | name = "tokio-util" 3239 | version = "0.7.12" 3240 | source = "registry+https://github.com/rust-lang/crates.io-index" 3241 | checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" 3242 | dependencies = [ 3243 | "bytes", 3244 | "futures-core", 3245 | "futures-sink", 3246 | "pin-project-lite", 3247 | "tokio", 3248 | ] 3249 | 3250 | [[package]] 3251 | name = "toml" 3252 | version = "0.8.19" 3253 | source = "registry+https://github.com/rust-lang/crates.io-index" 3254 | checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" 3255 | dependencies = [ 3256 | "serde", 3257 | "serde_spanned 0.6.8", 3258 | "toml_datetime 0.6.8", 3259 | "toml_edit", 3260 | ] 3261 | 3262 | [[package]] 3263 | name = "toml" 3264 | version = "0.9.7" 3265 | source = "registry+https://github.com/rust-lang/crates.io-index" 3266 | checksum = "00e5e5d9bf2475ac9d4f0d9edab68cc573dc2fd644b0dba36b0c30a92dd9eaa0" 3267 | dependencies = [ 3268 | "serde_core", 3269 | "serde_spanned 1.0.2", 3270 | "toml_datetime 0.7.2", 3271 | "toml_parser", 3272 | "winnow 0.7.13", 3273 | ] 3274 | 3275 | [[package]] 3276 | name = "toml_datetime" 3277 | version = "0.6.8" 3278 | source = "registry+https://github.com/rust-lang/crates.io-index" 3279 | checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" 3280 | dependencies = [ 3281 | "serde", 3282 | ] 3283 | 3284 | [[package]] 3285 | name = "toml_datetime" 3286 | version = "0.7.2" 3287 | source = "registry+https://github.com/rust-lang/crates.io-index" 3288 | checksum = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1" 3289 | dependencies = [ 3290 | "serde_core", 3291 | ] 3292 | 3293 | [[package]] 3294 | name = "toml_edit" 3295 | version = "0.22.22" 3296 | source = "registry+https://github.com/rust-lang/crates.io-index" 3297 | checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" 3298 | dependencies = [ 3299 | "indexmap 2.6.0", 3300 | "serde", 3301 | "serde_spanned 0.6.8", 3302 | "toml_datetime 0.6.8", 3303 | "winnow 0.6.20", 3304 | ] 3305 | 3306 | [[package]] 3307 | name = "toml_parser" 3308 | version = "1.0.3" 3309 | source = "registry+https://github.com/rust-lang/crates.io-index" 3310 | checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627" 3311 | dependencies = [ 3312 | "winnow 0.7.13", 3313 | ] 3314 | 3315 | [[package]] 3316 | name = "tower" 3317 | version = "0.5.2" 3318 | source = "registry+https://github.com/rust-lang/crates.io-index" 3319 | checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" 3320 | dependencies = [ 3321 | "futures-core", 3322 | "futures-util", 3323 | "pin-project-lite", 3324 | "sync_wrapper", 3325 | "tokio", 3326 | "tower-layer", 3327 | "tower-service", 3328 | ] 3329 | 3330 | [[package]] 3331 | name = "tower-http" 3332 | version = "0.6.5" 3333 | source = "registry+https://github.com/rust-lang/crates.io-index" 3334 | checksum = "5cc2d9e086a412a451384326f521c8123a99a466b329941a9403696bff9b0da2" 3335 | dependencies = [ 3336 | "bitflags 2.6.0", 3337 | "bytes", 3338 | "futures-util", 3339 | "http 1.3.1", 3340 | "http-body", 3341 | "iri-string", 3342 | "pin-project-lite", 3343 | "tower", 3344 | "tower-layer", 3345 | "tower-service", 3346 | ] 3347 | 3348 | [[package]] 3349 | name = "tower-layer" 3350 | version = "0.3.3" 3351 | source = "registry+https://github.com/rust-lang/crates.io-index" 3352 | checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 3353 | 3354 | [[package]] 3355 | name = "tower-service" 3356 | version = "0.3.3" 3357 | source = "registry+https://github.com/rust-lang/crates.io-index" 3358 | checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 3359 | 3360 | [[package]] 3361 | name = "tracing" 3362 | version = "0.1.41" 3363 | source = "registry+https://github.com/rust-lang/crates.io-index" 3364 | checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 3365 | dependencies = [ 3366 | "log", 3367 | "pin-project-lite", 3368 | "tracing-attributes", 3369 | "tracing-core", 3370 | ] 3371 | 3372 | [[package]] 3373 | name = "tracing-attributes" 3374 | version = "0.1.28" 3375 | source = "registry+https://github.com/rust-lang/crates.io-index" 3376 | checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" 3377 | dependencies = [ 3378 | "proc-macro2", 3379 | "quote", 3380 | "syn", 3381 | ] 3382 | 3383 | [[package]] 3384 | name = "tracing-core" 3385 | version = "0.1.33" 3386 | source = "registry+https://github.com/rust-lang/crates.io-index" 3387 | checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" 3388 | dependencies = [ 3389 | "once_cell", 3390 | ] 3391 | 3392 | [[package]] 3393 | name = "trim-in-place" 3394 | version = "0.1.7" 3395 | source = "registry+https://github.com/rust-lang/crates.io-index" 3396 | checksum = "343e926fc669bc8cde4fa3129ab681c63671bae288b1f1081ceee6d9d37904fc" 3397 | 3398 | [[package]] 3399 | name = "try-lock" 3400 | version = "0.2.5" 3401 | source = "registry+https://github.com/rust-lang/crates.io-index" 3402 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 3403 | 3404 | [[package]] 3405 | name = "typeid" 3406 | version = "1.0.3" 3407 | source = "registry+https://github.com/rust-lang/crates.io-index" 3408 | checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" 3409 | 3410 | [[package]] 3411 | name = "typenum" 3412 | version = "1.17.0" 3413 | source = "registry+https://github.com/rust-lang/crates.io-index" 3414 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" 3415 | 3416 | [[package]] 3417 | name = "ucd-trie" 3418 | version = "0.1.7" 3419 | source = "registry+https://github.com/rust-lang/crates.io-index" 3420 | checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" 3421 | 3422 | [[package]] 3423 | name = "unicase" 3424 | version = "2.8.0" 3425 | source = "registry+https://github.com/rust-lang/crates.io-index" 3426 | checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" 3427 | 3428 | [[package]] 3429 | name = "unicode-bidi" 3430 | version = "0.3.17" 3431 | source = "registry+https://github.com/rust-lang/crates.io-index" 3432 | checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" 3433 | 3434 | [[package]] 3435 | name = "unicode-ident" 3436 | version = "1.0.13" 3437 | source = "registry+https://github.com/rust-lang/crates.io-index" 3438 | checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" 3439 | 3440 | [[package]] 3441 | name = "unicode-normalization" 3442 | version = "0.1.24" 3443 | source = "registry+https://github.com/rust-lang/crates.io-index" 3444 | checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" 3445 | dependencies = [ 3446 | "tinyvec", 3447 | ] 3448 | 3449 | [[package]] 3450 | name = "unicode-properties" 3451 | version = "0.1.3" 3452 | source = "registry+https://github.com/rust-lang/crates.io-index" 3453 | checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" 3454 | 3455 | [[package]] 3456 | name = "unicode-segmentation" 3457 | version = "1.12.0" 3458 | source = "registry+https://github.com/rust-lang/crates.io-index" 3459 | checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" 3460 | 3461 | [[package]] 3462 | name = "unicode-xid" 3463 | version = "0.2.6" 3464 | source = "registry+https://github.com/rust-lang/crates.io-index" 3465 | checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" 3466 | 3467 | [[package]] 3468 | name = "untrusted" 3469 | version = "0.9.0" 3470 | source = "registry+https://github.com/rust-lang/crates.io-index" 3471 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 3472 | 3473 | [[package]] 3474 | name = "url" 3475 | version = "2.5.4" 3476 | source = "registry+https://github.com/rust-lang/crates.io-index" 3477 | checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" 3478 | dependencies = [ 3479 | "form_urlencoded", 3480 | "idna", 3481 | "percent-encoding", 3482 | "serde", 3483 | ] 3484 | 3485 | [[package]] 3486 | name = "utf16_iter" 3487 | version = "1.0.5" 3488 | source = "registry+https://github.com/rust-lang/crates.io-index" 3489 | checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" 3490 | 3491 | [[package]] 3492 | name = "utf8_iter" 3493 | version = "1.0.4" 3494 | source = "registry+https://github.com/rust-lang/crates.io-index" 3495 | checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 3496 | 3497 | [[package]] 3498 | name = "utf8parse" 3499 | version = "0.2.2" 3500 | source = "registry+https://github.com/rust-lang/crates.io-index" 3501 | checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 3502 | 3503 | [[package]] 3504 | name = "utoipa" 3505 | version = "5.4.0" 3506 | source = "registry+https://github.com/rust-lang/crates.io-index" 3507 | checksum = "2fcc29c80c21c31608227e0912b2d7fddba57ad76b606890627ba8ee7964e993" 3508 | dependencies = [ 3509 | "indexmap 2.6.0", 3510 | "serde", 3511 | "serde_json", 3512 | "utoipa-gen", 3513 | ] 3514 | 3515 | [[package]] 3516 | name = "utoipa-actix-web" 3517 | version = "0.1.2" 3518 | source = "registry+https://github.com/rust-lang/crates.io-index" 3519 | checksum = "b7eda9c23c05af0fb812f6a177514047331dac4851a2c8e9c4b895d6d826967f" 3520 | dependencies = [ 3521 | "actix-service", 3522 | "actix-web", 3523 | "utoipa", 3524 | ] 3525 | 3526 | [[package]] 3527 | name = "utoipa-gen" 3528 | version = "5.4.0" 3529 | source = "registry+https://github.com/rust-lang/crates.io-index" 3530 | checksum = "6d79d08d92ab8af4c5e8a6da20c47ae3f61a0f1dabc1997cdf2d082b757ca08b" 3531 | dependencies = [ 3532 | "proc-macro2", 3533 | "quote", 3534 | "regex", 3535 | "syn", 3536 | "uuid", 3537 | ] 3538 | 3539 | [[package]] 3540 | name = "utoipa-swagger-ui" 3541 | version = "8.1.1" 3542 | source = "registry+https://github.com/rust-lang/crates.io-index" 3543 | checksum = "040cad8bd8de63f3d028e08e5b39be49d68f8a646e99f4aea2e2d4d82c34b21f" 3544 | dependencies = [ 3545 | "actix-web", 3546 | "base64 0.22.1", 3547 | "mime_guess", 3548 | "regex", 3549 | "rust-embed", 3550 | "serde", 3551 | "serde_json", 3552 | "url", 3553 | "utoipa", 3554 | "zip", 3555 | ] 3556 | 3557 | [[package]] 3558 | name = "uuid" 3559 | version = "1.18.1" 3560 | source = "registry+https://github.com/rust-lang/crates.io-index" 3561 | checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" 3562 | dependencies = [ 3563 | "getrandom 0.3.1", 3564 | "js-sys", 3565 | "serde", 3566 | "wasm-bindgen", 3567 | ] 3568 | 3569 | [[package]] 3570 | name = "vcpkg" 3571 | version = "0.2.15" 3572 | source = "registry+https://github.com/rust-lang/crates.io-index" 3573 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 3574 | 3575 | [[package]] 3576 | name = "version_check" 3577 | version = "0.9.5" 3578 | source = "registry+https://github.com/rust-lang/crates.io-index" 3579 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 3580 | 3581 | [[package]] 3582 | name = "walkdir" 3583 | version = "2.5.0" 3584 | source = "registry+https://github.com/rust-lang/crates.io-index" 3585 | checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 3586 | dependencies = [ 3587 | "same-file", 3588 | "winapi-util", 3589 | ] 3590 | 3591 | [[package]] 3592 | name = "want" 3593 | version = "0.3.1" 3594 | source = "registry+https://github.com/rust-lang/crates.io-index" 3595 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 3596 | dependencies = [ 3597 | "try-lock", 3598 | ] 3599 | 3600 | [[package]] 3601 | name = "wasi" 3602 | version = "0.11.0+wasi-snapshot-preview1" 3603 | source = "registry+https://github.com/rust-lang/crates.io-index" 3604 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 3605 | 3606 | [[package]] 3607 | name = "wasi" 3608 | version = "0.13.3+wasi-0.2.2" 3609 | source = "registry+https://github.com/rust-lang/crates.io-index" 3610 | checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" 3611 | dependencies = [ 3612 | "wit-bindgen-rt", 3613 | ] 3614 | 3615 | [[package]] 3616 | name = "wasite" 3617 | version = "0.1.0" 3618 | source = "registry+https://github.com/rust-lang/crates.io-index" 3619 | checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" 3620 | 3621 | [[package]] 3622 | name = "wasm-bindgen" 3623 | version = "0.2.100" 3624 | source = "registry+https://github.com/rust-lang/crates.io-index" 3625 | checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 3626 | dependencies = [ 3627 | "cfg-if", 3628 | "once_cell", 3629 | "rustversion", 3630 | "wasm-bindgen-macro", 3631 | ] 3632 | 3633 | [[package]] 3634 | name = "wasm-bindgen-backend" 3635 | version = "0.2.100" 3636 | source = "registry+https://github.com/rust-lang/crates.io-index" 3637 | checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 3638 | dependencies = [ 3639 | "bumpalo", 3640 | "log", 3641 | "proc-macro2", 3642 | "quote", 3643 | "syn", 3644 | "wasm-bindgen-shared", 3645 | ] 3646 | 3647 | [[package]] 3648 | name = "wasm-bindgen-futures" 3649 | version = "0.4.42" 3650 | source = "registry+https://github.com/rust-lang/crates.io-index" 3651 | checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" 3652 | dependencies = [ 3653 | "cfg-if", 3654 | "js-sys", 3655 | "wasm-bindgen", 3656 | "web-sys", 3657 | ] 3658 | 3659 | [[package]] 3660 | name = "wasm-bindgen-macro" 3661 | version = "0.2.100" 3662 | source = "registry+https://github.com/rust-lang/crates.io-index" 3663 | checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 3664 | dependencies = [ 3665 | "quote", 3666 | "wasm-bindgen-macro-support", 3667 | ] 3668 | 3669 | [[package]] 3670 | name = "wasm-bindgen-macro-support" 3671 | version = "0.2.100" 3672 | source = "registry+https://github.com/rust-lang/crates.io-index" 3673 | checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 3674 | dependencies = [ 3675 | "proc-macro2", 3676 | "quote", 3677 | "syn", 3678 | "wasm-bindgen-backend", 3679 | "wasm-bindgen-shared", 3680 | ] 3681 | 3682 | [[package]] 3683 | name = "wasm-bindgen-shared" 3684 | version = "0.2.100" 3685 | source = "registry+https://github.com/rust-lang/crates.io-index" 3686 | checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 3687 | dependencies = [ 3688 | "unicode-ident", 3689 | ] 3690 | 3691 | [[package]] 3692 | name = "web-sys" 3693 | version = "0.3.69" 3694 | source = "registry+https://github.com/rust-lang/crates.io-index" 3695 | checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" 3696 | dependencies = [ 3697 | "js-sys", 3698 | "wasm-bindgen", 3699 | ] 3700 | 3701 | [[package]] 3702 | name = "whoami" 3703 | version = "1.5.1" 3704 | source = "registry+https://github.com/rust-lang/crates.io-index" 3705 | checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" 3706 | dependencies = [ 3707 | "redox_syscall 0.4.1", 3708 | "wasite", 3709 | "web-sys", 3710 | ] 3711 | 3712 | [[package]] 3713 | name = "winapi" 3714 | version = "0.3.9" 3715 | source = "registry+https://github.com/rust-lang/crates.io-index" 3716 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 3717 | dependencies = [ 3718 | "winapi-i686-pc-windows-gnu", 3719 | "winapi-x86_64-pc-windows-gnu", 3720 | ] 3721 | 3722 | [[package]] 3723 | name = "winapi-i686-pc-windows-gnu" 3724 | version = "0.4.0" 3725 | source = "registry+https://github.com/rust-lang/crates.io-index" 3726 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 3727 | 3728 | [[package]] 3729 | name = "winapi-util" 3730 | version = "0.1.6" 3731 | source = "registry+https://github.com/rust-lang/crates.io-index" 3732 | checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" 3733 | dependencies = [ 3734 | "winapi", 3735 | ] 3736 | 3737 | [[package]] 3738 | name = "winapi-x86_64-pc-windows-gnu" 3739 | version = "0.4.0" 3740 | source = "registry+https://github.com/rust-lang/crates.io-index" 3741 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 3742 | 3743 | [[package]] 3744 | name = "windows-core" 3745 | version = "0.52.0" 3746 | source = "registry+https://github.com/rust-lang/crates.io-index" 3747 | checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" 3748 | dependencies = [ 3749 | "windows-targets 0.52.6", 3750 | ] 3751 | 3752 | [[package]] 3753 | name = "windows-link" 3754 | version = "0.1.1" 3755 | source = "registry+https://github.com/rust-lang/crates.io-index" 3756 | checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" 3757 | 3758 | [[package]] 3759 | name = "windows-registry" 3760 | version = "0.4.0" 3761 | source = "registry+https://github.com/rust-lang/crates.io-index" 3762 | checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" 3763 | dependencies = [ 3764 | "windows-result", 3765 | "windows-strings", 3766 | "windows-targets 0.53.0", 3767 | ] 3768 | 3769 | [[package]] 3770 | name = "windows-result" 3771 | version = "0.3.2" 3772 | source = "registry+https://github.com/rust-lang/crates.io-index" 3773 | checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" 3774 | dependencies = [ 3775 | "windows-link", 3776 | ] 3777 | 3778 | [[package]] 3779 | name = "windows-strings" 3780 | version = "0.3.1" 3781 | source = "registry+https://github.com/rust-lang/crates.io-index" 3782 | checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" 3783 | dependencies = [ 3784 | "windows-link", 3785 | ] 3786 | 3787 | [[package]] 3788 | name = "windows-sys" 3789 | version = "0.48.0" 3790 | source = "registry+https://github.com/rust-lang/crates.io-index" 3791 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 3792 | dependencies = [ 3793 | "windows-targets 0.48.5", 3794 | ] 3795 | 3796 | [[package]] 3797 | name = "windows-sys" 3798 | version = "0.52.0" 3799 | source = "registry+https://github.com/rust-lang/crates.io-index" 3800 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 3801 | dependencies = [ 3802 | "windows-targets 0.52.6", 3803 | ] 3804 | 3805 | [[package]] 3806 | name = "windows-sys" 3807 | version = "0.59.0" 3808 | source = "registry+https://github.com/rust-lang/crates.io-index" 3809 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 3810 | dependencies = [ 3811 | "windows-targets 0.52.6", 3812 | ] 3813 | 3814 | [[package]] 3815 | name = "windows-targets" 3816 | version = "0.48.5" 3817 | source = "registry+https://github.com/rust-lang/crates.io-index" 3818 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 3819 | dependencies = [ 3820 | "windows_aarch64_gnullvm 0.48.5", 3821 | "windows_aarch64_msvc 0.48.5", 3822 | "windows_i686_gnu 0.48.5", 3823 | "windows_i686_msvc 0.48.5", 3824 | "windows_x86_64_gnu 0.48.5", 3825 | "windows_x86_64_gnullvm 0.48.5", 3826 | "windows_x86_64_msvc 0.48.5", 3827 | ] 3828 | 3829 | [[package]] 3830 | name = "windows-targets" 3831 | version = "0.52.6" 3832 | source = "registry+https://github.com/rust-lang/crates.io-index" 3833 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 3834 | dependencies = [ 3835 | "windows_aarch64_gnullvm 0.52.6", 3836 | "windows_aarch64_msvc 0.52.6", 3837 | "windows_i686_gnu 0.52.6", 3838 | "windows_i686_gnullvm 0.52.6", 3839 | "windows_i686_msvc 0.52.6", 3840 | "windows_x86_64_gnu 0.52.6", 3841 | "windows_x86_64_gnullvm 0.52.6", 3842 | "windows_x86_64_msvc 0.52.6", 3843 | ] 3844 | 3845 | [[package]] 3846 | name = "windows-targets" 3847 | version = "0.53.0" 3848 | source = "registry+https://github.com/rust-lang/crates.io-index" 3849 | checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" 3850 | dependencies = [ 3851 | "windows_aarch64_gnullvm 0.53.0", 3852 | "windows_aarch64_msvc 0.53.0", 3853 | "windows_i686_gnu 0.53.0", 3854 | "windows_i686_gnullvm 0.53.0", 3855 | "windows_i686_msvc 0.53.0", 3856 | "windows_x86_64_gnu 0.53.0", 3857 | "windows_x86_64_gnullvm 0.53.0", 3858 | "windows_x86_64_msvc 0.53.0", 3859 | ] 3860 | 3861 | [[package]] 3862 | name = "windows_aarch64_gnullvm" 3863 | version = "0.48.5" 3864 | source = "registry+https://github.com/rust-lang/crates.io-index" 3865 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 3866 | 3867 | [[package]] 3868 | name = "windows_aarch64_gnullvm" 3869 | version = "0.52.6" 3870 | source = "registry+https://github.com/rust-lang/crates.io-index" 3871 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 3872 | 3873 | [[package]] 3874 | name = "windows_aarch64_gnullvm" 3875 | version = "0.53.0" 3876 | source = "registry+https://github.com/rust-lang/crates.io-index" 3877 | checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" 3878 | 3879 | [[package]] 3880 | name = "windows_aarch64_msvc" 3881 | version = "0.48.5" 3882 | source = "registry+https://github.com/rust-lang/crates.io-index" 3883 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 3884 | 3885 | [[package]] 3886 | name = "windows_aarch64_msvc" 3887 | version = "0.52.6" 3888 | source = "registry+https://github.com/rust-lang/crates.io-index" 3889 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 3890 | 3891 | [[package]] 3892 | name = "windows_aarch64_msvc" 3893 | version = "0.53.0" 3894 | source = "registry+https://github.com/rust-lang/crates.io-index" 3895 | checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" 3896 | 3897 | [[package]] 3898 | name = "windows_i686_gnu" 3899 | version = "0.48.5" 3900 | source = "registry+https://github.com/rust-lang/crates.io-index" 3901 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 3902 | 3903 | [[package]] 3904 | name = "windows_i686_gnu" 3905 | version = "0.52.6" 3906 | source = "registry+https://github.com/rust-lang/crates.io-index" 3907 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 3908 | 3909 | [[package]] 3910 | name = "windows_i686_gnu" 3911 | version = "0.53.0" 3912 | source = "registry+https://github.com/rust-lang/crates.io-index" 3913 | checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" 3914 | 3915 | [[package]] 3916 | name = "windows_i686_gnullvm" 3917 | version = "0.52.6" 3918 | source = "registry+https://github.com/rust-lang/crates.io-index" 3919 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 3920 | 3921 | [[package]] 3922 | name = "windows_i686_gnullvm" 3923 | version = "0.53.0" 3924 | source = "registry+https://github.com/rust-lang/crates.io-index" 3925 | checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" 3926 | 3927 | [[package]] 3928 | name = "windows_i686_msvc" 3929 | version = "0.48.5" 3930 | source = "registry+https://github.com/rust-lang/crates.io-index" 3931 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 3932 | 3933 | [[package]] 3934 | name = "windows_i686_msvc" 3935 | version = "0.52.6" 3936 | source = "registry+https://github.com/rust-lang/crates.io-index" 3937 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 3938 | 3939 | [[package]] 3940 | name = "windows_i686_msvc" 3941 | version = "0.53.0" 3942 | source = "registry+https://github.com/rust-lang/crates.io-index" 3943 | checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" 3944 | 3945 | [[package]] 3946 | name = "windows_x86_64_gnu" 3947 | version = "0.48.5" 3948 | source = "registry+https://github.com/rust-lang/crates.io-index" 3949 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 3950 | 3951 | [[package]] 3952 | name = "windows_x86_64_gnu" 3953 | version = "0.52.6" 3954 | source = "registry+https://github.com/rust-lang/crates.io-index" 3955 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 3956 | 3957 | [[package]] 3958 | name = "windows_x86_64_gnu" 3959 | version = "0.53.0" 3960 | source = "registry+https://github.com/rust-lang/crates.io-index" 3961 | checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" 3962 | 3963 | [[package]] 3964 | name = "windows_x86_64_gnullvm" 3965 | version = "0.48.5" 3966 | source = "registry+https://github.com/rust-lang/crates.io-index" 3967 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 3968 | 3969 | [[package]] 3970 | name = "windows_x86_64_gnullvm" 3971 | version = "0.52.6" 3972 | source = "registry+https://github.com/rust-lang/crates.io-index" 3973 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 3974 | 3975 | [[package]] 3976 | name = "windows_x86_64_gnullvm" 3977 | version = "0.53.0" 3978 | source = "registry+https://github.com/rust-lang/crates.io-index" 3979 | checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" 3980 | 3981 | [[package]] 3982 | name = "windows_x86_64_msvc" 3983 | version = "0.48.5" 3984 | source = "registry+https://github.com/rust-lang/crates.io-index" 3985 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 3986 | 3987 | [[package]] 3988 | name = "windows_x86_64_msvc" 3989 | version = "0.52.6" 3990 | source = "registry+https://github.com/rust-lang/crates.io-index" 3991 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 3992 | 3993 | [[package]] 3994 | name = "windows_x86_64_msvc" 3995 | version = "0.53.0" 3996 | source = "registry+https://github.com/rust-lang/crates.io-index" 3997 | checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" 3998 | 3999 | [[package]] 4000 | name = "winnow" 4001 | version = "0.6.20" 4002 | source = "registry+https://github.com/rust-lang/crates.io-index" 4003 | checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" 4004 | dependencies = [ 4005 | "memchr", 4006 | ] 4007 | 4008 | [[package]] 4009 | name = "winnow" 4010 | version = "0.7.13" 4011 | source = "registry+https://github.com/rust-lang/crates.io-index" 4012 | checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" 4013 | dependencies = [ 4014 | "memchr", 4015 | ] 4016 | 4017 | [[package]] 4018 | name = "wit-bindgen-rt" 4019 | version = "0.33.0" 4020 | source = "registry+https://github.com/rust-lang/crates.io-index" 4021 | checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" 4022 | dependencies = [ 4023 | "bitflags 2.6.0", 4024 | ] 4025 | 4026 | [[package]] 4027 | name = "write16" 4028 | version = "1.0.0" 4029 | source = "registry+https://github.com/rust-lang/crates.io-index" 4030 | checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" 4031 | 4032 | [[package]] 4033 | name = "writeable" 4034 | version = "0.5.5" 4035 | source = "registry+https://github.com/rust-lang/crates.io-index" 4036 | checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" 4037 | 4038 | [[package]] 4039 | name = "xattr" 4040 | version = "1.3.1" 4041 | source = "registry+https://github.com/rust-lang/crates.io-index" 4042 | checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" 4043 | dependencies = [ 4044 | "libc", 4045 | "linux-raw-sys", 4046 | "rustix", 4047 | ] 4048 | 4049 | [[package]] 4050 | name = "yaml-rust2" 4051 | version = "0.10.0" 4052 | source = "registry+https://github.com/rust-lang/crates.io-index" 4053 | checksum = "232bdb534d65520716bef0bbb205ff8f2db72d807b19c0bc3020853b92a0cd4b" 4054 | dependencies = [ 4055 | "arraydeque", 4056 | "encoding_rs", 4057 | "hashlink", 4058 | ] 4059 | 4060 | [[package]] 4061 | name = "yoke" 4062 | version = "0.7.4" 4063 | source = "registry+https://github.com/rust-lang/crates.io-index" 4064 | checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" 4065 | dependencies = [ 4066 | "serde", 4067 | "stable_deref_trait", 4068 | "yoke-derive", 4069 | "zerofrom", 4070 | ] 4071 | 4072 | [[package]] 4073 | name = "yoke-derive" 4074 | version = "0.7.4" 4075 | source = "registry+https://github.com/rust-lang/crates.io-index" 4076 | checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" 4077 | dependencies = [ 4078 | "proc-macro2", 4079 | "quote", 4080 | "syn", 4081 | "synstructure", 4082 | ] 4083 | 4084 | [[package]] 4085 | name = "zerocopy" 4086 | version = "0.7.35" 4087 | source = "registry+https://github.com/rust-lang/crates.io-index" 4088 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 4089 | dependencies = [ 4090 | "byteorder", 4091 | "zerocopy-derive 0.7.35", 4092 | ] 4093 | 4094 | [[package]] 4095 | name = "zerocopy" 4096 | version = "0.8.14" 4097 | source = "registry+https://github.com/rust-lang/crates.io-index" 4098 | checksum = "a367f292d93d4eab890745e75a778da40909cab4d6ff8173693812f79c4a2468" 4099 | dependencies = [ 4100 | "zerocopy-derive 0.8.14", 4101 | ] 4102 | 4103 | [[package]] 4104 | name = "zerocopy-derive" 4105 | version = "0.7.35" 4106 | source = "registry+https://github.com/rust-lang/crates.io-index" 4107 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 4108 | dependencies = [ 4109 | "proc-macro2", 4110 | "quote", 4111 | "syn", 4112 | ] 4113 | 4114 | [[package]] 4115 | name = "zerocopy-derive" 4116 | version = "0.8.14" 4117 | source = "registry+https://github.com/rust-lang/crates.io-index" 4118 | checksum = "d3931cb58c62c13adec22e38686b559c86a30565e16ad6e8510a337cedc611e1" 4119 | dependencies = [ 4120 | "proc-macro2", 4121 | "quote", 4122 | "syn", 4123 | ] 4124 | 4125 | [[package]] 4126 | name = "zerofrom" 4127 | version = "0.1.4" 4128 | source = "registry+https://github.com/rust-lang/crates.io-index" 4129 | checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" 4130 | dependencies = [ 4131 | "zerofrom-derive", 4132 | ] 4133 | 4134 | [[package]] 4135 | name = "zerofrom-derive" 4136 | version = "0.1.4" 4137 | source = "registry+https://github.com/rust-lang/crates.io-index" 4138 | checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" 4139 | dependencies = [ 4140 | "proc-macro2", 4141 | "quote", 4142 | "syn", 4143 | "synstructure", 4144 | ] 4145 | 4146 | [[package]] 4147 | name = "zeroize" 4148 | version = "1.8.1" 4149 | source = "registry+https://github.com/rust-lang/crates.io-index" 4150 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 4151 | 4152 | [[package]] 4153 | name = "zerovec" 4154 | version = "0.10.4" 4155 | source = "registry+https://github.com/rust-lang/crates.io-index" 4156 | checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" 4157 | dependencies = [ 4158 | "yoke", 4159 | "zerofrom", 4160 | "zerovec-derive", 4161 | ] 4162 | 4163 | [[package]] 4164 | name = "zerovec-derive" 4165 | version = "0.10.3" 4166 | source = "registry+https://github.com/rust-lang/crates.io-index" 4167 | checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" 4168 | dependencies = [ 4169 | "proc-macro2", 4170 | "quote", 4171 | "syn", 4172 | ] 4173 | 4174 | [[package]] 4175 | name = "zip" 4176 | version = "2.2.0" 4177 | source = "registry+https://github.com/rust-lang/crates.io-index" 4178 | checksum = "dc5e4288ea4057ae23afc69a4472434a87a2495cafce6632fd1c4ec9f5cf3494" 4179 | dependencies = [ 4180 | "arbitrary", 4181 | "crc32fast", 4182 | "crossbeam-utils", 4183 | "displaydoc", 4184 | "flate2", 4185 | "indexmap 2.6.0", 4186 | "memchr", 4187 | "thiserror 1.0.68", 4188 | "zopfli", 4189 | ] 4190 | 4191 | [[package]] 4192 | name = "zopfli" 4193 | version = "0.8.1" 4194 | source = "registry+https://github.com/rust-lang/crates.io-index" 4195 | checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946" 4196 | dependencies = [ 4197 | "bumpalo", 4198 | "crc32fast", 4199 | "lockfree-object-pool", 4200 | "log", 4201 | "once_cell", 4202 | "simd-adler32", 4203 | ] 4204 | 4205 | [[package]] 4206 | name = "zstd" 4207 | version = "0.13.2" 4208 | source = "registry+https://github.com/rust-lang/crates.io-index" 4209 | checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" 4210 | dependencies = [ 4211 | "zstd-safe", 4212 | ] 4213 | 4214 | [[package]] 4215 | name = "zstd-safe" 4216 | version = "7.2.0" 4217 | source = "registry+https://github.com/rust-lang/crates.io-index" 4218 | checksum = "fa556e971e7b568dc775c136fc9de8c779b1c2fc3a63defaafadffdbd3181afa" 4219 | dependencies = [ 4220 | "zstd-sys", 4221 | ] 4222 | 4223 | [[package]] 4224 | name = "zstd-sys" 4225 | version = "2.0.12+zstd.1.5.6" 4226 | source = "registry+https://github.com/rust-lang/crates.io-index" 4227 | checksum = "0a4e40c320c3cb459d9a9ff6de98cff88f4751ee9275d140e2be94a2b74e4c13" 4228 | dependencies = [ 4229 | "cc", 4230 | "pkg-config", 4231 | ] 4232 | --------------------------------------------------------------------------------