From c75095505b0da0f682963b089802de577efa9f74 Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (Pragmatismo)" Date: Thu, 19 Jun 2025 23:16:57 -0300 Subject: [PATCH] Implement email, meeting, proxy, and webmail services with LXC containers - Added email service setup script to configure Stalwart Mail in a container. - Created meeting service script to install and configure LiveKit with TURN server. - Developed proxy service script to set up Caddy as a reverse proxy. - Implemented webmail service script to deploy Roundcube with PHP support. - Established system service files for each service to manage their lifecycle. - Configured persistent storage for logs, data, and configuration for all services. - Added integration tests for email listing and file upload functionalities. - Updated prompt guidelines for consistent directory structure and user management. --- .lapce/run.toml | 30 - Cargo.lock | 7860 ++--------------- Cargo.toml | 151 +- deploy.sh | 12 - gb-auth/Cargo.toml | 58 - gb-auth/config/auth_config.yaml | 23 - gb-auth/src/error.rs | 26 - gb-auth/src/errors.rs | 24 - gb-auth/src/handlers/mod.rs | 2 - gb-auth/src/lib.rs | 7 - gb-auth/src/middleware/auth_middleware.rs | 33 - gb-auth/src/middleware/mod.rs | 3 - gb-auth/src/models/auth.rs | 15 - gb-auth/src/models/mod.rs | 4 - gb-auth/src/models/user.rs | 48 - gb-auth/src/services/auth_service.rs | 0 gb-auth/src/services/mod.rs | 0 gb-auth/src/utils/mod.rs | 1 - gb-auth/tests/auth_service_tests.rs | 0 gb-automation/Cargo.toml | 28 - gb-automation/src/lib.rs | 4 - gb-automation/src/process.rs | 127 - gb-automation/src/web.rs | 61 - gb-calendar/Cargo.toml | 9 - gb-calendar/src/lib.rs | 0 gb-cloud/Cargo.toml | 19 - gb-cloud/src/lib.rs | 0 gb-core/Cargo.toml | 33 - gb-core/src/config.rs | 114 - gb-core/src/db.rs | 69 - gb-core/src/errors.rs | 123 - gb-core/src/lib.rs | 9 - gb-core/src/models.rs | 396 - gb-core/src/traits.rs | 0 gb-core/src/utils.rs | 155 - gb-document/Cargo.toml | 25 - gb-document/src/excel.rs | 35 - gb-document/src/lib.rs | 0 gb-document/src/pdf.rs | 127 - gb-document/src/word.rs | 105 - gb-file/Cargo.toml | 32 - gb-file/src/lib.rs | 1 - gb-image/Cargo.toml | 27 - gb-image/assets/DejaVuSans.ttf | 1794 ---- gb-image/src/build.rs | 21 - gb-image/src/converter.rs | 74 - gb-image/src/lib.rs | 54 - gb-image/src/processor.rs | 74 - gb-infra/Cargo.toml | 18 - gb-infra/README.md | 20 - gb-infra/architecture.png | Bin 152065 -> 0 bytes gb-infra/architecture.txt | 78 - gb-infra/src/lib.rs | 9 - gb-infra/src/manager.rs | 60 - gb-infra/src/services/minio.rs | 54 - gb-infra/src/services/nginx.rs | 83 - gb-infra/src/services/postgresql.rs | 89 - gb-infra/src/services/stalwart.rs | 58 - gb-infra/src/services/zitadel.rs | 63 - gb-infra/src/setup.rs | 276 - .../default/shared/scripts/check-space.sh | 5 - gb-llm/Cargo.toml | 16 - gb-llm/src/lib.rs | 0 gb-media/Cargo.toml | 23 - gb-media/src/audio.rs | 56 - gb-media/src/lib.rs | 5 - gb-media/src/processor.rs | 82 - gb-media/src/webrtc.rs | 85 - gb-messaging/Cargo.toml | 26 - gb-messaging/src/broker.rs | 53 - gb-messaging/src/kafka.rs | 112 - gb-messaging/src/lib.rs | 88 - gb-messaging/src/models.rs | 11 - gb-messaging/src/processor.rs | 150 - gb-messaging/src/redis_pubsub.rs | 123 - gb-messaging/src/websocket.rs | 88 - .../20231220000000_update_user_schema.sql | 37 - gb-migrations/Cargo.toml | 22 - gb-migrations/src/bin/migrations.rs | 19 - gb-migrations/src/lib.rs | 144 - gb-monitoring/Cargo.toml | 21 - gb-monitoring/src/lib.rs | 40 - gb-monitoring/src/logging.rs | 40 - gb-monitoring/src/metrics.rs | 82 - gb-monitoring/src/telemetry.rs | 65 - gb-server/Cargo.toml | 37 - gb-server/src/lib.rs | 0 gb-server/src/main.rs | 72 - gb-storage/Cargo.toml | 24 - gb-storage/src/lib.rs | 7 - gb-storage/src/models.rs | 21 - gb-storage/src/postgres.rs | 229 - gb-storage/src/redis.rs | 79 - gb-storage/src/tikv.rs | 73 - gb-testing/Cargo.toml | 76 - gb-testing/README.md | 1 - gb-testing/config/test_config.yaml | 57 - gb-testing/run_tests.sh | 26 - gb-testing/src/chaos/mod.rs | 20 - gb-testing/src/integration/mod.rs | 13 - gb-testing/src/lib.rs | 13 - gb-testing/src/load/mod.rs | 140 - gb-testing/src/metrics/mod.rs | 52 - gb-testing/src/performance/mod.rs | 29 - gb-testing/src/reports/mod.rs | 64 - gb-testing/src/scenarios/mod.rs | 31 - gb-testing/src/stress/mod.rs | 38 - gb-testing/src/utils/mod.rs | 49 - gb-testing/tests/chaos_kubernetes_test.rs | 12 - gb-testing/tests/load_auth_test.rs | 20 - gb-testing/tests/performance_api_bench.rs | 17 - gb-utils/Cargo.toml | 24 - gb-utils/src/detector.rs | 66 - gb-utils/src/lib.rs | 45 - gb-utils/src/processor.rs | 0 gb-vm/Cargo.toml | 20 - gb-vm/src/db.rs | 65 - gb-vm/src/handlers.rs | 0 gb-vm/src/lib.rs | 0 gb-vm/src/router.rs | 4 - infra.sh | 276 - install.sh | 187 - .../20231220000000_update_auth_schema.sql | 16 - .../20231220000001_add_role_to_users.sql | 15 - .../20231220000002_update_users_schema.sql | 25 - ...20231220000003_update_customers_schema.sql | 7 - prompt.md | 891 -- run_tests.sh | 42 - gb-file/src/handlers.rs => src/lib.rs | 95 +- src/main.rs | 38 + .../handlers/auth_handler.rs => src/models.rs | 0 .../ai/analyze-customer-sentiment.bas | 0 .../prompts}/analytics/sales-performance.bas | 0 .../prompts}/business/send-proposal.bas | 0 .../prompts}/calendar/schedule-meeting.bas | 0 .../communication/keyword-sendmail.bas | 0 .../conversations/meeting-assistant.bas | 0 .../prompts}/core/system-prompt.bas | 0 .../prompts}/crm/update-opportunity.bas | 0 .../prompts}/files/search-documents.bas | 0 {gb-llm/.gbdialog => src/prompts}/geral.bas | 0 .../prompts}/groups/create-workspace.bas | 0 .../prompts}/health/system-check.bas | 0 .../prompts}/scheduled/basic-check.bas | 0 .../prompts}/security/access-review.bas | 0 .../prompts}/tools/on-receive-email.bas | 0 src/scripts/check-space.sh | 29 + src/scripts/cleaner.sh | 68 + .../limits.sh => src/scripts/set-limits.sh | 2 +- .../shared => src}/scripts/set-size-5GB.sh | 0 .../default/shared => src}/scripts/startup.sh | 0 .../opt/gbo/tenants/default/alm-ci/alm-ci.sh | 21 +- .../opt/gbo/tenants/default/alm/alm.sh | 0 .../opt/gbo/tenants/default/bot/bot.sh | 0 .../gbo/tenants/default/desktop/desktop.sh | 0 .../tenants/default/directory/directory.sh | 0 .../opt/gbo/tenants/default/drive/drive.sh | 0 .../opt/gbo/tenants/default/email/email.sh | 0 .../gbo/tenants/default/meeting/meeting.sh | 0 .../opt/gbo/tenants/default/prompt.txt | 0 .../opt/gbo/tenants/default/proxy/proxy.sh | 0 .../opt/gbo/tenants/default/social/.sh | 0 .../opt/gbo/tenants/default/system/system.sh | 0 .../default/table-editor/table-editor.sh | 0 .../opt/gbo/tenants/default/tables/tables.sh | 0 .../gbo/tenants/default/webmail/webmail.sh | 0 .../tests/integration_email_list.rs | 0 .../tests/integration_file_list_test.rs | 0 .../tests/integration_file_upload_test.rs | 0 169 files changed, 798 insertions(+), 16352 deletions(-) delete mode 100644 .lapce/run.toml delete mode 100755 deploy.sh delete mode 100644 gb-auth/Cargo.toml delete mode 100644 gb-auth/config/auth_config.yaml delete mode 100644 gb-auth/src/error.rs delete mode 100644 gb-auth/src/errors.rs delete mode 100644 gb-auth/src/handlers/mod.rs delete mode 100644 gb-auth/src/lib.rs delete mode 100644 gb-auth/src/middleware/auth_middleware.rs delete mode 100644 gb-auth/src/middleware/mod.rs delete mode 100644 gb-auth/src/models/auth.rs delete mode 100644 gb-auth/src/models/mod.rs delete mode 100644 gb-auth/src/models/user.rs delete mode 100644 gb-auth/src/services/auth_service.rs delete mode 100644 gb-auth/src/services/mod.rs delete mode 100644 gb-auth/src/utils/mod.rs delete mode 100644 gb-auth/tests/auth_service_tests.rs delete mode 100644 gb-automation/Cargo.toml delete mode 100644 gb-automation/src/lib.rs delete mode 100644 gb-automation/src/process.rs delete mode 100644 gb-automation/src/web.rs delete mode 100644 gb-calendar/Cargo.toml delete mode 100644 gb-calendar/src/lib.rs delete mode 100644 gb-cloud/Cargo.toml delete mode 100644 gb-cloud/src/lib.rs delete mode 100644 gb-core/Cargo.toml delete mode 100644 gb-core/src/config.rs delete mode 100644 gb-core/src/db.rs delete mode 100644 gb-core/src/errors.rs delete mode 100644 gb-core/src/lib.rs delete mode 100644 gb-core/src/models.rs delete mode 100644 gb-core/src/traits.rs delete mode 100644 gb-core/src/utils.rs delete mode 100644 gb-document/Cargo.toml delete mode 100644 gb-document/src/excel.rs delete mode 100644 gb-document/src/lib.rs delete mode 100644 gb-document/src/pdf.rs delete mode 100644 gb-document/src/word.rs delete mode 100644 gb-file/Cargo.toml delete mode 100644 gb-file/src/lib.rs delete mode 100644 gb-image/Cargo.toml delete mode 100644 gb-image/assets/DejaVuSans.ttf delete mode 100644 gb-image/src/build.rs delete mode 100644 gb-image/src/converter.rs delete mode 100644 gb-image/src/lib.rs delete mode 100644 gb-image/src/processor.rs delete mode 100644 gb-infra/Cargo.toml delete mode 100644 gb-infra/README.md delete mode 100644 gb-infra/architecture.png delete mode 100644 gb-infra/architecture.txt delete mode 100644 gb-infra/src/lib.rs delete mode 100644 gb-infra/src/manager.rs delete mode 100644 gb-infra/src/services/minio.rs delete mode 100644 gb-infra/src/services/nginx.rs delete mode 100644 gb-infra/src/services/postgresql.rs delete mode 100644 gb-infra/src/services/stalwart.rs delete mode 100644 gb-infra/src/services/zitadel.rs delete mode 100644 gb-infra/src/setup.rs delete mode 100644 gb-infra/src/templates/opt/gbo/tenants/default/shared/scripts/check-space.sh delete mode 100644 gb-llm/Cargo.toml delete mode 100644 gb-llm/src/lib.rs delete mode 100644 gb-media/Cargo.toml delete mode 100644 gb-media/src/audio.rs delete mode 100644 gb-media/src/lib.rs delete mode 100644 gb-media/src/processor.rs delete mode 100644 gb-media/src/webrtc.rs delete mode 100644 gb-messaging/Cargo.toml delete mode 100644 gb-messaging/src/broker.rs delete mode 100644 gb-messaging/src/kafka.rs delete mode 100644 gb-messaging/src/lib.rs delete mode 100644 gb-messaging/src/models.rs delete mode 100644 gb-messaging/src/processor.rs delete mode 100644 gb-messaging/src/redis_pubsub.rs delete mode 100644 gb-messaging/src/websocket.rs delete mode 100644 gb-migrations/20231220000000_update_user_schema.sql delete mode 100644 gb-migrations/Cargo.toml delete mode 100644 gb-migrations/src/bin/migrations.rs delete mode 100644 gb-migrations/src/lib.rs delete mode 100644 gb-monitoring/Cargo.toml delete mode 100644 gb-monitoring/src/lib.rs delete mode 100644 gb-monitoring/src/logging.rs delete mode 100644 gb-monitoring/src/metrics.rs delete mode 100644 gb-monitoring/src/telemetry.rs delete mode 100644 gb-server/Cargo.toml delete mode 100644 gb-server/src/lib.rs delete mode 100644 gb-server/src/main.rs delete mode 100644 gb-storage/Cargo.toml delete mode 100644 gb-storage/src/lib.rs delete mode 100644 gb-storage/src/models.rs delete mode 100644 gb-storage/src/postgres.rs delete mode 100644 gb-storage/src/redis.rs delete mode 100644 gb-storage/src/tikv.rs delete mode 100644 gb-testing/Cargo.toml delete mode 100644 gb-testing/README.md delete mode 100644 gb-testing/config/test_config.yaml delete mode 100755 gb-testing/run_tests.sh delete mode 100644 gb-testing/src/chaos/mod.rs delete mode 100644 gb-testing/src/integration/mod.rs delete mode 100644 gb-testing/src/lib.rs delete mode 100644 gb-testing/src/load/mod.rs delete mode 100644 gb-testing/src/metrics/mod.rs delete mode 100644 gb-testing/src/performance/mod.rs delete mode 100644 gb-testing/src/reports/mod.rs delete mode 100644 gb-testing/src/scenarios/mod.rs delete mode 100644 gb-testing/src/stress/mod.rs delete mode 100644 gb-testing/src/utils/mod.rs delete mode 100644 gb-testing/tests/chaos_kubernetes_test.rs delete mode 100644 gb-testing/tests/load_auth_test.rs delete mode 100644 gb-testing/tests/performance_api_bench.rs delete mode 100644 gb-utils/Cargo.toml delete mode 100644 gb-utils/src/detector.rs delete mode 100644 gb-utils/src/lib.rs delete mode 100644 gb-utils/src/processor.rs delete mode 100644 gb-vm/Cargo.toml delete mode 100644 gb-vm/src/db.rs delete mode 100644 gb-vm/src/handlers.rs delete mode 100644 gb-vm/src/lib.rs delete mode 100644 gb-vm/src/router.rs delete mode 100644 infra.sh delete mode 100755 install.sh delete mode 100755 migrations/20231220000000_update_auth_schema.sql delete mode 100644 migrations/20231220000001_add_role_to_users.sql delete mode 100644 migrations/20231220000002_update_users_schema.sql delete mode 100644 migrations/20231220000003_update_customers_schema.sql delete mode 100644 prompt.md delete mode 100755 run_tests.sh rename gb-file/src/handlers.rs => src/lib.rs (60%) create mode 100644 src/main.rs rename gb-auth/src/handlers/auth_handler.rs => src/models.rs (100%) rename {gb-llm/.gbdialog => src/prompts}/ai/analyze-customer-sentiment.bas (100%) rename {gb-llm/.gbdialog => src/prompts}/analytics/sales-performance.bas (100%) rename {gb-llm/.gbdialog => src/prompts}/business/send-proposal.bas (100%) rename {gb-llm/.gbdialog => src/prompts}/calendar/schedule-meeting.bas (100%) rename {gb-llm/.gbdialog => src/prompts}/communication/keyword-sendmail.bas (100%) rename {gb-llm/.gbdialog => src/prompts}/conversations/meeting-assistant.bas (100%) rename {gb-llm/.gbdialog => src/prompts}/core/system-prompt.bas (100%) rename {gb-llm/.gbdialog => src/prompts}/crm/update-opportunity.bas (100%) rename {gb-llm/.gbdialog => src/prompts}/files/search-documents.bas (100%) rename {gb-llm/.gbdialog => src/prompts}/geral.bas (100%) rename {gb-llm/.gbdialog => src/prompts}/groups/create-workspace.bas (100%) rename {gb-llm/.gbdialog => src/prompts}/health/system-check.bas (100%) rename {gb-llm/.gbdialog => src/prompts}/scheduled/basic-check.bas (100%) rename {gb-llm/.gbdialog => src/prompts}/security/access-review.bas (100%) rename {gb-llm/.gbdialog => src/prompts}/tools/on-receive-email.bas (100%) create mode 100644 src/scripts/check-space.sh create mode 100644 src/scripts/cleaner.sh rename gb-infra/src/templates/opt/gbo/tenants/default/shared/scripts/limits.sh => src/scripts/set-limits.sh (97%) rename {gb-infra/src/templates/opt/gbo/tenants/default/shared => src}/scripts/set-size-5GB.sh (100%) rename {gb-infra/src/templates/opt/gbo/tenants/default/shared => src}/scripts/startup.sh (100%) rename {gb-infra/src => src}/templates/opt/gbo/tenants/default/alm-ci/alm-ci.sh (97%) rename {gb-infra/src => src}/templates/opt/gbo/tenants/default/alm/alm.sh (100%) rename {gb-infra/src => src}/templates/opt/gbo/tenants/default/bot/bot.sh (100%) rename {gb-infra/src => src}/templates/opt/gbo/tenants/default/desktop/desktop.sh (100%) rename {gb-infra/src => src}/templates/opt/gbo/tenants/default/directory/directory.sh (100%) rename {gb-infra/src => src}/templates/opt/gbo/tenants/default/drive/drive.sh (100%) rename {gb-infra/src => src}/templates/opt/gbo/tenants/default/email/email.sh (100%) rename {gb-infra/src => src}/templates/opt/gbo/tenants/default/meeting/meeting.sh (100%) rename {gb-infra/src => src}/templates/opt/gbo/tenants/default/prompt.txt (100%) rename {gb-infra/src => src}/templates/opt/gbo/tenants/default/proxy/proxy.sh (100%) rename {gb-infra/src => src}/templates/opt/gbo/tenants/default/social/.sh (100%) rename {gb-infra/src => src}/templates/opt/gbo/tenants/default/system/system.sh (100%) rename {gb-infra/src => src}/templates/opt/gbo/tenants/default/table-editor/table-editor.sh (100%) rename {gb-infra/src => src}/templates/opt/gbo/tenants/default/tables/tables.sh (100%) rename {gb-infra/src => src}/templates/opt/gbo/tenants/default/webmail/webmail.sh (100%) rename {gb-testing => src}/tests/integration_email_list.rs (100%) rename {gb-testing => src}/tests/integration_file_list_test.rs (100%) rename {gb-testing => src}/tests/integration_file_upload_test.rs (100%) diff --git a/.lapce/run.toml b/.lapce/run.toml deleted file mode 100644 index 35478ab..0000000 --- a/.lapce/run.toml +++ /dev/null @@ -1,30 +0,0 @@ - -# The run config is used for both run mode and debug mode - -[[configs]] -# the name of this task -name = "task" - -# the type of the debugger. If not set, it can't be debugged but can still be run -# type = "lldb" - -# the program to run, e.g. "${workspace}\\target\\debug\\check.exe" -program = "" - -# the program arguments, e.g. args = ["arg1", "arg2"], optional -# args = [] - -# current working directory, optional -# cwd = "${workspace}" - -# environment variables, optional -# [configs.env] -# VAR1 = "VAL1" -# VAR2 = "VAL2" - -# task to run before the run/debug session is started, optional -# [configs.prelaunch] -# program = "cargo" -# args = [ -# "build", -# ] diff --git a/Cargo.lock b/Cargo.lock index 4eacc78..46a0ab8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,19 +2,13 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "ab_glyph_rasterizer" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" - [[package]] name = "actix-codec" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" dependencies = [ - "bitflags 2.9.0", + "bitflags", "bytes", "futures-core", "futures-sink", @@ -27,23 +21,23 @@ dependencies = [ [[package]] name = "actix-http" -version = "3.9.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d48f96fc3003717aeb9856ca3d02a8c7de502667ad76eeacd830b48d2e91fac4" +checksum = "44dfe5c9e0004c623edc65391dfd51daa201e7e30ebd9c9bedf873048ec32bc2" dependencies = [ "actix-codec", "actix-rt", "actix-service", "actix-utils", - "ahash", - "base64 0.22.1", - "bitflags 2.9.0", + "base64", + "bitflags", "brotli", "bytes", "bytestring", - "derive_more", + "derive_more 2.0.1", "encoding_rs", "flate2", + "foldhash", "futures-core", "h2 0.3.26", "http 0.2.12", @@ -55,13 +49,13 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "rand 0.8.5", + "rand 0.9.1", "sha1", "smallvec", "tokio", "tokio-util", "tracing", - "zstd 0.13.3", + "zstd", ] [[package]] @@ -71,25 +65,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.99", + "syn 2.0.103", ] [[package]] name = "actix-multipart" -version = "0.4.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9edfb0e7663d7fe18c8d5b668c9c1bcf79176b1dcc9d4da9592503209a6bfb0" +checksum = "d974dd6c4f78d102d057c672dcf6faa618fafa9df91d44f9c466688fc1275a3a" dependencies = [ + "actix-multipart-derive", "actix-utils", "actix-web", "bytes", - "derive_more", + "derive_more 0.99.20", "futures-core", + "futures-util", "httparse", "local-waker", "log", + "memchr", "mime", - "twoway", + "rand 0.8.5", + "serde", + "serde_json", + "serde_plain", + "tempfile", + "tokio", +] + +[[package]] +name = "actix-multipart-derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a0a77f836d869f700e5b47ac7c3c8b9c8bc82e4aec861954c6198abee3ebd4d" +dependencies = [ + "darling", + "parse-size", + "proc-macro2", + "quote", + "syn 2.0.103", ] [[package]] @@ -119,9 +134,9 @@ dependencies = [ [[package]] name = "actix-server" -version = "2.5.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6398974fd4284f4768af07965701efbbb5fdc0616bff20cade1bb14b77675e24" +checksum = "a65064ea4a457eaf07f2fba30b4c695bf43b721790e9530d26cb6f9019ff7502" dependencies = [ "actix-rt", "actix-service", @@ -129,19 +144,18 @@ dependencies = [ "futures-core", "futures-util", "mio", - "socket2 0.5.8", + "socket2", "tokio", "tracing", ] [[package]] name = "actix-service" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" +checksum = "9e46f36bf0e5af44bdc4bdb36fbbd421aa98c79a9bce724e1edeb3894e10dc7f" dependencies = [ "futures-core", - "paste", "pin-project-lite", ] @@ -157,9 +171,9 @@ dependencies = [ [[package]] name = "actix-web" -version = "4.9.0" +version = "4.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9180d76e5cc7ccbc4d60a506f2c727730b154010262df5b910eb17dbe4b8cb38" +checksum = "a597b77b5c6d6a1e1097fddde329a83665e25c5437c696a3a9a4aa514a614dea" dependencies = [ "actix-codec", "actix-http", @@ -170,13 +184,13 @@ dependencies = [ "actix-service", "actix-utils", "actix-web-codegen", - "ahash", "bytes", "bytestring", "cfg-if", - "cookie 0.16.2", - "derive_more", + "cookie", + "derive_more 2.0.1", "encoding_rs", + "foldhash", "futures-core", "futures-util", "impl-more", @@ -192,8 +206,9 @@ dependencies = [ "serde_json", "serde_urlencoded", "smallvec", - "socket2 0.5.8", + "socket2", "time", + "tracing", "url", ] @@ -206,7 +221,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.103", ] [[package]] @@ -220,58 +235,9 @@ dependencies = [ [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - -[[package]] -name = "aead" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" -dependencies = [ - "crypto-common", - "generic-array", -] - -[[package]] -name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "aes-gcm" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" -dependencies = [ - "aead", - "aes", - "cipher", - "ctr", - "ghash", - "subtle", -] - -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "getrandom 0.2.15", - "once_cell", - "serde", - "version_check", - "zerocopy 0.7.35", -] +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aho-corasick" @@ -297,60 +263,6 @@ dependencies = [ "alloc-no-stdlib", ] -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - -[[package]] -name = "amq-protocol" -version = "7.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a41c091e49edfcc098b4f90d4d7706a8cf9158034e84ebfee7ff346092f67c" -dependencies = [ - "amq-protocol-tcp", - "amq-protocol-types", - "amq-protocol-uri", - "cookie-factory", - "nom 7.1.3", - "serde", -] - -[[package]] -name = "amq-protocol-tcp" -version = "7.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed7a4a662472f88823ed2fc81babb0b00562f2c54284e3e7bffc02b6df649bf" -dependencies = [ - "amq-protocol-uri", - "tcp-stream", - "tracing", -] - -[[package]] -name = "amq-protocol-types" -version = "7.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6484fdc918c1b6e2ae8eda2914d19a5873e1975f93ad8d33d6a24d1d98df05" -dependencies = [ - "cookie-factory", - "nom 7.1.3", - "serde", - "serde_json", -] - -[[package]] -name = "amq-protocol-uri" -version = "7.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7f2da69e0e1182765bf33407cd8a843f20791b5af2b57a2645818c4776c56c" -dependencies = [ - "amq-protocol-types", - "percent-encoding", - "url", -] - [[package]] name = "android-tzdata" version = "0.1.1" @@ -366,17 +278,11 @@ dependencies = [ "libc", ] -[[package]] -name = "anes" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" - [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" dependencies = [ "anstyle", "anstyle-parse", @@ -389,182 +295,39 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.7" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" dependencies = [ "anstyle", - "once_cell", + "once_cell_polyfill", "windows-sys 0.59.0", ] -[[package]] -name = "anyhow" -version = "1.0.97" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" - -[[package]] -name = "approx" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" -dependencies = [ - "num-traits", -] - -[[package]] -name = "arc-swap" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" - -[[package]] -name = "argon2" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" -dependencies = [ - "base64ct", - "blake2", - "cpufeatures", - "password-hash 0.5.0", -] - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - -[[package]] -name = "asn1-rs" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" -dependencies = [ - "asn1-rs-derive 0.4.0", - "asn1-rs-impl 0.1.0", - "displaydoc", - "nom 7.1.3", - "num-traits", - "rusticata-macros", - "thiserror 1.0.69", - "time", -] - -[[package]] -name = "asn1-rs" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "607495ec7113b178fbba7a6166a27f99e774359ef4823adbefd756b5b81d7970" -dependencies = [ - "asn1-rs-derive 0.6.0", - "asn1-rs-impl 0.2.0", - "displaydoc", - "nom 7.1.3", - "num-traits", - "rusticata-macros", - "thiserror 2.0.12", - "time", -] - -[[package]] -name = "asn1-rs-derive" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "synstructure 0.12.6", -] - -[[package]] -name = "asn1-rs-derive" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.99", - "synstructure 0.13.1", -] - -[[package]] -name = "asn1-rs-impl" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "asn1-rs-impl" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.99", -] - -[[package]] -name = "assert-json-diff" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "assert_cmd" -version = "2.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1835b7f27878de8525dc71410b5a31cdcc5f230aed5ba5df968e09c201b23d" -dependencies = [ - "anstyle", - "bstr", - "doc-comment", - "libc", - "predicates", - "predicates-core", - "predicates-tree", - "wait-timeout", -] - [[package]] name = "async-attributes" version = "1.1.2" @@ -598,29 +361,17 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "async-compression" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "310c9bcae737a48ef5cdee3174184e6d548b292739ede61a1f955ef76a738861" -dependencies = [ - "flate2", - "futures-core", - "memchr", - "pin-project-lite", - "tokio", -] - [[package]] name = "async-executor" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" +checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa" dependencies = [ "async-task", "concurrent-queue", - "fastrand 2.3.0", - "futures-lite 2.6.0", + "fastrand", + "futures-lite", + "pin-project-lite", "slab", ] @@ -632,86 +383,32 @@ checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ "async-channel 2.3.1", "async-executor", - "async-io 2.4.0", - "async-lock 3.4.0", + "async-io", + "async-lock", "blocking", - "futures-lite 2.6.0", + "futures-lite", "once_cell", ] -[[package]] -name = "async-global-executor" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13f937e26114b93193065fd44f507aa2e9169ad0cdabbb996920b1fe1ddea7ba" -dependencies = [ - "async-channel 2.3.1", - "async-executor", - "async-io 2.4.0", - "async-lock 3.4.0", - "blocking", - "futures-lite 2.6.0", -] - -[[package]] -name = "async-global-executor-trait" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9af57045d58eeb1f7060e7025a1631cbc6399e0a1d10ad6735b3d0ea7f8346ce" -dependencies = [ - "async-global-executor 3.1.0", - "async-trait", - "executor-trait", -] - [[package]] name = "async-io" -version = "1.13.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +checksum = "1237c0ae75a0f3765f58910ff9cdd0a12eeb39ab2f4c7de23262f337f0aacbb3" dependencies = [ - "async-lock 2.8.0", - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-lite 1.13.0", - "log", - "parking", - "polling 2.8.0", - "rustix 0.37.28", - "slab", - "socket2 0.4.10", - "waker-fn", -] - -[[package]] -name = "async-io" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" -dependencies = [ - "async-lock 3.4.0", + "async-lock", "cfg-if", "concurrent-queue", "futures-io", - "futures-lite 2.6.0", + "futures-lite", "parking", - "polling 3.7.4", - "rustix 0.38.44", + "polling", + "rustix", "slab", "tracing", "windows-sys 0.59.0", ] -[[package]] -name = "async-lock" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" -dependencies = [ - "event-listener 2.5.3", -] - [[package]] name = "async-lock" version = "3.4.0" @@ -723,37 +420,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "async-process" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" -dependencies = [ - "async-channel 2.3.1", - "async-io 2.4.0", - "async-lock 3.4.0", - "async-signal", - "async-task", - "blocking", - "cfg-if", - "event-listener 5.4.0", - "futures-lite 2.6.0", - "rustix 0.38.44", - "tracing", -] - -[[package]] -name = "async-reactor-trait" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6012d170ad00de56c9ee354aef2e358359deb1ec504254e0e5a3774771de0e" -dependencies = [ - "async-io 1.13.0", - "async-trait", - "futures-core", - "reactor-trait", -] - [[package]] name = "async-recursion" version = "1.1.1" @@ -762,44 +428,25 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", -] - -[[package]] -name = "async-signal" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" -dependencies = [ - "async-io 2.4.0", - "async-lock 3.4.0", - "atomic-waker", - "cfg-if", - "futures-core", - "futures-io", - "rustix 0.38.44", - "signal-hook-registry", - "slab", - "windows-sys 0.59.0", + "syn 2.0.103", ] [[package]] name = "async-std" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615" +checksum = "730294c1c08c2e0f85759590518f6333f0d5a0a766a27d519c1b244c3dfd8a24" dependencies = [ "async-attributes", "async-channel 1.9.0", - "async-global-executor 2.4.1", - "async-io 2.4.0", - "async-lock 3.4.0", - "async-process", + "async-global-executor", + "async-io", + "async-lock", "crossbeam-utils", "futures-channel", "futures-core", "futures-io", - "futures-lite 2.6.0", + "futures-lite", "gloo-timers", "kv-log-macro", "log", @@ -830,7 +477,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.103", ] [[package]] @@ -841,37 +488,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.87" +version = "0.1.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d556ec1359574147ec0c4fc5eb525f3f23263a592b1a9c07e0a75b427de55c97" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", -] - -[[package]] -name = "async-tungstenite" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e9efbe14612da0a19fb983059a0b621e9cf6225d7018ecab4f9988215540dc" -dependencies = [ - "async-std", - "futures-io", - "futures-util", - "log", - "pin-project-lite", - "tokio", - "tungstenite 0.20.1", -] - -[[package]] -name = "atoi" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" -dependencies = [ - "num-traits", + "syn 2.0.103", ] [[package]] @@ -880,179 +503,17 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" -[[package]] -name = "audiopus_sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62314a1546a2064e033665d658e88c620a62904be945f8147e6b16c3db9f8651" -dependencies = [ - "cmake", - "log", - "pkg-config", -] - -[[package]] -name = "auto_generate_cdp" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6e1961a0d5d77969057eba90d448e610d3c439024d135d9dbd98e33ec973520" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "serde", - "serde_json", - "ureq", -] - [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "axum" -version = "0.6.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" -dependencies = [ - "async-trait", - "axum-core 0.3.4", - "bitflags 1.3.2", - "bytes", - "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.32", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "sync_wrapper 0.1.2", - "tower 0.4.13", - "tower-layer", - "tower-service", -] - -[[package]] -name = "axum" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" -dependencies = [ - "async-trait", - "axum-core 0.4.5", - "axum-macros", - "base64 0.22.1", - "bytes", - "futures-util", - "http 1.2.0", - "http-body 1.0.1", - "http-body-util", - "hyper 1.6.0", - "hyper-util", - "itoa", - "matchit", - "memchr", - "mime", - "multer", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "serde_json", - "serde_path_to_error", - "serde_urlencoded", - "sha1", - "sync_wrapper 1.0.2", - "tokio", - "tokio-tungstenite 0.24.0", - "tower 0.5.2", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-core" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "mime", - "rustversion", - "tower-layer", - "tower-service", -] - -[[package]] -name = "axum-core" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http 1.2.0", - "http-body 1.0.1", - "http-body-util", - "mime", - "pin-project-lite", - "rustversion", - "sync_wrapper 1.0.2", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-extra" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a93e433be9382c737320af3924f7d5fc6f89c155cf2bf88949d8f5126fab283f" -dependencies = [ - "axum 0.6.20", - "axum-core 0.3.4", - "bytes", - "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "mime", - "pin-project-lite", - "serde", - "tokio", - "tower 0.4.13", - "tower-layer", - "tower-service", -] - -[[package]] -name = "axum-macros" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.99", -] +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", "cfg-if", @@ -1063,109 +524,17 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - -[[package]] -name = "bindgen" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd4865004a46a0aafb2a0a5eb19d3c9fc46ee5f063a6cfc605c69ac9ecf5263d" -dependencies = [ - "bitflags 1.3.2", - "cexpr", - "clang-sys", - "lazy_static", - "lazycell", - "peeking_take_while", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex 0.1.1", -] - -[[package]] -name = "biscuit" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28865439fc81744500265d96c920985ceb6b612ef8564d43f1cc78e7a6c89e26" -dependencies = [ - "chrono", - "data-encoding", - "num-bigint", - "num-traits", - "once_cell", - "ring 0.16.20", - "serde", - "serde_json", -] - -[[package]] -name = "bit_field" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" - [[package]] name = "bitflags" -version = "1.3.2" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" -dependencies = [ - "serde", -] - -[[package]] -name = "blake2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" -dependencies = [ - "digest", -] +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "block-buffer" @@ -1176,15 +545,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block-padding" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" -dependencies = [ - "generic-array", -] - [[package]] name = "blocking" version = "1.6.1" @@ -1194,24 +554,15 @@ dependencies = [ "async-channel 2.3.1", "async-task", "futures-io", - "futures-lite 2.6.0", + "futures-lite", "piper", ] -[[package]] -name = "boringssl-src" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0511b9f0b739706e05b7279ece5dfc1932a42839cf005cb0f00420a3fea27c96" -dependencies = [ - "cmake", -] - [[package]] name = "brotli" -version = "6.0.0" +version = "8.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" +checksum = "9991eea70ea4f293524138648e41ee89b0b2b12ddef3b255effa43c8056e0e0d" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -1220,36 +571,19 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "4.0.2" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74fa05ad7d803d413eb8380983b092cbbaf9a85f151b871360e7b00cd7060b37" +checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", ] -[[package]] -name = "bstr" -version = "1.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" -dependencies = [ - "memchr", - "regex-automata 0.4.9", - "serde", -] - [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" - -[[package]] -name = "bytemuck" -version = "1.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" +checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" [[package]] name = "byteorder" @@ -1262,9 +596,6 @@ name = "bytes" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" -dependencies = [ - "serde", -] [[package]] name = "bytestring" @@ -1275,321 +606,42 @@ dependencies = [ "bytes", ] -[[package]] -name = "bzip2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" -dependencies = [ - "bzip2-sys", - "libc", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.13+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" -dependencies = [ - "cc", - "pkg-config", -] - -[[package]] -name = "calamine" -version = "0.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95f023f9ae2c2f017564b7eca85660c3c09477bb037f2fbfbaaba732b5642a32" -dependencies = [ - "byteorder", - "codepage", - "encoding_rs", - "log", - "quick-xml", - "serde", - "zip", -] - -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - -[[package]] -name = "cbc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" -dependencies = [ - "cipher", -] - [[package]] name = "cc" -version = "1.2.16" +version = "1.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" dependencies = [ "jobserver", "libc", - "shlex 1.3.0", -] - -[[package]] -name = "ccm" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ae3c82e4355234767756212c570e29833699ab63e6ffd161887314cc5b43847" -dependencies = [ - "aead", - "cipher", - "ctr", - "subtle", -] - -[[package]] -name = "cexpr" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" -dependencies = [ - "nom 5.1.3", -] - -[[package]] -name = "cfg-expr" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" -dependencies = [ - "smallvec", - "target-lexicon", + "shlex", ] [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - -[[package]] -name = "chromiumoxide" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2abb1e644b7fcaa711fe4d3fca06c52bf18ebc5398711b2b11e8281c6107fbe" -dependencies = [ - "async-std", - "async-tungstenite", - "base64 0.21.7", - "bytes", - "cfg-if", - "chromiumoxide_cdp", - "chromiumoxide_types", - "dunce", - "fnv", - "futures 0.3.31", - "futures-timer", - "pin-project-lite", - "reqwest 0.11.27", - "serde", - "serde_json", - "thiserror 1.0.69", - "tokio", - "tracing", - "url", - "which 4.4.2", - "winreg 0.51.0", -] - -[[package]] -name = "chromiumoxide_cdp" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72641e4931b5372361160346d88605bbd6252b54c89581b71ac06b3b68b8b7c0" -dependencies = [ - "chromiumoxide_pdl", - "chromiumoxide_types", - "serde", - "serde_json", -] - -[[package]] -name = "chromiumoxide_pdl" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ecbd2d949e41b72575e61f9a38a5e2d6207ffb98544448e1eb7b9310d48bbbe" -dependencies = [ - "chromiumoxide_types", - "either", - "heck 0.4.1", - "once_cell", - "proc-macro2", - "quote", - "regex", - "serde", - "serde_json", -] - -[[package]] -name = "chromiumoxide_types" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5fc717f4c899a7a02a50f7698a90acade50a1a65fe7804e57c747739fa23e25" -dependencies = [ - "serde", - "serde_json", -] +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "chrono" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", - "serde", "wasm-bindgen", "windows-link", ] -[[package]] -name = "ciborium" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" - -[[package]] -name = "ciborium-ll" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" -dependencies = [ - "ciborium-io", - "half", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", -] - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "clap" -version = "4.5.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767" -dependencies = [ - "clap_builder", -] - -[[package]] -name = "clap_builder" -version = "4.5.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863" -dependencies = [ - "anstyle", - "clap_lex", -] - -[[package]] -name = "clap_lex" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" - -[[package]] -name = "cmake" -version = "0.1.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" -dependencies = [ - "cc", -] - -[[package]] -name = "cms" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b77c319abfd5219629c45c34c89ba945ed3c5e49fcde9d16b6c3885f118a730" -dependencies = [ - "const-oid", - "der", - "spki", - "x509-cert", -] - -[[package]] -name = "codepage" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f68d061bc2828ae826206326e61251aca94c1e4a5305cf52d9138639c918b4" -dependencies = [ - "encoding_rs", -] - -[[package]] -name = "color_quant" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" - [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" - -[[package]] -name = "combine" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes", - "futures-core", - "memchr", - "pin-project-lite", - "tokio", - "tokio-util", -] +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "concurrent-queue" @@ -1600,27 +652,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - -[[package]] -name = "conv" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299" -dependencies = [ - "custom_derive", -] - [[package]] name = "convert_case" version = "0.4.0" @@ -1638,40 +669,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "cookie" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7efb37c3e1ccb1ff97164ad95ac1606e8ccd35b3fa0a7d99a304c7f4a428cc24" -dependencies = [ - "percent-encoding", - "time", - "version_check", -] - -[[package]] -name = "cookie-factory" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9885fa71e26b8ab7855e2ec7cae6e9b380edff76cd052e07c683a0319d51b3a2" - -[[package]] -name = "cookie_store" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387461abbc748185c3a6e1673d826918b450b87ff22639429c694619a83b6cf6" -dependencies = [ - "cookie 0.17.0", - "idna 0.3.0", - "log", - "publicsuffix", - "serde", - "serde_derive", - "serde_json", - "time", - "url", -] - [[package]] name = "core-foundation" version = "0.9.4" @@ -1682,16 +679,6 @@ dependencies = [ "libc", ] -[[package]] -name = "core-foundation" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1709,9 +696,9 @@ dependencies = [ [[package]] name = "crc" -version = "3.2.1" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" dependencies = [ "crc-catalog", ] @@ -1731,104 +718,12 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "criterion" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" -dependencies = [ - "anes", - "cast", - "ciborium", - "clap", - "criterion-plot", - "futures 0.3.31", - "is-terminal", - "itertools 0.10.5", - "num-traits", - "once_cell", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" -dependencies = [ - "cast", - "itertools 0.10.5", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "crossbeam-utils" version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" -[[package]] -name = "crunchy" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" - -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - [[package]] name = "crypto-common" version = "0.1.6" @@ -1836,73 +731,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", - "rand_core 0.6.4", "typenum", ] -[[package]] -name = "ctr" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" -dependencies = [ - "cipher", -] - -[[package]] -name = "ctrlc" -version = "3.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3" -dependencies = [ - "nix 0.29.0", - "windows-sys 0.59.0", -] - -[[package]] -name = "curve25519-dalek" -version = "4.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" -dependencies = [ - "cfg-if", - "cpufeatures", - "curve25519-dalek-derive", - "digest", - "fiat-crypto", - "rustc_version", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.99", -] - -[[package]] -name = "custom_derive" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9" - -[[package]] -name = "custom_error" -version = "1.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f8a51dd197fa6ba5b4dc98a990a43cc13693c23eb0089ebb0fcc1f04152bca6" - [[package]] name = "darling" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ "darling_core", "darling_macro", @@ -1910,40 +746,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.99", + "syn 2.0.103", ] [[package]] name = "darling_macro" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn 2.0.99", -] - -[[package]] -name = "dashmap" -version = "5.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core 0.9.10", + "syn 2.0.103", ] [[package]] @@ -1957,94 +780,16 @@ dependencies = [ "hashbrown 0.14.5", "lock_api", "once_cell", - "parking_lot_core 0.9.10", -] - -[[package]] -name = "data-encoding" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" - -[[package]] -name = "deadpool" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "421fe0f90f2ab22016f32a9881be5134fdd71c65298917084b0c7477cbc3856e" -dependencies = [ - "async-trait", - "deadpool-runtime", - "num_cpus", - "retain_mut", - "tokio", -] - -[[package]] -name = "deadpool-runtime" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" - -[[package]] -name = "der" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" -dependencies = [ - "const-oid", - "der_derive", - "flagset", - "pem-rfc7468", - "zeroize", -] - -[[package]] -name = "der-parser" -version = "8.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" -dependencies = [ - "asn1-rs 0.5.2", - "displaydoc", - "nom 7.1.3", - "num-bigint", - "num-traits", - "rusticata-macros", -] - -[[package]] -name = "der-parser" -version = "10.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" -dependencies = [ - "asn1-rs 0.7.0", - "displaydoc", - "nom 7.1.3", - "num-bigint", - "num-traits", - "rusticata-macros", -] - -[[package]] -name = "der_derive" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.99", + "parking_lot_core", ] [[package]] name = "deranged" -version = "0.3.11" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" dependencies = [ "powerfmt", - "serde", ] [[package]] @@ -2058,81 +803,39 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "derive-new" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive_builder" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" -dependencies = [ - "derive_builder_macro", -] - -[[package]] -name = "derive_builder_core" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.99", -] - -[[package]] -name = "derive_builder_macro" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" -dependencies = [ - "derive_builder_core", - "syn 2.0.99", -] - [[package]] name = "derive_more" -version = "0.99.19" +version = "0.99.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version", - "syn 2.0.99", + "syn 2.0.103", ] [[package]] -name = "des" -version = "0.8.1" +name = "derive_more" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdd80ce8ce993de27e9f063a444a4d53ce8e8db4c1f00cc03af5ad5a9867a1e" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" dependencies = [ - "cipher", + "derive_more-impl", ] [[package]] -name = "deunicode" -version = "1.6.0" +name = "derive_more-impl" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "339544cc9e2c4dc3fc7149fd630c5f22263a4fdf18a98afd0075784968b5cf00" - -[[package]] -name = "difflib" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.103", + "unicode-xid", +] [[package]] name = "digest" @@ -2141,7 +844,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", - "const-oid", "crypto-common", "subtle", ] @@ -2154,28 +856,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", -] - -[[package]] -name = "doc-comment" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" - -[[package]] -name = "docx-rs" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e593b51d4fe95d69d70fd40da4b314b029736302c986c3c760826e842fd27dc3" -dependencies = [ - "base64 0.13.1", - "image", - "serde", - "serde_json", - "thiserror 1.0.69", - "xml-rs", - "zip", + "syn 2.0.103", ] [[package]] @@ -2184,132 +865,6 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" -[[package]] -name = "dotenvy" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" - -[[package]] -name = "downcast" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" - -[[package]] -name = "downcast-rs" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" - -[[package]] -name = "dummy" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac124e13ae9aa56acc4241f8c8207501d93afdd8d8e62f0c1f2e12f6508c65" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.99", -] - -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - -[[package]] -name = "dyn-clone" -version = "1.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" - -[[package]] -name = "ecdsa" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" -dependencies = [ - "der", - "digest", - "elliptic-curve", - "rfc6979", - "signature", - "spki", -] - -[[package]] -name = "ed25519" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" -dependencies = [ - "pkcs8", - "signature", -] - -[[package]] -name = "ed25519-dalek" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" -dependencies = [ - "curve25519-dalek", - "ed25519", - "serde", - "sha2", - "subtle", - "zeroize", -] - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" -dependencies = [ - "serde", -] - -[[package]] -name = "elliptic-curve" -version = "0.13.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct", - "crypto-bigint", - "digest", - "ff", - "generic-array", - "group", - "hkdf", - "pem-rfc7468", - "pkcs8", - "rand_core 0.6.4", - "sec1", - "subtle", - "zeroize", -] - -[[package]] -name = "email-encoding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a87260449b06739ee78d6281c68d2a0ff3e3af64a78df63d3a1aeb3c06997c8a" -dependencies = [ - "base64 0.22.1", - "memchr", -] - -[[package]] -name = "email_address" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449" - [[package]] name = "encoding_rs" version = "0.8.35" @@ -2329,35 +884,16 @@ dependencies = [ "regex", ] -[[package]] -name = "env_home" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" - [[package]] name = "env_logger" -version = "0.10.2" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" -dependencies = [ - "humantime", - "is-terminal", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "env_logger" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" dependencies = [ "anstream", "anstyle", "env_filter", - "humantime", + "jiff", "log", ] @@ -2369,23 +905,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.10" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "etcetera" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" -dependencies = [ - "cfg-if", - "home", - "windows-sys 0.48.0", + "windows-sys 0.60.2", ] [[package]] @@ -2407,189 +932,42 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ "event-listener 5.4.0", "pin-project-lite", ] -[[package]] -name = "executor-trait" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c39dff9342e4e0e16ce96be751eb21a94e94a87bb2f6e63ad1961c2ce109bf" -dependencies = [ - "async-trait", -] - -[[package]] -name = "exr" -version = "1.73.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" -dependencies = [ - "bit_field", - "half", - "lebe", - "miniz_oxide", - "rayon-core", - "smallvec", - "zune-inflate", -] - -[[package]] -name = "fail" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be3c61c59fdc91f5dbc3ea31ee8623122ce80057058be560654c5d410d181a6" -dependencies = [ - "lazy_static", - "log", - "rand 0.7.3", -] - -[[package]] -name = "fake" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d391ba4af7f1d93f01fcf7b2f29e2bc9348e109dfdbf4dcbdc51dfa38dab0b6" -dependencies = [ - "deunicode", - "dummy", - "rand 0.8.5", -] - -[[package]] -name = "fantoccini" -version = "0.19.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65f0fbe245d714b596ba5802b46f937f5ce68dcae0f32f9a70b5c3b04d3c6f64" -dependencies = [ - "base64 0.13.1", - "cookie 0.16.2", - "futures-core", - "futures-util", - "http 0.2.12", - "hyper 0.14.32", - "hyper-tls 0.5.0", - "mime", - "serde", - "serde_json", - "time", - "tokio", - "url", - "webdriver", -] - -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - [[package]] name = "fastrand" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" -[[package]] -name = "fdeflate" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "ff" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "fiat-crypto" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" - -[[package]] -name = "filetime" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" -dependencies = [ - "cfg-if", - "libc", - "libredox", - "windows-sys 0.59.0", -] - -[[package]] -name = "fixedbitset" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" - -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - -[[package]] -name = "flagset" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3ea1ec5f8307826a5b71094dd91fc04d4ae75d5709b20ad351c7fb4815c86ec" - [[package]] name = "flate2" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" dependencies = [ "crc32fast", "miniz_oxide", ] -[[package]] -name = "float-cmp" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" -dependencies = [ - "num-traits", -] - -[[package]] -name = "flume" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" -dependencies = [ - "futures-core", - "futures-sink", - "nanorand", - "spin 0.9.8", -] - [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "foreign-types" version = "0.3.2" @@ -2614,18 +992,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fragile" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" - -[[package]] -name = "futures" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" - [[package]] name = "futures" version = "0.3.31" @@ -2666,18 +1032,6 @@ dependencies = [ "futures-core", "futures-task", "futures-util", - "num_cpus", -] - -[[package]] -name = "futures-intrusive" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" -dependencies = [ - "futures-core", - "lock_api", - "parking_lot 0.12.3", ] [[package]] @@ -2686,28 +1040,13 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - [[package]] name = "futures-lite" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" dependencies = [ - "fastrand 2.3.0", + "fastrand", "futures-core", "futures-io", "parking", @@ -2722,7 +1061,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.103", ] [[package]] @@ -2737,19 +1076,12 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" -[[package]] -name = "futures-timer" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" - [[package]] name = "futures-util" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ - "futures 0.1.31", "futures-channel", "futures-core", "futures-io", @@ -2763,415 +1095,23 @@ dependencies = [ ] [[package]] -name = "gb-auth" -version = "0.1.0" -dependencies = [ - "argon2", - "async-trait", - "axum 0.7.9", - "axum-extra", - "chrono", - "gb-core", - "headers", - "jsonwebtoken", - "mockall", - "oauth2", - "openid", - "rand 0.8.5", - "redis", - "ring 0.17.13", - "rstest", - "serde", - "serde_json", - "sqlx", - "thiserror 1.0.69", - "tokio", - "tokio-openssl", - "tokio-stream", - "tokio-test", - "tower 0.4.13", - "tower-http", - "tracing", - "uuid", - "validator", -] - -[[package]] -name = "gb-automation" -version = "0.1.0" -dependencies = [ - "async-recursion", - "async-trait", - "chromiumoxide", - "fantoccini", - "futures-util", - "gb-core", - "headless_chrome", - "image", - "mock_instant", - "regex", - "rstest", - "serde", - "serde_json", - "thiserror 1.0.69", - "tokio", - "tokio-test", - "tracing", - "uuid", -] - -[[package]] -name = "gb-calendar" -version = "0.1.0" -dependencies = [ - "gb-core", -] - -[[package]] -name = "gb-cloud" -version = "0.1.0" -dependencies = [ - "async-trait", - "gb-core", - "rstest", - "serde", - "tempfile", - "thiserror 1.0.69", - "tokio", - "tokio-test", - "tracing", -] - -[[package]] -name = "gb-core" -version = "0.1.0" -dependencies = [ - "actix-web", - "anyhow", - "async-trait", - "axum 0.7.9", - "chrono", - "jsonwebtoken", - "lettre", - "minio", - "mockall", - "rdkafka", - "redis", - "rstest", - "serde", - "serde_json", - "sqlx", - "thiserror 1.0.69", - "tokio", - "tokio-test", - "tokio-tungstenite 0.24.0", - "tonic 0.10.2", - "tracing", - "uuid", - "zitadel", -] - -[[package]] -name = "gb-document" -version = "0.1.0" -dependencies = [ - "async-trait", - "calamine", - "docx-rs", - "encoding_rs", - "gb-core", - "lopdf", - "rstest", - "serde", - "serde_json", - "tempfile", - "thiserror 1.0.69", - "tokio", - "tokio-test", - "tracing", - "zip", -] - -[[package]] -name = "gb-file" +name = "gbserver" version = "0.1.0" dependencies = [ "actix-multipart", "actix-web", - "async-trait", - "env_logger 0.10.2", - "futures 0.3.31", - "gb-core", - "jsonwebtoken", - "lettre", + "dotenv", "log", "minio", - "rstest", - "sanitize-filename", "serde", "serde_json", "tempfile", - "thiserror 1.0.69", "tokio", "tokio-stream", - "tokio-test", - "tracing", - "uuid", -] - -[[package]] -name = "gb-image" -version = "0.1.0" -dependencies = [ - "async-trait", - "gb-core", - "image", - "imageproc", - "reqwest 0.11.27", - "rstest", - "rusttype", - "serde", - "serde_json", - "tempfile", - "thiserror 1.0.69", - "tokio", - "tokio-test", - "tracing", -] - -[[package]] -name = "gb-infra" -version = "0.1.0" -dependencies = [ - "ctrlc", - "dotenv", - "flate2", - "reqwest 0.11.27", - "serde", - "serde_json", - "tar", - "tokio", - "zip", -] - -[[package]] -name = "gb-llm" -version = "0.1.0" -dependencies = [ - "async-trait", - "gb-core", - "rstest", - "thiserror 1.0.69", - "tokio", - "tracing", -] - -[[package]] -name = "gb-media" -version = "0.1.0" -dependencies = [ - "anyhow", - "async-trait", - "gb-core", - "gstreamer", - "mockall", - "opus", - "rstest", - "serde", - "tokio", - "tokio-test", - "tracing", - "uuid", - "webrtc", -] - -[[package]] -name = "gb-messaging" -version = "0.1.0" -dependencies = [ - "async-trait", - "chrono", - "futures 0.3.31", - "futures-util", - "gb-core", - "lapin", - "rdkafka", - "redis", - "rstest", - "serde", - "serde_json", - "tokio", - "tokio-test", - "tokio-tungstenite 0.24.0", - "tracing", - "uuid", -] - -[[package]] -name = "gb-migrations" -version = "0.1.0" -dependencies = [ - "chrono", - "gb-core", - "rstest", - "serde_json", - "sqlx", - "tokio", - "tracing", - "uuid", -] - -[[package]] -name = "gb-monitoring" -version = "0.1.0" -dependencies = [ - "gb-core", - "lazy_static", - "opentelemetry 0.19.0", - "opentelemetry-otlp", - "prometheus 0.13.4", - "rstest", - "serde", - "serde_json", - "thiserror 1.0.69", - "tokio", - "tokio-test", "tracing", "tracing-subscriber", ] -[[package]] -name = "gb-server" -version = "0.1.0" -dependencies = [ - "actix-web", - "async-trait", - "axum 0.7.9", - "chrono", - "dotenv", - "futures-util", - "gb-core", - "gb-file", - "gb-messaging", - "gb-monitoring", - "hyper 1.6.0", - "hyper-util", - "log", - "redis", - "rstest", - "serde", - "serde_json", - "sqlx", - "tokio", - "tokio-stream", - "tokio-test", - "tower 0.4.13", - "tower-http", - "tracing", - "tracing-subscriber", - "uuid", - "vector", -] - -[[package]] -name = "gb-storage" -version = "0.1.0" -dependencies = [ - "async-trait", - "chrono", - "gb-core", - "mockall", - "redis", - "rstest", - "serde", - "serde_json", - "sqlx", - "tikv-client", - "tokio", - "tokio-test", - "tracing", - "uuid", -] - -[[package]] -name = "gb-testing" -version = "0.1.0" -dependencies = [ - "actix-multipart", - "actix-web", - "anyhow", - "assert_cmd", - "async-trait", - "bytes", - "chrono", - "criterion", - "fake", - "futures 0.3.31", - "gb-auth", - "gb-core", - "gb-file", - "gb-server", - "goose", - "hyper 1.6.0", - "jmap-client", - "minio", - "opentelemetry 0.20.0", - "predicates", - "prometheus 0.13.4", - "rand 0.8.5", - "redis", - "reqwest 0.11.27", - "rstest", - "sanitize-filename", - "serde", - "serde_json", - "sqlx", - "tempfile", - "tokio", - "tokio-stream", - "tokio-tungstenite 0.24.0", - "tracing", - "tungstenite 0.20.1", - "uuid", - "wiremock", -] - -[[package]] -name = "gb-utils" -version = "0.1.0" -dependencies = [ - "async-trait", - "gb-core", - "gb-document", - "gb-image", - "mime", - "mime_guess", - "rstest", - "serde", - "serde_json", - "thiserror 1.0.69", - "tokio", - "tokio-test", - "tracing", - "uuid", -] - -[[package]] -name = "gb-vm" -version = "0.1.0" -dependencies = [ - "async-trait", - "gb-core", - "rstest", - "serde", - "serde_json", - "tempfile", - "thiserror 1.0.69", - "tokio", - "tokio-test", - "tracing", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -3180,63 +1120,29 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", - "zeroize", ] [[package]] name = "getrandom" -version = "0.1.16" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "wasi 0.9.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", ] [[package]] name = "getrandom" -version = "0.2.15" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets 0.52.6", -] - -[[package]] -name = "ghash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" -dependencies = [ - "opaque-debug", - "polyval", -] - -[[package]] -name = "gif" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" -dependencies = [ - "color_quant", - "weezl", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] [[package]] @@ -3245,72 +1151,6 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" -[[package]] -name = "gio-sys" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", - "winapi", -] - -[[package]] -name = "glib" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" -dependencies = [ - "bitflags 2.9.0", - "futures-channel", - "futures-core", - "futures-executor", - "futures-task", - "futures-util", - "gio-sys", - "glib-macros", - "glib-sys", - "gobject-sys", - "libc", - "memchr", - "once_cell", - "smallvec", - "thiserror 1.0.69", -] - -[[package]] -name = "glib-macros" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" -dependencies = [ - "heck 0.4.1", - "proc-macro-crate", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.99", -] - -[[package]] -name = "glib-sys" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" -dependencies = [ - "libc", - "system-deps", -] - -[[package]] -name = "glob" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" - [[package]] name = "gloo-timers" version = "0.3.0" @@ -3323,162 +1163,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "gobject-sys" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" -dependencies = [ - "glib-sys", - "libc", - "system-deps", -] - -[[package]] -name = "goose" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cfeedc01d217935e1371901ea642ea6693d68893c67336d146eba23be04bf11" -dependencies = [ - "async-trait", - "chrono", - "ctrlc", - "downcast-rs", - "flume", - "futures 0.3.31", - "gumdrop", - "http 0.2.12", - "itertools 0.11.0", - "lazy_static", - "log", - "num-format", - "rand 0.8.5", - "regex", - "reqwest 0.11.27", - "serde", - "serde_json", - "simplelog", - "strum", - "strum_macros", - "tokio", - "tokio-tungstenite 0.20.1", - "tungstenite 0.20.1", - "url", -] - -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "grpcio" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cf790272c5fb75a2fd7f2e8282e910d0fe0ed1d954cb29b07b74228694302a" -dependencies = [ - "bytes", - "futures 0.3.31", - "grpcio-sys", - "libc", - "log", - "parking_lot 0.11.2", - "prost 0.7.0", -] - -[[package]] -name = "grpcio-compiler" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375292b9a9e3f5f9c6ef978d1f28070a6b56ab78f8be0cfbee16c62d5b0fa361" -dependencies = [ - "derive-new", - "prost 0.11.9", - "prost-build 0.11.9", - "prost-types 0.11.9", - "tempfile", -] - -[[package]] -name = "grpcio-sys" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f89a56d830be4dddc939c377c95e3b77e30c86a8df99c20095c34cf9038447b" -dependencies = [ - "bindgen", - "boringssl-src", - "cc", - "cmake", - "libc", - "libz-sys", - "openssl-sys", - "pkg-config", - "walkdir", -] - -[[package]] -name = "gstreamer" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de95703f4c8e79f4f4e42279cf1ab0e5a46b7ece4a9dfcd16424164af7be9055" -dependencies = [ - "cfg-if", - "futures-channel", - "futures-core", - "futures-util", - "glib", - "gstreamer-sys", - "itertools 0.12.1", - "libc", - "muldiv", - "num-integer", - "num-rational", - "option-operations", - "paste", - "pin-project-lite", - "pretty-hex", - "smallvec", - "thiserror 1.0.69", -] - -[[package]] -name = "gstreamer-sys" -version = "0.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "564cda782b3e6eed1b81cb4798a06794db56440fb05b422505be689f34ce3bc4" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", -] - -[[package]] -name = "gumdrop" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bc700f989d2f6f0248546222d9b4258f5b02a171a431f8285a81c08142629e3" -dependencies = [ - "gumdrop_derive", -] - -[[package]] -name = "gumdrop_derive" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729f9bd3449d77e7831a18abfb7ba2f99ee813dfd15b8c2167c9a54ba20aa99d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "h2" version = "0.3.26" @@ -3491,7 +1175,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.7.1", + "indexmap", "slab", "tokio", "tokio-util", @@ -3500,152 +1184,40 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2" +checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" dependencies = [ "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "http 1.2.0", - "indexmap 2.7.1", + "http 1.3.1", + "indexmap", "slab", "tokio", "tokio-util", "tracing", ] -[[package]] -name = "half" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" -dependencies = [ - "cfg-if", - "crunchy", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - [[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", - "allocator-api2", -] [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" - -[[package]] -name = "hashlink" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" -dependencies = [ - "hashbrown 0.14.5", -] - -[[package]] -name = "headers" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" -dependencies = [ - "base64 0.21.7", - "bytes", - "headers-core", - "http 0.2.12", - "httpdate", - "mime", - "sha1", -] - -[[package]] -name = "headers-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" -dependencies = [ - "http 0.2.12", -] - -[[package]] -name = "headless_chrome" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c268ea01c2902b2acb382c1fae26818113dd661e0dba036a893f0ba40f00cdd8" -dependencies = [ - "anyhow", - "auto_generate_cdp", - "base64 0.22.1", - "derive_builder", - "log", - "rand 0.9.0", - "regex", - "serde", - "serde_json", - "tempfile", - "thiserror 2.0.12", - "tungstenite 0.26.2", - "url", - "which 7.0.2", - "winreg 0.55.0", -] - -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" [[package]] name = "hermit-abi" -version = "0.3.9" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" - -[[package]] -name = "hermit-abi" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -3653,15 +1225,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "hkdf" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" -dependencies = [ - "hmac", -] - [[package]] name = "hmac" version = "0.12.1" @@ -3671,26 +1234,6 @@ dependencies = [ "digest", ] -[[package]] -name = "home" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "hostname" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" -dependencies = [ - "libc", - "match_cfg", - "winapi", -] - [[package]] name = "http" version = "0.2.12" @@ -3704,26 +1247,15 @@ dependencies = [ [[package]] name = "http" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", "itoa", ] -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - [[package]] name = "http-body" version = "1.0.1" @@ -3731,49 +1263,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.2.0", + "http 1.3.1", ] [[package]] name = "http-body-util" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", - "futures-util", - "http 1.2.0", - "http-body 1.0.1", + "futures-core", + "http 1.3.1", + "http-body", "pin-project-lite", ] -[[package]] -name = "http-range-header" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c" - -[[package]] -name = "http-types" -version = "2.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e9b187a72d63adbfba487f48095306ac823049cb504ee195541e91c7775f5ad" -dependencies = [ - "anyhow", - "async-channel 1.9.0", - "base64 0.13.1", - "futures-lite 1.13.0", - "http 0.2.12", - "infer", - "pin-project-lite", - "rand 0.7.3", - "serde", - "serde_json", - "serde_qs", - "serde_urlencoded", - "url", -] - [[package]] name = "httparse" version = "1.10.1" @@ -3786,36 +1291,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "hyper" -version = "0.14.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.5.8", - "tokio", - "tower-service", - "tracing", - "want", -] - [[package]] name = "hyper" version = "1.6.0" @@ -3825,9 +1300,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.8", - "http 1.2.0", - "http-body 1.0.1", + "h2 0.4.10", + "http 1.3.1", + "http-body", "httparse", "httpdate", "itoa", @@ -3837,58 +1312,6 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http 0.2.12", - "hyper 0.14.32", - "rustls 0.21.12", - "tokio", - "tokio-rustls 0.24.1", -] - -[[package]] -name = "hyper-timeout" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" -dependencies = [ - "hyper 0.14.32", - "pin-project-lite", - "tokio", - "tokio-io-timeout", -] - -[[package]] -name = "hyper-timeout" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" -dependencies = [ - "hyper 1.6.0", - "hyper-util", - "pin-project-lite", - "tokio", - "tower-service", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper 0.14.32", - "native-tls", - "tokio", - "tokio-native-tls", -] - [[package]] name = "hyper-tls" version = "0.6.0" @@ -3897,7 +1320,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.6.0", + "hyper", "hyper-util", "native-tls", "tokio", @@ -3907,18 +1330,23 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" dependencies = [ + "base64", "bytes", "futures-channel", + "futures-core", "futures-util", - "http 1.2.0", - "http-body 1.0.1", - "hyper 1.6.0", + "http 1.3.1", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", "pin-project-lite", - "socket2 0.5.8", + "socket2", "tokio", "tower-service", "tracing", @@ -3926,14 +1354,15 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.61" +version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", "windows-core", ] @@ -3949,21 +1378,22 @@ dependencies = [ [[package]] name = "icu_collections" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" dependencies = [ "displaydoc", + "potential_utf", "yoke", "zerofrom", "zerovec", ] [[package]] -name = "icu_locid" -version = "1.5.0" +name = "icu_locale_core" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" dependencies = [ "displaydoc", "litemap", @@ -3972,31 +1402,11 @@ dependencies = [ "zerovec", ] -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - [[package]] name = "icu_normalizer" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" dependencies = [ "displaydoc", "icu_collections", @@ -4004,93 +1414,60 @@ dependencies = [ "icu_properties", "icu_provider", "smallvec", - "utf16_iter", - "utf8_iter", - "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" [[package]] name = "icu_properties" -version = "1.5.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" dependencies = [ "displaydoc", "icu_collections", - "icu_locid_transform", + "icu_locale_core", "icu_properties_data", "icu_provider", - "tinystr", + "potential_utf", + "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "1.5.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" [[package]] name = "icu_provider" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" dependencies = [ "displaydoc", - "icu_locid", - "icu_provider_macros", + "icu_locale_core", "stable_deref_trait", "tinystr", "writeable", "yoke", "zerofrom", + "zerotrie", "zerovec", ] -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.99", -] - [[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" -[[package]] -name = "idna" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "idna" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - [[package]] name = "idna" version = "1.0.3" @@ -4104,56 +1481,14 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", ] -[[package]] -name = "if_chain" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" - -[[package]] -name = "image" -version = "0.24.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "exr", - "gif", - "jpeg-decoder", - "num-traits", - "png", - "qoi", - "tiff", -] - -[[package]] -name = "imageproc" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aee993351d466301a29655d628bfc6f5a35a0d062b6160ca0808f425805fd7" -dependencies = [ - "approx", - "conv", - "image", - "itertools 0.10.5", - "nalgebra", - "num", - "rand 0.7.3", - "rand_distr", - "rayon", - "rusttype", -] - [[package]] name = "impl-more" version = "0.1.9" @@ -4162,79 +1497,12 @@ checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2" [[package]] name = "indexmap" -version = "1.9.3" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", -] - -[[package]] -name = "indexmap" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", - "hashbrown 0.15.2", - "serde", -] - -[[package]] -name = "infer" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" - -[[package]] -name = "inout" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" -dependencies = [ - "block-padding", - "generic-array", -] - -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "interceptor" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5927883184e6a819b22d5e4f5f7bc7ca134fde9b2026fbddd8d95249746ba21e" -dependencies = [ - "async-trait", - "bytes", - "log", - "rand 0.8.5", - "rtcp", - "rtp 0.9.0", - "thiserror 1.0.69", - "tokio", - "waitgroup", - "webrtc-srtp", - "webrtc-util", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.9", - "libc", - "windows-sys 0.48.0", + "hashbrown 0.15.4", ] [[package]] @@ -4244,14 +1512,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] -name = "is-terminal" -version = "0.4.16" +name = "iri-string" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" dependencies = [ - "hermit-abi 0.5.0", - "libc", - "windows-sys 0.59.0", + "memchr", + "serde", ] [[package]] @@ -4260,51 +1527,6 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" -[[package]] -name = "itertools" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.15" @@ -4312,40 +1534,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] -name = "jmap-client" -version = "0.1.0" +name = "jiff" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d478b6514a12725ee2653689846b49c8dd18c215dcc5b84ea02ba9b079bc4f" +checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" dependencies = [ - "ahash", - "async-stream", - "base64 0.13.1", - "chrono", - "futures-util", - "parking_lot 0.12.3", - "reqwest 0.11.27", + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", "serde", - "serde_json", +] + +[[package]] +name = "jiff-static" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.103", ] [[package]] name = "jobserver" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ + "getrandom 0.3.3", "libc", ] -[[package]] -name = "jpeg-decoder" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" -dependencies = [ - "rayon", -] - [[package]] name = "js-sys" version = "0.3.77" @@ -4356,21 +1577,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "jsonwebtoken" -version = "9.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" -dependencies = [ - "base64 0.22.1", - "js-sys", - "pem", - "ring 0.17.13", - "serde", - "serde_json", - "simple_asn1", -] - [[package]] name = "kv-log-macro" version = "1.0.7" @@ -4386,157 +1592,29 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" -[[package]] -name = "lapin" -version = "2.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3551b363b2fcf985fa39c47114333fa12fbb6518f863d4fd9556d0e19f48c1c9" -dependencies = [ - "amq-protocol", - "async-global-executor-trait", - "async-reactor-trait", - "async-trait", - "executor-trait", - "flume", - "futures-core", - "futures-io", - "parking_lot 0.12.3", - "pinky-swear", - "reactor-trait", - "serde", - "tracing", - "waker-fn", -] - [[package]] name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -dependencies = [ - "spin 0.9.8", -] - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "lebe" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" - -[[package]] -name = "lettre" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bd09637ae3ec7bd605b8e135e757980b3968430ff2b1a4a94fb7769e50166d" -dependencies = [ - "base64 0.21.7", - "email-encoding", - "email_address", - "fastrand 1.9.0", - "futures-util", - "hostname", - "httpdate", - "idna 0.3.0", - "mime", - "native-tls", - "nom 7.1.3", - "once_cell", - "quoted_printable", - "socket2 0.4.10", - "tokio", -] [[package]] name = "libc" -version = "0.2.170" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" - -[[package]] -name = "libloading" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" -dependencies = [ - "cfg-if", - "windows-targets 0.52.6", -] - -[[package]] -name = "libm" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" - -[[package]] -name = "libredox" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" -dependencies = [ - "bitflags 2.9.0", - "libc", - "redox_syscall 0.5.10", -] - -[[package]] -name = "libsqlite3-sys" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716" -dependencies = [ - "cc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "libz-sys" -version = "1.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9b68e50e6e0b26f672573834882eb57759f6db9b3be2ea3c35c91188bb4eaa" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - -[[package]] -name = "linux-raw-sys" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9c683daf087dc577b7506e9695b3d556a9f3849903fa28186283afd6809e9" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "litemap" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "local-channel" @@ -4557,9 +1635,9 @@ checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", @@ -4567,73 +1645,13 @@ dependencies = [ [[package]] name = "log" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" dependencies = [ "value-bag", ] -[[package]] -name = "lopdf" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c8e1b6184b1b32ea5f72f572ebdc40e5da1d2921fa469947ff7c480ad1f85a" -dependencies = [ - "chrono", - "encoding_rs", - "flate2", - "itoa", - "linked-hash-map", - "log", - "md5", - "nom 7.1.3", - "rayon", - "time", - "weezl", -] - -[[package]] -name = "match_cfg" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata 0.1.10", -] - -[[package]] -name = "matchit" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" - -[[package]] -name = "matrixmultiply" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" -dependencies = [ - "autocfg", - "rawpointer", -] - -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest", -] - [[package]] name = "md5" version = "0.7.0" @@ -4642,18 +1660,9 @@ checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "mime" @@ -4661,179 +1670,74 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "mime_guess" -version = "2.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" -dependencies = [ - "mime", - "unicase", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "minio" -version = "0.2.0-alpha" -source = "git+https://github.com/minio/minio-rs?branch=master#112c0aed1a01720e4c8bde726900a710d805303a" +version = "0.3.0" +source = "git+https://github.com/minio/minio-rs?branch=master#720943b4bbcbdcd718e5ac27c2f338df87d6fcd3" dependencies = [ "async-recursion", + "async-std", + "async-stream", "async-trait", - "base64 0.22.1", + "base64", "byteorder", "bytes", "chrono", "crc", - "dashmap 6.1.0", + "dashmap", "derivative", - "env_logger 0.11.6", + "env_logger", + "futures", "futures-util", "hex", "hmac", - "home", - "http 1.2.0", - "hyper 1.6.0", + "http 1.3.1", + "hyper", "lazy_static", "log", "md5", - "multimap 0.10.0", - "os_info", + "multimap", "percent-encoding", "rand 0.8.5", "regex", - "reqwest 0.12.12", + "reqwest", "serde", "serde_json", "sha2", - "tokio", - "tokio-stream", - "tokio-util", "urlencoding", "xmltree", ] [[package]] name = "miniz_oxide" -version = "0.8.5" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", - "simd-adler32", ] [[package]] name = "mio" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", -] - -[[package]] -name = "mock_instant" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "717e29a243b81f8130e31e24e04fb151b04a44b5a7d05370935f7d937e9de06d" - -[[package]] -name = "mockall" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43766c2b5203b10de348ffe19f7e54564b64f3d6018ff7648d1e2d6d3a0f0a48" -dependencies = [ - "cfg-if", - "downcast", - "fragile", - "lazy_static", - "mockall_derive", - "predicates", - "predicates-tree", -] - -[[package]] -name = "mockall_derive" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cbce79ec385a1d4f54baa90a76401eb15d9cab93685f62e7e9f942aa00ae2" -dependencies = [ - "cfg-if", - "proc-macro2", - "quote", - "syn 2.0.99", -] - -[[package]] -name = "muldiv" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956787520e75e9bd233246045d19f42fb73242759cc57fba9611d940ae96d4b0" - -[[package]] -name = "multer" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" -dependencies = [ - "bytes", - "encoding_rs", - "futures-util", - "http 1.2.0", - "httparse", - "memchr", - "mime", - "spin 0.9.8", - "version_check", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", ] [[package]] name = "multimap" -version = "0.8.3" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" - -[[package]] -name = "multimap" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" dependencies = [ "serde", ] -[[package]] -name = "nalgebra" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb2d0de08694bed883320212c18ee3008576bfe8c306f4c3c4a58b4876998be" -dependencies = [ - "approx", - "matrixmultiply", - "num-complex", - "num-rational", - "num-traits", - "simba", - "typenum", -] - -[[package]] -name = "nanorand" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" -dependencies = [ - "getrandom 0.2.15", -] - [[package]] name = "native-tls" version = "0.2.14" @@ -4846,62 +1750,11 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework 2.11.1", + "security-framework", "security-framework-sys", "tempfile", ] -[[package]] -name = "nix" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset", - "pin-utils", -] - -[[package]] -name = "nix" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" -dependencies = [ - "bitflags 2.9.0", - "cfg-if", - "cfg_aliases", - "libc", -] - -[[package]] -name = "nom" -version = "5.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08959a387a676302eebf4ddbcbc611da04285579f76f88ee0506c63b1a61dd4b" -dependencies = [ - "memchr", - "version_check", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "normalize-line-endings" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -4912,103 +1765,12 @@ dependencies = [ "winapi", ] -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-bigint-dig" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" -dependencies = [ - "byteorder", - "lazy_static", - "libm", - "num-integer", - "num-iter", - "num-traits", - "rand 0.8.5", - "smallvec", - "zeroize", -] - -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" -[[package]] -name = "num-format" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" -dependencies = [ - "arrayvec", - "itoa", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -5016,67 +1778,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.9", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.99", -] - -[[package]] -name = "num_threads" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" -dependencies = [ - "libc", -] - -[[package]] -name = "oauth2" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c38841cdd844847e3e7c8d29cef9dcfed8877f8f56f9071f77843ecf3baf937f" -dependencies = [ - "base64 0.13.1", - "chrono", - "getrandom 0.2.15", - "http 0.2.12", - "rand 0.8.5", - "reqwest 0.11.27", - "serde", - "serde_json", - "serde_path_to_error", - "sha2", - "thiserror 1.0.69", - "url", ] [[package]] @@ -5088,100 +1789,25 @@ dependencies = [ "memchr", ] -[[package]] -name = "oid-registry" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" -dependencies = [ - "asn1-rs 0.5.2", -] - -[[package]] -name = "oid-registry" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7" -dependencies = [ - "asn1-rs 0.7.0", -] - [[package]] name = "once_cell" -version = "1.20.3" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] -name = "oorandom" -version = "11.1.5" +name = "once_cell_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" - -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - -[[package]] -name = "openid" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbe1792e10fb9ec5a27aad80a8471a2f5cf013dfac32db439b024d66cf97e7be" -dependencies = [ - "base64 0.21.7", - "biscuit", - "chrono", - "lazy_static", - "mime", - "reqwest 0.11.27", - "serde", - "serde_json", - "thiserror 1.0.69", - "url", - "validator", -] - -[[package]] -name = "openidconnect" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f47e80a9cfae4462dd29c41e987edd228971d6565553fbc14b8a11e666d91590" -dependencies = [ - "base64 0.13.1", - "chrono", - "dyn-clone", - "ed25519-dalek", - "hmac", - "http 0.2.12", - "itertools 0.10.5", - "log", - "oauth2", - "p256", - "p384", - "rand 0.8.5", - "rsa", - "serde", - "serde-value", - "serde_derive", - "serde_json", - "serde_path_to_error", - "serde_plain", - "serde_with", - "sha2", - "subtle", - "thiserror 1.0.69", - "url", -] +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" [[package]] name = "openssl" -version = "0.10.71" +version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ - "bitflags 2.9.0", + "bitflags", "cfg-if", "foreign-types", "libc", @@ -5198,7 +1824,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.103", ] [[package]] @@ -5207,263 +1833,24 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" -[[package]] -name = "openssl-src" -version = "300.4.2+3.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168ce4e058f975fe43e89d9ccf78ca668601887ae736090aacc23ae353c298e2" -dependencies = [ - "cc", -] - [[package]] name = "openssl-sys" -version = "0.9.106" +version = "0.9.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" dependencies = [ "cc", "libc", - "openssl-src", "pkg-config", "vcpkg", ] -[[package]] -name = "opentelemetry" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4b8347cc26099d3aeee044065ecc3ae11469796b4d65d065a23a584ed92a6f" -dependencies = [ - "opentelemetry_api 0.19.0", - "opentelemetry_sdk 0.19.0", -] - -[[package]] -name = "opentelemetry" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9591d937bc0e6d2feb6f71a559540ab300ea49955229c347a517a28d27784c54" -dependencies = [ - "opentelemetry_api 0.20.0", - "opentelemetry_sdk 0.20.0", -] - -[[package]] -name = "opentelemetry-otlp" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8af72d59a4484654ea8eb183fea5ae4eb6a41d7ac3e3bae5f4d2a282a3a7d3ca" -dependencies = [ - "async-trait", - "futures 0.3.31", - "futures-util", - "http 0.2.12", - "opentelemetry 0.19.0", - "opentelemetry-proto", - "prost 0.11.9", - "thiserror 1.0.69", - "tokio", - "tonic 0.8.3", -] - -[[package]] -name = "opentelemetry-proto" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "045f8eea8c0fa19f7d48e7bc3128a39c2e5c533d5c61298c548dfefc1064474c" -dependencies = [ - "futures 0.3.31", - "futures-util", - "opentelemetry 0.19.0", - "prost 0.11.9", - "tonic 0.8.3", -] - -[[package]] -name = "opentelemetry_api" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed41783a5bf567688eb38372f2b7a8530f5a607a4b49d38dd7573236c23ca7e2" -dependencies = [ - "fnv", - "futures-channel", - "futures-util", - "indexmap 1.9.3", - "once_cell", - "pin-project-lite", - "thiserror 1.0.69", - "urlencoding", -] - -[[package]] -name = "opentelemetry_api" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a81f725323db1b1206ca3da8bb19874bbd3f57c3bcd59471bfb04525b265b9b" -dependencies = [ - "futures-channel", - "futures-util", - "indexmap 1.9.3", - "js-sys", - "once_cell", - "pin-project-lite", - "thiserror 1.0.69", - "urlencoding", -] - -[[package]] -name = "opentelemetry_sdk" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b3a2a91fdbfdd4d212c0dcc2ab540de2c2bcbbd90be17de7a7daf8822d010c1" -dependencies = [ - "async-trait", - "crossbeam-channel", - "dashmap 5.5.3", - "fnv", - "futures-channel", - "futures-executor", - "futures-util", - "once_cell", - "opentelemetry_api 0.19.0", - "percent-encoding", - "rand 0.8.5", - "thiserror 1.0.69", - "tokio", - "tokio-stream", -] - -[[package]] -name = "opentelemetry_sdk" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa8e705a0612d48139799fcbaba0d4a90f06277153e43dd2bdc16c6f0edd8026" -dependencies = [ - "async-trait", - "crossbeam-channel", - "futures-channel", - "futures-executor", - "futures-util", - "once_cell", - "opentelemetry_api 0.20.0", - "ordered-float 3.9.2", - "percent-encoding", - "rand 0.8.5", - "thiserror 1.0.69", - "tokio", - "tokio-stream", -] - -[[package]] -name = "option-operations" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c26d27bb1aeab65138e4bf7666045169d1717febcc9ff870166be8348b223d0" -dependencies = [ - "paste", -] - -[[package]] -name = "opus" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6526409b274a7e98e55ff59d96aafd38e6cd34d46b7dbbc32ce126dffcd75e8e" -dependencies = [ - "audiopus_sys", - "libc", -] - -[[package]] -name = "ordered-float" -version = "2.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" -dependencies = [ - "num-traits", -] - -[[package]] -name = "ordered-float" -version = "3.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1e1c390732d15f1d48471625cd92d154e66db2c56645e29a9cd26f4699f72dc" -dependencies = [ - "num-traits", -] - -[[package]] -name = "os_info" -version = "3.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a604e53c24761286860eba4e2c8b23a0161526476b1de520139d69cdb85a6b5" -dependencies = [ - "log", - "serde", - "windows-sys 0.52.0", -] - [[package]] name = "overload" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" -[[package]] -name = "owned_ttf_parser" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e6affeb1632d6ff6a23d2cd40ffed138e82f1532571a26f527c8a284bb2fbb" -dependencies = [ - "ttf-parser", -] - -[[package]] -name = "p12-keystore" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a09eaa3a6d8884c204c2ab17e313f563b524362e62567f09ba27857a6e31257f" -dependencies = [ - "cbc", - "cms", - "der", - "des", - "hex", - "hmac", - "pkcs12", - "pkcs5", - "rand 0.9.0", - "rc2", - "sha1", - "sha2", - "thiserror 2.0.12", - "x509-parser 0.17.0", -] - -[[package]] -name = "p256" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" -dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2", -] - -[[package]] -name = "p384" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" -dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2", -] - [[package]] name = "parking" version = "2.2.1" @@ -5472,163 +1859,32 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.11.2" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", - "parking_lot_core 0.9.10", + "parking_lot_core", ] [[package]] name = "parking_lot_core" -version = "0.8.6" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.10", + "redox_syscall", "smallvec", "windows-targets 0.52.6", ] [[package]] -name = "password-hash" -version = "0.4.2" +name = "parse-size" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "password-hash" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "pbjson" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e6349fa080353f4a597daffd05cb81572a9c031a6d4fff7e504947496fcc68" -dependencies = [ - "base64 0.21.7", - "serde", -] - -[[package]] -name = "pbjson-build" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eea3058763d6e656105d1403cb04e0a41b7bbac6362d413e7c33be0c32279c9" -dependencies = [ - "heck 0.5.0", - "itertools 0.13.0", - "prost 0.13.5", - "prost-types 0.13.5", -] - -[[package]] -name = "pbjson-types" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e54e5e7bfb1652f95bc361d76f3c780d8e526b134b85417e774166ee941f0887" -dependencies = [ - "bytes", - "chrono", - "pbjson", - "pbjson-build", - "prost 0.13.5", - "prost-build 0.13.5", - "serde", -] - -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest", - "hmac", - "password-hash 0.4.2", - "sha2", -] - -[[package]] -name = "pbkdf2" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" -dependencies = [ - "digest", - "hmac", -] - -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - -[[package]] -name = "pem" -version = "3.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" -dependencies = [ - "base64 0.22.1", - "serde", -] - -[[package]] -name = "pem-rfc7468" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" -dependencies = [ - "base64ct", -] +checksum = "487f2ccd1e17ce8c1bfab3a65c89525af41cfad4c8659021a1e9a2aacd73b89b" [[package]] name = "percent-encoding" @@ -5636,46 +1892,6 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" -[[package]] -name = "petgraph" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" -dependencies = [ - "fixedbitset 0.2.0", - "indexmap 1.9.3", -] - -[[package]] -name = "petgraph" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" -dependencies = [ - "fixedbitset 0.4.2", - "indexmap 2.7.1", -] - -[[package]] -name = "pin-project" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.99", -] - [[package]] name = "pin-project-lite" version = "0.2.16" @@ -5688,18 +1904,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "pinky-swear" -version = "6.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cfae3ead413ca051a681152bd266438d3bfa301c9bdf836939a14c721bb2a21" -dependencies = [ - "doc-comment", - "flume", - "parking_lot 0.12.3", - "tracing", -] - [[package]] name = "piper" version = "0.2.4" @@ -5707,149 +1911,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", - "fastrand 2.3.0", + "fastrand", "futures-io", ] -[[package]] -name = "pkcs1" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" -dependencies = [ - "der", - "pkcs8", - "spki", -] - -[[package]] -name = "pkcs12" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "695b3df3d3cc1015f12d70235e35b6b79befc5fa7a9b95b951eab1dd07c9efc2" -dependencies = [ - "cms", - "const-oid", - "der", - "digest", - "spki", - "x509-cert", - "zeroize", -] - -[[package]] -name = "pkcs5" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6" -dependencies = [ - "aes", - "cbc", - "der", - "pbkdf2 0.12.2", - "scrypt", - "sha2", - "spki", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "spki", -] - [[package]] name = "pkg-config" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" -[[package]] -name = "plotters" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" - -[[package]] -name = "plotters-svg" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" -dependencies = [ - "plotters-backend", -] - -[[package]] -name = "png" -version = "0.17.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" -dependencies = [ - "bitflags 1.3.2", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - [[package]] name = "polling" -version = "2.8.0" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "concurrent-queue", - "libc", - "log", - "pin-project-lite", - "windows-sys 0.48.0", -] - -[[package]] -name = "polling" -version = "3.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" +checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi 0.4.0", + "hermit-abi", "pin-project-lite", - "rustix 0.38.44", + "rustix", "tracing", "windows-sys 0.59.0", ] [[package]] -name = "polyval" -version = "0.6.2" +name = "portable-atomic" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" dependencies = [ - "cfg-if", - "cpufeatures", - "opaque-debug", - "universal-hash", + "portable-atomic", +] + +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", ] [[package]] @@ -5860,441 +1968,36 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.7.35", -] - -[[package]] -name = "predicates" -version = "3.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" -dependencies = [ - "anstyle", - "difflib", - "float-cmp", - "normalize-line-endings", - "predicates-core", - "regex", -] - -[[package]] -name = "predicates-core" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" - -[[package]] -name = "predicates-tree" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" -dependencies = [ - "predicates-core", - "termtree", -] - -[[package]] -name = "pretty-hex" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbc83ee4a840062f368f9096d80077a9841ec117e17e7f700df81958f1451254" - -[[package]] -name = "prettyplease" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" -dependencies = [ - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "prettyplease" -version = "0.2.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1ccf34da56fc294e7d4ccf69a85992b7dfb826b7cf57bac6a70bba3494cc08a" -dependencies = [ - "proc-macro2", - "syn 2.0.99", -] - -[[package]] -name = "primeorder" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" -dependencies = [ - "elliptic-curve", -] - -[[package]] -name = "proc-macro-crate" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" -dependencies = [ - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", + "zerocopy", ] [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] -[[package]] -name = "procfs" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab8809e0c18450a2db0f236d2a44ec0b4c1412d0eb936233579f0990faa5d5cd" -dependencies = [ - "bitflags 1.3.2", - "byteorder", - "flate2", - "hex", - "lazy_static", - "libc", -] - -[[package]] -name = "procfs" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "731e0d9356b0c25f16f33b5be79b1c57b562f141ebfcdb0ad8ac2c13a24293b4" -dependencies = [ - "bitflags 2.9.0", - "hex", - "lazy_static", - "procfs-core", - "rustix 0.38.44", -] - -[[package]] -name = "procfs-core" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3554923a69f4ce04c4a754260c338f505ce22642d3830e049a399fc2059a29" -dependencies = [ - "bitflags 2.9.0", - "hex", -] - -[[package]] -name = "prometheus" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5986aa8d62380092d2f50f8b1cdba9cb9b6731ffd4b25b51fd126b6c3e05b99c" -dependencies = [ - "cfg-if", - "fnv", - "lazy_static", - "libc", - "memchr", - "parking_lot 0.11.2", - "procfs 0.9.1", - "protobuf", - "reqwest 0.11.27", - "thiserror 1.0.69", -] - -[[package]] -name = "prometheus" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" -dependencies = [ - "cfg-if", - "fnv", - "lazy_static", - "libc", - "memchr", - "parking_lot 0.12.3", - "procfs 0.16.0", - "protobuf", - "thiserror 1.0.69", -] - -[[package]] -name = "prost" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e6984d2f1a23009bd270b8bb56d0926810a3d483f59c987d77969e9d8e840b2" -dependencies = [ - "bytes", - "prost-derive 0.7.0", -] - -[[package]] -name = "prost" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" -dependencies = [ - "bytes", - "prost-derive 0.11.9", -] - -[[package]] -name = "prost" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" -dependencies = [ - "bytes", -] - -[[package]] -name = "prost" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" -dependencies = [ - "bytes", - "prost-derive 0.13.5", -] - -[[package]] -name = "prost-build" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d3ebd75ac2679c2af3a92246639f9fcc8a442ee420719cc4fe195b98dd5fa3" -dependencies = [ - "bytes", - "heck 0.3.3", - "itertools 0.9.0", - "log", - "multimap 0.8.3", - "petgraph 0.5.1", - "prost 0.7.0", - "prost-types 0.7.0", - "tempfile", - "which 4.4.2", -] - -[[package]] -name = "prost-build" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" -dependencies = [ - "bytes", - "heck 0.4.1", - "itertools 0.10.5", - "lazy_static", - "log", - "multimap 0.8.3", - "petgraph 0.6.5", - "prettyplease 0.1.25", - "prost 0.11.9", - "prost-types 0.11.9", - "regex", - "syn 1.0.109", - "tempfile", - "which 4.4.2", -] - -[[package]] -name = "prost-build" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" -dependencies = [ - "heck 0.5.0", - "itertools 0.13.0", - "log", - "multimap 0.10.0", - "once_cell", - "petgraph 0.6.5", - "prettyplease 0.2.30", - "prost 0.13.5", - "prost-types 0.13.5", - "regex", - "syn 2.0.99", - "tempfile", -] - -[[package]] -name = "prost-derive" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "169a15f3008ecb5160cba7d37bcd690a7601b6d30cfb87a117d45e59d52af5d4" -dependencies = [ - "anyhow", - "itertools 0.9.0", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "prost-derive" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" -dependencies = [ - "anyhow", - "itertools 0.10.5", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "prost-derive" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" -dependencies = [ - "anyhow", - "itertools 0.13.0", - "proc-macro2", - "quote", - "syn 2.0.99", -] - -[[package]] -name = "prost-types" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b518d7cdd93dab1d1122cf07fa9a60771836c668dde9d9e2a139f957f0d9f1bb" -dependencies = [ - "bytes", - "prost 0.7.0", -] - -[[package]] -name = "prost-types" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" -dependencies = [ - "prost 0.11.9", -] - -[[package]] -name = "prost-types" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" -dependencies = [ - "prost 0.13.5", -] - -[[package]] -name = "protobuf" -version = "2.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" - -[[package]] -name = "protobuf-build" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a7266835d38c38c73b091a24412de1f4b4382a5195fab1ec038161582b03b78" -dependencies = [ - "bitflags 1.3.2", - "grpcio-compiler", - "proc-macro2", - "prost-build 0.7.0", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "psl-types" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" - -[[package]] -name = "publicsuffix" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42ea446cab60335f76979ec15e12619a2165b5ae2c12166bef27d283a9fadf" -dependencies = [ - "idna 1.0.3", - "psl-types", -] - -[[package]] -name = "qoi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "quick-xml" -version = "0.28.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce5e73202a820a31f8a0ee32ada5e21029c81fd9e3ebf668a40832e4219d9d1" -dependencies = [ - "encoding_rs", - "memchr", -] - [[package]] name = "quote" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] [[package]] -name = "quoted_printable" -version = "0.4.8" +name = "r-efi" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3866219251662ec3b26fc217e3e05bf9c4f84325234dfb96bf0bf840889e49" - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rand" @@ -6309,23 +2012,12 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", - "zerocopy 0.8.23", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", ] [[package]] @@ -6348,22 +2040,13 @@ dependencies = [ "rand_core 0.9.3", ] -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", ] [[package]] @@ -6372,166 +2055,16 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.1", -] - -[[package]] -name = "rand_distr" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96977acbdd3a6576fb1d27391900035bf3863d4a16422973a409b488cf29ffb2" -dependencies = [ - "rand 0.7.3", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "random" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c7093a82705b48f10d4b165c6482dbe9f58cd63a870d85537e857b2badbd88" - -[[package]] -name = "rawpointer" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" - -[[package]] -name = "rayon" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "rc2" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62c64daa8e9438b84aaae55010a93f396f8e60e3911590fcba770d04643fc1dd" -dependencies = [ - "cipher", -] - -[[package]] -name = "rcgen" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52c4f3084aa3bc7dfbba4eff4fab2a54db4324965d8872ab933565e6fbd83bc6" -dependencies = [ - "pem", - "ring 0.16.20", - "time", - "x509-parser 0.15.1", - "yasna", -] - -[[package]] -name = "rdkafka" -version = "0.36.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1beea247b9a7600a81d4cc33f659ce1a77e1988323d7d2809c7ed1c21f4c316d" -dependencies = [ - "futures-channel", - "futures-util", - "libc", - "log", - "rdkafka-sys", - "serde", - "serde_derive", - "serde_json", - "slab", - "tokio", -] - -[[package]] -name = "rdkafka-sys" -version = "4.8.0+2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced38182dc436b3d9df0c77976f37a67134df26b050df1f0006688e46fc4c8be" -dependencies = [ - "cmake", - "libc", - "libz-sys", - "num_enum", - "openssl-sys", - "pkg-config", -] - -[[package]] -name = "reactor-trait" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "438a4293e4d097556730f4711998189416232f009c137389e0f961d2bc0ddc58" -dependencies = [ - "async-trait", - "futures-core", - "futures-io", -] - -[[package]] -name = "redis" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c580d9cbbe1d1b479e8d67cf9daf6a62c957e6846048408b80b43ac3f6af84cd" -dependencies = [ - "arc-swap", - "async-trait", - "bytes", - "combine", - "futures 0.3.31", - "futures-util", - "itoa", - "percent-encoding", - "pin-project-lite", - "ryu", - "serde", - "serde_json", - "sha1_smol", - "socket2 0.4.10", - "tokio", - "tokio-retry", - "tokio-util", - "url", + "getrandom 0.3.3", ] [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" -dependencies = [ - "bitflags 2.9.0", + "bitflags", ] [[package]] @@ -6542,17 +2075,8 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", + "regex-automata", + "regex-syntax", ] [[package]] @@ -6563,7 +2087,7 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.5", + "regex-syntax", ] [[package]] @@ -6572,257 +2096,56 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - [[package]] name = "regex-syntax" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" -[[package]] -name = "relative-path" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" - [[package]] name = "reqwest" -version = "0.11.27" +version = "0.12.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +checksum = "eabf4c97d9130e2bf606614eb937e86edac8292eaa6f422f995d7e8de1eb1813" dependencies = [ - "async-compression", - "base64 0.21.7", - "bytes", - "cookie 0.17.0", - "cookie_store", - "encoding_rs", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.32", - "hyper-rustls", - "hyper-tls 0.5.0", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls 0.21.12", - "rustls-pemfile 1.0.4", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 0.1.2", - "system-configuration", - "tokio", - "tokio-native-tls", - "tokio-rustls 0.24.1", - "tokio-util", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", - "webpki-roots 0.25.4", - "winreg 0.50.0", -] - -[[package]] -name = "reqwest" -version = "0.12.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" -dependencies = [ - "base64 0.22.1", + "base64", "bytes", "futures-core", "futures-util", - "http 1.2.0", - "http-body 1.0.1", + "http 1.3.1", + "http-body", "http-body-util", - "hyper 1.6.0", - "hyper-tls 0.6.0", + "hyper", + "hyper-tls", "hyper-util", - "ipnet", "js-sys", "log", - "mime", "native-tls", - "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile 2.2.0", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.2", + "sync_wrapper", "tokio", "tokio-native-tls", "tokio-util", - "tower 0.5.2", + "tower", + "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "wasm-streams", "web-sys", - "windows-registry", -] - -[[package]] -name = "retain_mut" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4389f1d5789befaf6029ebd9f7dac4af7f7e3d61b69d4f30e2ac02b57e7712b0" - -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac", - "subtle", -] - -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - -[[package]] -name = "ring" -version = "0.17.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.15", - "libc", - "untrusted 0.9.0", - "windows-sys 0.52.0", -] - -[[package]] -name = "rsa" -version = "0.9.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" -dependencies = [ - "const-oid", - "digest", - "num-bigint-dig", - "num-integer", - "num-traits", - "pkcs1", - "pkcs8", - "rand_core 0.6.4", - "signature", - "spki", - "subtle", - "zeroize", -] - -[[package]] -name = "rstest" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97eeab2f3c0a199bc4be135c36c924b6590b88c377d416494288c14f2db30199" -dependencies = [ - "futures 0.3.31", - "futures-timer", - "rstest_macros", - "rustc_version", -] - -[[package]] -name = "rstest_macros" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d428f8247852f894ee1be110b375111b586d4fa431f6c46e64ba5a0dcccbe605" -dependencies = [ - "cfg-if", - "glob", - "proc-macro2", - "quote", - "regex", - "relative-path", - "rustc_version", - "syn 2.0.99", - "unicode-ident", -] - -[[package]] -name = "rtcp" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33648a781874466a62d89e265fee9f17e32bc7d05a256e6cca41bf97eadcd8aa" -dependencies = [ - "bytes", - "thiserror 1.0.69", - "webrtc-util", -] - -[[package]] -name = "rtp" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e60482acbe8afb31edf6b1413103b7bca7a65004c423b3c3993749a083994fbe" -dependencies = [ - "bytes", - "rand 0.8.5", - "serde", - "thiserror 1.0.69", - "webrtc-util", -] - -[[package]] -name = "rtp" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47fca9bd66ae0b1f3f649b8f5003d6176433d7293b78b0fce7e1031816bdd99d" -dependencies = [ - "bytes", - "rand 0.8.5", - "serde", - "thiserror 1.0.69", - "webrtc-util", ] [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" [[package]] name = "rustc_version" @@ -6833,180 +2156,33 @@ dependencies = [ "semver", ] -[[package]] -name = "rusticata-macros" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" -dependencies = [ - "nom 7.1.3", -] - [[package]] name = "rustix" -version = "0.37.28" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "519165d378b97752ca44bbe15047d5d3409e875f39327546b42ac81d7e18c1b6" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.9.0", + "bitflags", "errno", "libc", - "linux-raw-sys 0.4.15", + "linux-raw-sys", "windows-sys 0.59.0", ] -[[package]] -name = "rustix" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dade4812df5c384711475be5fcd8c162555352945401aed22a35bffeab61f657" -dependencies = [ - "bitflags 2.9.0", - "errno", - "libc", - "linux-raw-sys 0.9.2", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustls" -version = "0.21.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" -dependencies = [ - "log", - "ring 0.17.13", - "rustls-webpki 0.101.7", - "sct", -] - -[[package]] -name = "rustls" -version = "0.23.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" -dependencies = [ - "log", - "once_cell", - "ring 0.17.13", - "rustls-pki-types", - "rustls-webpki 0.102.8", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-connector" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a980454b497c439c274f2feae2523ed8138bbd3d323684e1435fec62f800481" -dependencies = [ - "log", - "rustls 0.23.23", - "rustls-native-certs 0.7.3", - "rustls-pki-types", - "rustls-webpki 0.102.8", -] - -[[package]] -name = "rustls-native-certs" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" -dependencies = [ - "openssl-probe", - "rustls-pemfile 2.2.0", - "rustls-pki-types", - "schannel", - "security-framework 2.11.1", -] - -[[package]] -name = "rustls-native-certs" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" -dependencies = [ - "openssl-probe", - "rustls-pki-types", - "schannel", - "security-framework 3.2.0", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "rustls-pki-types" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" - -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ - "ring 0.17.13", - "untrusted 0.9.0", -] - -[[package]] -name = "rustls-webpki" -version = "0.102.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" -dependencies = [ - "ring 0.17.13", - "rustls-pki-types", - "untrusted 0.9.0", -] - -[[package]] -name = "rusttype" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff8374aa04134254b7995b63ad3dc41c7f7236f69528b28553da7d72efaa967" -dependencies = [ - "ab_glyph_rasterizer", - "owned_ttf_parser", + "zeroize", ] [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "ryu" @@ -7014,43 +2190,6 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" -[[package]] -name = "safe_arch" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "salsa20" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" -dependencies = [ - "cipher", -] - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "sanitize-filename" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf18934a12018228c5b55a6dae9df5d0641e3566b3630cb46cc55564068e7c2f" -dependencies = [ - "lazy_static", - "regex", -] - [[package]] name = "schannel" version = "0.1.27" @@ -7066,74 +2205,14 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "scrypt" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" -dependencies = [ - "pbkdf2 0.12.2", - "salsa20", - "sha2", -] - -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring 0.17.13", - "untrusted 0.9.0", -] - -[[package]] -name = "sdp" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13254db766b17451aced321e7397ebf0a446ef0c8d2942b6e67a95815421093f" -dependencies = [ - "rand 0.8.5", - "substring", - "thiserror 1.0.69", - "url", -] - -[[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct", - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", -] - [[package]] name = "security-framework" version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.9.0", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" -dependencies = [ - "bitflags 2.9.0", - "core-foundation 0.10.0", + "bitflags", + "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", @@ -7157,32 +2236,22 @@ checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "serde" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] -[[package]] -name = "serde-value" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" -dependencies = [ - "ordered-float 2.10.1", - "serde", -] - [[package]] name = "serde_derive" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.103", ] [[package]] @@ -7191,23 +2260,12 @@ version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ - "indexmap 2.7.1", "itoa", "memchr", "ryu", "serde", ] -[[package]] -name = "serde_path_to_error" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" -dependencies = [ - "itoa", - "serde", -] - [[package]] name = "serde_plain" version = "1.0.2" @@ -7217,26 +2275,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_qs" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7715380eec75f029a4ef7de39a9200e0a63823176b759d055b613f5a87df6a6" -dependencies = [ - "percent-encoding", - "serde", - "thiserror 1.0.69", -] - -[[package]] -name = "serde_spanned" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" -dependencies = [ - "serde", -] - [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -7249,36 +2287,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_with" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" -dependencies = [ - "base64 0.22.1", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.7.1", - "serde", - "serde_derive", - "serde_json", - "serde_with_macros", - "time", -] - -[[package]] -name = "serde_with_macros" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.99", -] - [[package]] name = "sha1" version = "0.10.6" @@ -7290,17 +2298,11 @@ dependencies = [ "digest", ] -[[package]] -name = "sha1_smol" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" - [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -7316,12 +2318,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "shlex" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" - [[package]] name = "shlex" version = "1.3.0" @@ -7330,435 +2326,47 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" dependencies = [ "libc", ] -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest", - "rand_core 0.6.4", -] - -[[package]] -name = "simba" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f3fd720c48c53cace224ae62bef1bbff363a70c68c4802a78b5cc6159618176" -dependencies = [ - "approx", - "num-complex", - "num-traits", - "paste", - "wide", -] - -[[package]] -name = "simd-adler32" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" - -[[package]] -name = "simple_asn1" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" -dependencies = [ - "num-bigint", - "num-traits", - "thiserror 2.0.12", - "time", -] - -[[package]] -name = "simplelog" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16257adbfaef1ee58b1363bdc0664c9b8e1e30aed86049635fb5f147d065a9c0" -dependencies = [ - "log", - "termcolor", - "time", -] - [[package]] name = "slab" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" [[package]] name = "smallvec" -version = "1.14.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" - -[[package]] -name = "smol_str" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" -dependencies = [ - "serde", -] +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.4.10" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", ] -[[package]] -name = "socks" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c3dbbd9ae980613c6dd8e28a9407b50509d3803b57624d5dfe8315218cd58b" -dependencies = [ - "byteorder", - "libc", - "winapi", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "sqlformat" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" -dependencies = [ - "nom 7.1.3", - "unicode_categories", -] - -[[package]] -name = "sqlx" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9a2ccff1a000a5a59cd33da541d9f2fdcd9e6e8229cc200565942bff36d0aaa" -dependencies = [ - "sqlx-core", - "sqlx-macros", - "sqlx-mysql", - "sqlx-postgres", - "sqlx-sqlite", -] - -[[package]] -name = "sqlx-core" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24ba59a9342a3d9bab6c56c118be528b27c9b60e490080e9711a04dccac83ef6" -dependencies = [ - "ahash", - "atoi", - "byteorder", - "bytes", - "chrono", - "crc", - "crossbeam-queue", - "either", - "event-listener 2.5.3", - "futures-channel", - "futures-core", - "futures-intrusive", - "futures-io", - "futures-util", - "hashlink", - "hex", - "indexmap 2.7.1", - "log", - "memchr", - "native-tls", - "once_cell", - "paste", - "percent-encoding", - "rustls 0.21.12", - "rustls-pemfile 1.0.4", - "serde", - "serde_json", - "sha2", - "smallvec", - "sqlformat", - "thiserror 1.0.69", - "time", - "tokio", - "tokio-stream", - "tracing", - "url", - "uuid", - "webpki-roots 0.25.4", -] - -[[package]] -name = "sqlx-macros" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea40e2345eb2faa9e1e5e326db8c34711317d2b5e08d0d5741619048a803127" -dependencies = [ - "proc-macro2", - "quote", - "sqlx-core", - "sqlx-macros-core", - "syn 1.0.109", -] - -[[package]] -name = "sqlx-macros-core" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5833ef53aaa16d860e92123292f1f6a3d53c34ba8b1969f152ef1a7bb803f3c8" -dependencies = [ - "dotenvy", - "either", - "heck 0.4.1", - "hex", - "once_cell", - "proc-macro2", - "quote", - "serde", - "serde_json", - "sha2", - "sqlx-core", - "sqlx-mysql", - "sqlx-postgres", - "sqlx-sqlite", - "syn 1.0.109", - "tempfile", - "tokio", - "url", -] - -[[package]] -name = "sqlx-mysql" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418" -dependencies = [ - "atoi", - "base64 0.21.7", - "bitflags 2.9.0", - "byteorder", - "bytes", - "chrono", - "crc", - "digest", - "dotenvy", - "either", - "futures-channel", - "futures-core", - "futures-io", - "futures-util", - "generic-array", - "hex", - "hkdf", - "hmac", - "itoa", - "log", - "md-5", - "memchr", - "once_cell", - "percent-encoding", - "rand 0.8.5", - "rsa", - "serde", - "sha1", - "sha2", - "smallvec", - "sqlx-core", - "stringprep", - "thiserror 1.0.69", - "time", - "tracing", - "uuid", - "whoami", -] - -[[package]] -name = "sqlx-postgres" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" -dependencies = [ - "atoi", - "base64 0.21.7", - "bitflags 2.9.0", - "byteorder", - "chrono", - "crc", - "dotenvy", - "etcetera", - "futures-channel", - "futures-core", - "futures-io", - "futures-util", - "hex", - "hkdf", - "hmac", - "home", - "itoa", - "log", - "md-5", - "memchr", - "once_cell", - "rand 0.8.5", - "serde", - "serde_json", - "sha2", - "smallvec", - "sqlx-core", - "stringprep", - "thiserror 1.0.69", - "time", - "tracing", - "uuid", - "whoami", -] - -[[package]] -name = "sqlx-sqlite" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b244ef0a8414da0bed4bb1910426e890b19e5e9bccc27ada6b797d05c55ae0aa" -dependencies = [ - "atoi", - "chrono", - "flume", - "futures-channel", - "futures-core", - "futures-executor", - "futures-intrusive", - "futures-util", - "libsqlite3-sys", - "log", - "percent-encoding", - "serde", - "sqlx-core", - "time", - "tracing", - "url", - "urlencoding", - "uuid", -] - [[package]] name = "stable_deref_trait" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "stringprep" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" -dependencies = [ - "unicode-bidi", - "unicode-normalization", - "unicode-properties", -] - [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "strum" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" - -[[package]] -name = "strum_macros" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.99", -] - -[[package]] -name = "stun" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3f371788132e9d623e6eab4ba28aac083763a4133f045e6ebaee5ceb869803d" -dependencies = [ - "base64 0.21.7", - "crc", - "lazy_static", - "md-5", - "rand 0.8.5", - "ring 0.17.13", - "subtle", - "thiserror 1.0.69", - "tokio", - "url", - "webrtc-util", -] - -[[package]] -name = "substring" -version = "1.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ee6433ecef213b2e72f587ef64a2f5943e7cd16fbd82dbe8bc07486c534c86" -dependencies = [ - "autocfg", -] - [[package]] name = "subtle" version = "2.6.1" @@ -7778,21 +2386,15 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.99" +version = "2.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" +checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - [[package]] name = "sync_wrapper" version = "1.0.2" @@ -7804,277 +2406,46 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.12.6" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", - "unicode-xid", -] - -[[package]] -name = "synstructure" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.99", -] - -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.9.4", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "system-deps" -version = "6.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" -dependencies = [ - "cfg-expr", - "heck 0.5.0", - "pkg-config", - "toml", - "version-compare", -] - -[[package]] -name = "tar" -version = "0.4.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" -dependencies = [ - "filetime", - "libc", - "xattr", -] - -[[package]] -name = "target-lexicon" -version = "0.12.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" - -[[package]] -name = "tcp-stream" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "495b0abdce3dc1f8fd27240651c9e68890c14e9d9c61527b1ce44d8a5a7bd3d5" -dependencies = [ - "cfg-if", - "p12-keystore", - "rustls-connector", - "rustls-pemfile 2.2.0", + "syn 2.0.103", ] [[package]] name = "tempfile" -version = "3.18.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c317e0a526ee6120d8dabad239c8dadca62b24b6f168914bbbc8e2fb1f0e567" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ - "cfg-if", - "fastrand 2.3.0", - "getrandom 0.3.1", + "fastrand", + "getrandom 0.3.3", "once_cell", - "rustix 1.0.1", + "rustix", "windows-sys 0.59.0", ] -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "termtree" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" -dependencies = [ - "thiserror-impl 2.0.12", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.99", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.99", -] - [[package]] name = "thread_local" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", - "once_cell", -] - -[[package]] -name = "tiff" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" -dependencies = [ - "flate2", - "jpeg-decoder", - "weezl", -] - -[[package]] -name = "tikv-client" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26904b386ca52ce25b3a620b397e6e4e93c4fd06d13c2c5936d9ac597f897263" -dependencies = [ - "async-trait", - "derive-new", - "fail", - "futures 0.3.31", - "futures-timer", - "grpcio", - "lazy_static", - "log", - "prometheus 0.12.0", - "rand 0.8.5", - "regex", - "serde", - "serde_derive", - "thiserror 1.0.69", - "tikv-client-common", - "tikv-client-pd", - "tikv-client-proto", - "tikv-client-store", - "tokio", -] - -[[package]] -name = "tikv-client-common" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72fc3bb3fbec1f2a3354d4bbe48501b23ea47b79da2ffaedeadcc8a6183188e4" -dependencies = [ - "futures 0.3.31", - "grpcio", - "lazy_static", - "log", - "regex", - "thiserror 1.0.69", - "tikv-client-proto", -] - -[[package]] -name = "tikv-client-pd" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cadef1633d4e7952d9a3a88211f03f71e9f90769a5b50c40b5eccc06408977" -dependencies = [ - "async-trait", - "futures 0.3.31", - "grpcio", - "log", - "tikv-client-common", - "tikv-client-proto", -] - -[[package]] -name = "tikv-client-proto" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9707c63c11c19b87b6eb3df40c6103d0f1e2f06b53445bad91a8c9e06407d9b" -dependencies = [ - "futures 0.3.31", - "grpcio", - "lazy_static", - "prost 0.7.0", - "prost-derive 0.7.0", - "protobuf", - "protobuf-build", -] - -[[package]] -name = "tikv-client-store" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ab348b60ef0a384985c488e25bf35721956b3b45332945f0841f9ac8a693586" -dependencies = [ - "async-trait", - "derive-new", - "futures 0.3.31", - "grpcio", - "log", - "tikv-client-common", - "tikv-client-proto", ] [[package]] name = "time" -version = "0.3.39" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad298b01a40a23aac4580b67e3dbedb7cc8402f3592d7f49469de2ea4aecdd8" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa", - "libc", "num-conv", - "num_threads", "powerfmt", "serde", "time-core", @@ -8083,15 +2454,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765c97a5b985b7c11d7bc27fa927dc4fe6af3a6dfb021d28deb60d3bf51e76ef" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" -version = "0.2.20" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8093bc3e81c3bc5f7879de09619d06c9a5a5e45ca44dfeeb7225bae38005c5c" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" dependencies = [ "num-conv", "time-core", @@ -8099,67 +2470,32 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.6" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ "displaydoc", "zerovec", ] -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "tinyvec" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" -version = "1.44.0" +version = "1.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9975ea0f48b5aa3972bf2d888c238182458437cc2a19374b81b25cdf1023fb3a" +checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" dependencies = [ "backtrace", "bytes", "libc", "mio", - "parking_lot 0.12.3", + "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.8", + "socket2", "tokio-macros", "windows-sys 0.52.0", ] -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", -] - [[package]] name = "tokio-macros" version = "2.5.0" @@ -8168,7 +2504,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.103", ] [[package]] @@ -8181,48 +2517,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-openssl" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59df6849caa43bb7567f9a36f863c447d95a11d5903c9cc334ba32576a27eadd" -dependencies = [ - "openssl", - "openssl-sys", - "tokio", -] - -[[package]] -name = "tokio-retry" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f" -dependencies = [ - "pin-project", - "rand 0.8.5", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.12", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" -dependencies = [ - "rustls 0.23.23", - "tokio", -] - [[package]] name = "tokio-stream" version = "0.1.17" @@ -8234,50 +2528,11 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-test" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2468baabc3311435b55dd935f702f42cd1b8abb7e754fb7dfb16bd36aa88f9f7" -dependencies = [ - "async-stream", - "bytes", - "futures-core", - "tokio", - "tokio-stream", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" -dependencies = [ - "futures-util", - "log", - "tokio", - "tungstenite 0.20.1", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" -dependencies = [ - "futures-util", - "log", - "native-tls", - "tokio", - "tokio-native-tls", - "tungstenite 0.24.0", -] - [[package]] name = "tokio-util" -version = "0.7.13" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" dependencies = [ "bytes", "futures-core", @@ -8286,166 +2541,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "toml" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" -dependencies = [ - "indexmap 2.7.1", - "serde", - "serde_spanned", - "toml_datetime", - "winnow", -] - -[[package]] -name = "tonic" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb" -dependencies = [ - "async-stream", - "async-trait", - "axum 0.6.20", - "base64 0.13.1", - "bytes", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.32", - "hyper-timeout 0.4.1", - "percent-encoding", - "pin-project", - "prost 0.11.9", - "prost-derive 0.11.9", - "tokio", - "tokio-stream", - "tokio-util", - "tower 0.4.13", - "tower-layer", - "tower-service", - "tracing", - "tracing-futures", -] - -[[package]] -name = "tonic" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" -dependencies = [ - "async-stream", - "async-trait", - "axum 0.6.20", - "base64 0.21.7", - "bytes", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.32", - "hyper-timeout 0.4.1", - "percent-encoding", - "pin-project", - "prost 0.12.6", - "rustls 0.21.12", - "rustls-pemfile 1.0.4", - "tokio", - "tokio-rustls 0.24.1", - "tokio-stream", - "tower 0.4.13", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tonic" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" -dependencies = [ - "async-stream", - "async-trait", - "axum 0.7.9", - "base64 0.22.1", - "bytes", - "h2 0.4.8", - "http 1.2.0", - "http-body 1.0.1", - "http-body-util", - "hyper 1.6.0", - "hyper-timeout 0.5.2", - "hyper-util", - "percent-encoding", - "pin-project", - "prost 0.13.5", - "rustls-native-certs 0.8.1", - "rustls-pemfile 2.2.0", - "socket2 0.5.8", - "tokio", - "tokio-rustls 0.26.2", - "tokio-stream", - "tower 0.4.13", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tonic-types" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0081d8ee0847d01271392a5aebe960a4600f5d4da6c67648a6382a0940f8b367" -dependencies = [ - "prost 0.13.5", - "prost-types 0.13.5", - "tonic 0.12.3", -] - -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "indexmap 1.9.3", - "pin-project", - "pin-project-lite", - "rand 0.8.5", - "slab", - "tokio", - "tokio-util", - "tower-layer", - "tower-service", - "tracing", -] - [[package]] name = "tower" version = "0.5.2" @@ -8455,37 +2550,28 @@ dependencies = [ "futures-core", "futures-util", "pin-project-lite", - "sync_wrapper 1.0.2", + "sync_wrapper", "tokio", "tower-layer", "tower-service", - "tracing", ] [[package]] name = "tower-http" -version = "0.5.2" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" dependencies = [ - "base64 0.21.7", - "bitflags 2.9.0", + "bitflags", "bytes", "futures-util", - "http 1.2.0", - "http-body 1.0.1", - "http-body-util", - "http-range-header", - "httpdate", - "mime", - "mime_guess", - "percent-encoding", + "http 1.3.1", + "http-body", + "iri-string", "pin-project-lite", - "tokio", - "tokio-util", + "tower", "tower-layer", "tower-service", - "tracing", ] [[package]] @@ -8514,35 +2600,25 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.28" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.103", ] [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", "valuable", ] -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "pin-project", - "tracing", -] - [[package]] name = "tracing-log" version = "0.2.0" @@ -8560,14 +2636,10 @@ version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ - "matchers", "nu-ansi-term", - "once_cell", - "regex", "sharded-slab", "smallvec", "thread_local", - "tracing", "tracing-core", "tracing-log", ] @@ -8578,199 +2650,24 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "ttf-parser" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd" - -[[package]] -name = "tungstenite" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http 0.2.12", - "httparse", - "log", - "rand 0.8.5", - "sha1", - "thiserror 1.0.69", - "url", - "utf-8", -] - -[[package]] -name = "tungstenite" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http 1.2.0", - "httparse", - "log", - "native-tls", - "rand 0.8.5", - "sha1", - "thiserror 1.0.69", - "utf-8", -] - -[[package]] -name = "tungstenite" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" -dependencies = [ - "bytes", - "data-encoding", - "http 1.2.0", - "httparse", - "log", - "rand 0.9.0", - "sha1", - "thiserror 2.0.12", - "utf-8", -] - -[[package]] -name = "turn" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb2ac4f331064513ad510b7a36edc0df555bd61672986607f7c9ff46f98f415" -dependencies = [ - "async-trait", - "base64 0.21.7", - "futures 0.3.31", - "log", - "md-5", - "rand 0.8.5", - "ring 0.17.13", - "stun", - "thiserror 1.0.69", - "tokio", - "tokio-util", - "webrtc-util", -] - -[[package]] -name = "twoway" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c57ffb460d7c24cd6eda43694110189030a3d1dfe418416d9468fd1c1d290b47" -dependencies = [ - "memchr", - "unchecked-index", -] - [[package]] name = "typenum" version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" -[[package]] -name = "unchecked-index" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeba86d422ce181a719445e51872fa30f1f7413b62becb52e95ec91aa262d85c" - -[[package]] -name = "unicase" -version = "2.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" - -[[package]] -name = "unicode-bidi" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" - [[package]] name = "unicode-ident" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-properties" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" - -[[package]] -name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - [[package]] name = "unicode-xid" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" -[[package]] -name = "unicode_categories" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" - -[[package]] -name = "universal-hash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" -dependencies = [ - "crypto-common", - "subtle", -] - -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "ureq" -version = "2.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" -dependencies = [ - "base64 0.22.1", - "flate2", - "log", - "once_cell", - "rustls 0.23.23", - "rustls-pki-types", - "socks", - "url", - "webpki-roots 0.26.8", -] - [[package]] name = "url" version = "2.5.4" @@ -8778,9 +2675,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", - "idna 1.0.3", + "idna", "percent-encoding", - "serde", ] [[package]] @@ -8789,18 +2685,6 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -8813,58 +2697,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" -[[package]] -name = "uuid" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587" -dependencies = [ - "getrandom 0.3.1", - "serde", -] - -[[package]] -name = "validator" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b92f40481c04ff1f4f61f304d61793c7b56ff76ac1469f1beb199b1445b253bd" -dependencies = [ - "idna 0.4.0", - "lazy_static", - "regex", - "serde", - "serde_derive", - "serde_json", - "url", - "validator_derive", -] - -[[package]] -name = "validator_derive" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc44ca3088bb3ba384d9aecf40c6a23a676ce23e09bdaca2073d99c207f864af" -dependencies = [ - "if_chain", - "lazy_static", - "proc-macro-error", - "proc-macro2", - "quote", - "regex", - "syn 1.0.109", - "validator_types", -] - -[[package]] -name = "validator_types" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "111abfe30072511849c5910134e8baf8dc05de4c0e5903d681cbd5c9c4d611e3" -dependencies = [ - "proc-macro2", - "syn 1.0.109", -] - [[package]] name = "valuable" version = "0.1.1" @@ -8873,9 +2705,9 @@ checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "value-bag" -version = "1.10.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2" +checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5" [[package]] name = "vcpkg" @@ -8883,61 +2715,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "vector" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280be990562443e0cb0ddc1ef2893fc2f4ff8ce0a2805a2dd42826f13e8eafd0" -dependencies = [ - "random", -] - -[[package]] -name = "version-compare" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" - [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "wait-timeout" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" -dependencies = [ - "libc", -] - -[[package]] -name = "waitgroup" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1f50000a783467e6c0200f9d10642f4bc424e39efc1b770203e88b488f79292" -dependencies = [ - "atomic-waker", -] - -[[package]] -name = "waker-fn" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - [[package]] name = "want" version = "0.3.1" @@ -8949,31 +2732,19 @@ dependencies = [ [[package]] name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasi" -version = "0.13.3+wasi-0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ "wit-bindgen-rt", ] -[[package]] -name = "wasite" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" - [[package]] name = "wasm-bindgen" version = "0.2.100" @@ -8996,7 +2767,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.103", "wasm-bindgen-shared", ] @@ -9031,7 +2802,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.103", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -9068,293 +2839,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webdriver" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9973cb72c8587d5ad5efdb91e663d36177dc37725e6c90ca86c626b0cc45c93f" -dependencies = [ - "base64 0.13.1", - "bytes", - "cookie 0.16.2", - "http 0.2.12", - "log", - "serde", - "serde_derive", - "serde_json", - "time", - "unicode-segmentation", - "url", -] - -[[package]] -name = "webpki-roots" -version = "0.25.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" - -[[package]] -name = "webpki-roots" -version = "0.26.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "webrtc" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91e7cf018f7185552bf6a5dd839f4ed9827aea33b746763c9a215f84a0d0b34" -dependencies = [ - "arc-swap", - "async-trait", - "bytes", - "cfg-if", - "hex", - "interceptor", - "lazy_static", - "log", - "rand 0.8.5", - "rcgen", - "regex", - "ring 0.16.20", - "rtcp", - "rtp 0.9.0", - "rustls 0.21.12", - "sdp", - "serde", - "serde_json", - "sha2", - "smol_str", - "stun", - "thiserror 1.0.69", - "time", - "tokio", - "turn", - "url", - "waitgroup", - "webrtc-data", - "webrtc-dtls", - "webrtc-ice", - "webrtc-mdns", - "webrtc-media", - "webrtc-sctp", - "webrtc-srtp", - "webrtc-util", -] - -[[package]] -name = "webrtc-data" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c08e648e10572b9edbe741074e0f4d3cb221aa7cdf9a814ee71606de312f33" -dependencies = [ - "bytes", - "log", - "thiserror 1.0.69", - "tokio", - "webrtc-sctp", - "webrtc-util", -] - -[[package]] -name = "webrtc-dtls" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b140b953f986e97828aa33ec6318186b05d862bee689efbc57af04a243e832" -dependencies = [ - "aes", - "aes-gcm", - "async-trait", - "bincode", - "byteorder", - "cbc", - "ccm", - "der-parser 8.2.0", - "hkdf", - "hmac", - "log", - "p256", - "p384", - "rand 0.8.5", - "rand_core 0.6.4", - "rcgen", - "ring 0.16.20", - "rustls 0.21.12", - "sec1", - "serde", - "sha1", - "sha2", - "subtle", - "thiserror 1.0.69", - "tokio", - "webrtc-util", - "x25519-dalek", - "x509-parser 0.15.1", -] - -[[package]] -name = "webrtc-ice" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1bbd6b3dea22cc6e961e22b012e843d8869e2ac8e76b96e54d4a25e311857ad" -dependencies = [ - "arc-swap", - "async-trait", - "crc", - "log", - "rand 0.8.5", - "serde", - "serde_json", - "stun", - "thiserror 1.0.69", - "tokio", - "turn", - "url", - "uuid", - "waitgroup", - "webrtc-mdns", - "webrtc-util", -] - -[[package]] -name = "webrtc-mdns" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce981f93104a8debb3563bb0cedfe4aa2f351fdf6b53f346ab50009424125c08" -dependencies = [ - "log", - "socket2 0.5.8", - "thiserror 1.0.69", - "tokio", - "webrtc-util", -] - -[[package]] -name = "webrtc-media" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280017b6b9625ef7329146332518b339c3cceff231cc6f6a9e0e6acab25ca4af" -dependencies = [ - "byteorder", - "bytes", - "rand 0.8.5", - "rtp 0.10.0", - "thiserror 1.0.69", -] - -[[package]] -name = "webrtc-sctp" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df75ec042002fe995194712cbeb2029107a60a7eab646f1b789eb1be94d0e367" -dependencies = [ - "arc-swap", - "async-trait", - "bytes", - "crc", - "log", - "rand 0.8.5", - "thiserror 1.0.69", - "tokio", - "webrtc-util", -] - -[[package]] -name = "webrtc-srtp" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1db1f36c1c81e4b1e531c0b9678ba0c93809e196ce62122d87259bb71c03b9f" -dependencies = [ - "aead", - "aes", - "aes-gcm", - "byteorder", - "bytes", - "ctr", - "hmac", - "log", - "rtcp", - "rtp 0.9.0", - "sha1", - "subtle", - "thiserror 1.0.69", - "tokio", - "webrtc-util", -] - -[[package]] -name = "webrtc-util" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e85154ef743d9a2a116d104faaaa82740a281b8b4bed5ee691a2df6c133d873" -dependencies = [ - "async-trait", - "bitflags 1.3.2", - "bytes", - "ipnet", - "lazy_static", - "libc", - "log", - "nix 0.26.4", - "rand 0.8.5", - "thiserror 1.0.69", - "tokio", - "winapi", -] - -[[package]] -name = "weezl" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" - -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix 0.38.44", -] - -[[package]] -name = "which" -version = "7.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2774c861e1f072b3aadc02f8ba886c26ad6321567ecc294c935434cad06f1283" -dependencies = [ - "either", - "env_home", - "rustix 0.38.44", - "winsafe", -] - -[[package]] -name = "whoami" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" -dependencies = [ - "redox_syscall 0.5.10", - "wasite", -] - -[[package]] -name = "wide" -version = "0.7.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41b5576b9a81633f3e8df296ce0063042a73507636cbe956c61133dd7034ab22" -dependencies = [ - "bytemuck", - "safe_arch", -] - [[package]] name = "winapi" version = "0.3.9" @@ -9371,15 +2855,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys 0.59.0", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -9388,56 +2863,61 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.52.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ - "windows-targets 0.52.6", + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.103", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.103", ] [[package]] name = "windows-link" -version = "0.1.0" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" - -[[package]] -name = "windows-registry" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" -dependencies = [ - "windows-result", - "windows-strings", - "windows-targets 0.52.6", -] +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] name = "windows-result" -version = "0.2.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-targets 0.52.6", + "windows-link", ] [[package]] name = "windows-strings" -version = "0.1.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-result", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", + "windows-link", ] [[package]] @@ -9459,18 +2939,12 @@ dependencies = [ ] [[package]] -name = "windows-targets" -version = "0.48.5" +name = "windows-sys" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-targets 0.53.2", ] [[package]] @@ -9482,7 +2956,7 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", @@ -9490,10 +2964,20 @@ dependencies = [ ] [[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" +name = "windows-targets" +version = "0.53.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] [[package]] name = "windows_aarch64_gnullvm" @@ -9502,10 +2986,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" +name = "windows_aarch64_gnullvm" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" [[package]] name = "windows_aarch64_msvc" @@ -9514,10 +2998,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] -name = "windows_i686_gnu" -version = "0.48.5" +name = "windows_aarch64_msvc" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" [[package]] name = "windows_i686_gnu" @@ -9525,6 +3009,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" @@ -9532,10 +3022,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] -name = "windows_i686_msvc" -version = "0.48.5" +name = "windows_i686_gnullvm" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" [[package]] name = "windows_i686_msvc" @@ -9544,10 +3034,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" +name = "windows_i686_msvc" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" [[package]] name = "windows_x86_64_gnu" @@ -9556,10 +3046,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" +name = "windows_x86_64_gnu" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" [[package]] name = "windows_x86_64_gnullvm" @@ -9568,10 +3058,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" +name = "windows_x86_64_gnullvm" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" [[package]] name = "windows_x86_64_msvc" @@ -9580,166 +3070,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] -name = "winnow" -version = "0.5.40" +name = "windows_x86_64_msvc" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "winreg" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "937f3df7948156640f46aacef17a70db0de5917bda9c92b0f751f3a955b588fc" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "winreg" -version = "0.55.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97" -dependencies = [ - "cfg-if", - "windows-sys 0.59.0", -] - -[[package]] -name = "winsafe" -version = "0.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" - -[[package]] -name = "wiremock" -version = "0.5.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13a3a53eaf34f390dd30d7b1b078287dd05df2aa2e21a589ccb80f5c7253c2e9" -dependencies = [ - "assert-json-diff", - "async-trait", - "base64 0.21.7", - "deadpool", - "futures 0.3.31", - "futures-timer", - "http-types", - "hyper 0.14.32", - "log", - "once_cell", - "regex", - "serde", - "serde_json", - "tokio", -] +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "wit-bindgen-rt" -version = "0.33.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags 2.9.0", + "bitflags", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - [[package]] name = "writeable" -version = "0.5.5" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" - -[[package]] -name = "x25519-dalek" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" -dependencies = [ - "curve25519-dalek", - "rand_core 0.6.4", - "serde", - "zeroize", -] - -[[package]] -name = "x509-cert" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1301e935010a701ae5f8655edc0ad17c44bad3ac5ce8c39185f75453b720ae94" -dependencies = [ - "const-oid", - "der", - "spki", -] - -[[package]] -name = "x509-parser" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7069fba5b66b9193bd2c5d3d4ff12b839118f6bcbef5328efafafb5395cf63da" -dependencies = [ - "asn1-rs 0.5.2", - "data-encoding", - "der-parser 8.2.0", - "lazy_static", - "nom 7.1.3", - "oid-registry 0.6.1", - "ring 0.16.20", - "rusticata-macros", - "thiserror 1.0.69", - "time", -] - -[[package]] -name = "x509-parser" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569f339c0c402346d4a75a9e39cf8dad310e287eef1ff56d4c68e5067f53460" -dependencies = [ - "asn1-rs 0.7.0", - "data-encoding", - "der-parser 10.0.0", - "lazy_static", - "nom 7.1.3", - "oid-registry 0.8.1", - "rusticata-macros", - "thiserror 2.0.12", - "time", -] - -[[package]] -name = "xattr" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d65cbf2f12c15564212d48f4e3dfb87923d25d611f2aed18f4cb23f0413d89e" -dependencies = [ - "libc", - "rustix 1.0.1", -] +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "xml-rs" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5b940ebc25896e71dd073bad2dbaa2abfe97b0a391415e22ad1326d9c54e3c4" +checksum = "a62ce76d9b56901b19a74f19431b0d8b3bc7ca4ad685a746dfd78ca8f4fc6bda" [[package]] name = "xmltree" @@ -9750,20 +3105,11 @@ dependencies = [ "xml-rs", ] -[[package]] -name = "yasna" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" -dependencies = [ - "time", -] - [[package]] name = "yoke" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ "serde", "stable_deref_trait", @@ -9773,55 +3119,34 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", - "synstructure 0.13.1", + "syn 2.0.103", + "synstructure", ] [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ - "byteorder", - "zerocopy-derive 0.7.35", -] - -[[package]] -name = "zerocopy" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" -dependencies = [ - "zerocopy-derive 0.8.23", + "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.99", + "syn 2.0.103", ] [[package]] @@ -9841,8 +3166,8 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", - "synstructure 0.13.1", + "syn 2.0.103", + "synstructure", ] [[package]] @@ -9850,26 +3175,23 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -dependencies = [ - "zeroize_derive", -] [[package]] -name = "zeroize_derive" -version = "1.4.2" +name = "zerotrie" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.99", + "displaydoc", + "yoke", + "zerofrom", ] [[package]] name = "zerovec" -version = "0.10.4" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" dependencies = [ "yoke", "zerofrom", @@ -9878,64 +3200,13 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", -] - -[[package]] -name = "zip" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" -dependencies = [ - "aes", - "byteorder", - "bzip2", - "constant_time_eq", - "crc32fast", - "crossbeam-utils", - "flate2", - "hmac", - "pbkdf2 0.11.0", - "sha1", - "time", - "zstd 0.11.2+zstd.1.5.2", -] - -[[package]] -name = "zitadel" -version = "5.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168b66027ca4fd1aa3c529f1359a59f94495db612b57223bf933b2900df4e052" -dependencies = [ - "custom_error", - "jsonwebtoken", - "openidconnect", - "pbjson-types", - "prost 0.13.5", - "prost-types 0.13.5", - "reqwest 0.11.27", - "serde", - "serde_json", - "serde_urlencoded", - "time", - "tokio", - "tonic 0.12.3", - "tonic-types", -] - -[[package]] -name = "zstd" -version = "0.11.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" -dependencies = [ - "zstd-safe 5.0.2+zstd.1.5.2", + "syn 2.0.103", ] [[package]] @@ -9944,43 +3215,24 @@ version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" dependencies = [ - "zstd-safe 7.2.3", + "zstd-safe", ] [[package]] name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" +version = "7.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" -dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-safe" -version = "7.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3051792fbdc2e1e143244dc28c60f73d8470e93f3f9cbd0ead44da5ed802722" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.14+zstd.1.5.7" +version = "2.0.15+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb060d4926e4ac3a3ad15d864e99ceb5f343c6b34f5bd6d81ae6ed417311be5" +checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" dependencies = [ "cc", "pkg-config", ] - -[[package]] -name = "zune-inflate" -version = "0.2.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" -dependencies = [ - "simd-adler32", -] diff --git a/Cargo.toml b/Cargo.toml index a1bb492..e863c8d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,143 +1,22 @@ -[workspace] -resolver = "2" -members = [ - "gb-core", - "gb-server", - "gb-media", - "gb-messaging", - "gb-storage", - "gb-monitoring", - "gb-auth", - "gb-testing", - "gb-migrations", - "gb-cloud", - "gb-vm", - "gb-automation", - "gb-image", - "gb-utils", - "gb-document", - "gb-file", - "gb-llm", - "gb-calendar", "gb-infra", -] - -[workspace.package] +[package] +name = "gbserver" version = "0.1.0" edition = "2021" -authors = ["General Bots Maintainers"] +authors = ["Your Name "] +description = "File server with MinIO integration" license = "MIT" +repository = "" -[workspace.dependencies] -# Core async runtime and utilities -tokio = { version = "1.34", features = ["full"] } -tokio-tungstenite = { version = "0.24.0", features = ["native-tls"] } -tungstenite = "0.20" -tokio-test = "0.4" -tokio-stream = "0.1.17" -async-trait = "0.1" -futures = "0.3" -futures-util = "0.3" # Add futures-util here -parking_lot = "0.12" -bytes = "1.0" +[dependencies] +actix-web = "4" +actix-multipart = "0.6" +tokio = { version = "1", features = ["full"] } log = "0.4" -env_logger = "0.10" -ctrlc = "3.2" - -# Web framework and servers -axum = { version = "0.7.9", features = ["ws", "multipart"] } -tower = "0.4" -tower-http = { version = "0.5", features = ["cors", "trace", "fs"] } -hyper = { version = "1.1", features = ["full"] } -hyper-util = { version = "0.1" } -tonic = { version = "0.10", features = ["tls", "transport"] } -actix-multipart = "0.4" - - -# Database and storage -sqlx = { version = "0.7", features = ["runtime-tokio-native-tls", "postgres", "mysql", "sqlite", "uuid", "time", "json"] } -redis = { version = "0.24", features = ["tokio-comp", "connection-manager"] } -tikv-client = "0.3" -sea-orm = { version = "0.12", features = ["sqlx-postgres", "runtime-tokio-native-tls", "macros"] } - -# Message queues -rdkafka = { version = "0.36", features = ["cmake-build", "ssl"] } -lapin = "2.3" - - -# Drive, Serialization and data formats -minio = { git = "https://github.com/minio/minio-rs", branch = "master" } +tracing = "0.1" +tracing-subscriber = { version = "0.3", features = ["fmt"] } +dotenv = "0.15" +tempfile = "3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -protobuf = "3.3" -prost = "0.12" -csv = "1.3" - -# WebRTC and media processing -webrtc = "0.9" -gstreamer = "0.21" -opus = "0.3" -image = "0.24" - -# Authentication and security -zitadel = {version = "5.5.1", features = ["api-common", "api-auth-v1", "zitadel-auth-v1", "credentials", "interceptors"]} -jsonwebtoken = "9.2" - -argon2 = "0.5" -ring = "0.17" -reqwest = { version = "0.11", features = ["json", "stream", "blocking"] } - -# Cloud services -aws-sdk-core = "1.1" -azure_core = "0.15" -azure_identity = "0.15" -google-cloud-storage = "0.16" - -# Monitoring and metrics -prometheus = "0.13.0" -opentelemetry = { version = "0.20", features = ["rt-tokio"] } -tracing = "0.1" -tracing-subscriber = { version = "0.3", features = ["env-filter"] } - -# Testing -criterion = "0.5" -mockall = "0.12" -fake = { version = "2.9", features = ["derive"] } -rstest = "0.18" - -# Utilities -actix-web = "4.0.1" -uuid = { version = "1.6", features = ["serde", "v4"] } -chrono = { version = "0.4", features = ["serde"] } -thiserror = "1.0" -anyhow = "1.0" -regex = "1.10" -url = "2.5" -rand = "0.8" -base64 = "0.21" -semver = "1.0" -walkdir = "2.4" -tempfile = "3.9" -dotenv = "0.15" -lettre = "0.10" -sanitize-filename = "0.3" - -# Web assembly -wasm-bindgen = "0.2" -js-sys = "0.3" -web-sys = { version = "0.3", features = ["WebSocket", "WebRtcPeerConnection"] } - -# Natural language processing -rust-bert = "0.21" -tokenizers = "0.15" -whatlang = "0.16" - -# PDF and document processing -pdf = "0.8" -docx = "1.1" -zip = "0.6" -tar = "0.4" -flate2 = "1.0" - -[workspace.metadata] -msrv = "1.70.0" - +minio = { git = "https://github.com/minio/minio-rs", branch = "master" } +tokio-stream = "0.1.17" diff --git a/deploy.sh b/deploy.sh deleted file mode 100755 index 558f070..0000000 --- a/deploy.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -e - -echo "Deploying General Bots platform..." - -# Create DB. - -cargo run -p gb-migrations --bin migrations - -echo "Deployment completed successfully!" -echo "Please wait for all pods to be ready..." - diff --git a/gb-auth/Cargo.toml b/gb-auth/Cargo.toml deleted file mode 100644 index dda7052..0000000 --- a/gb-auth/Cargo.toml +++ /dev/null @@ -1,58 +0,0 @@ -[package] -name = "gb-auth" -version = { workspace = true } -edition = { workspace = true } -authors = { workspace = true } -license = { workspace = true } - -[dependencies] -gb-core = { path = "../gb-core" } - -# Authentication & Security -jsonwebtoken = { workspace = true } -argon2 = "0.5" -rand = { version = "0.8", features = ["std"] } -oauth2 = "4.4" -openid = "0.12" -tokio-openssl = "0.6" -ring = "0.17" - -# Async Runtime -tokio= { workspace = true } -async-trait= { workspace = true } - - -# Database -sqlx = { version = "0.7", features = ["runtime-tokio-native-tls", "postgres", "uuid", "chrono", "json"] } -redis = { version = "0.24", features = ["tokio-comp", "json"] } - -# Serialization -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" - -# Error Handling -thiserror = "1.0" - -# Logging & Metrics -tracing= { workspace = true } - -# Utils -chrono = { version = "0.4", features = ["serde"] } -uuid = { version = "1.6", features = ["serde", "v4"] } -validator = { version = "0.16", features = ["derive"] } - -# Web Framework -axum = { version = "0.7.9" } -axum-extra = { version = "0.7" } # Add headers feature -tower = "0.4" -tower-http = { version = "0.5", features = ["auth", "cors", "trace"] } -headers = "0.3" -tokio-stream = { workspace = true } - -[dev-dependencies] -rstest = "0.18" -tokio-test = "0.4" -mockall = "0.12" -axum-extra = { version = "0.7" } -sqlx = { version = "0.7", features = ["runtime-tokio-native-tls", "postgres", "uuid", "chrono", "json"] } - diff --git a/gb-auth/config/auth_config.yaml b/gb-auth/config/auth_config.yaml deleted file mode 100644 index 9bfa875..0000000 --- a/gb-auth/config/auth_config.yaml +++ /dev/null @@ -1,23 +0,0 @@ -jwt: - secret: your_jwt_secret_key_here - expiration: 3600 # 1 hour in seconds - -password: - min_length: 8 - require_uppercase: true - require_lowercase: true - require_numbers: true - require_special: true - -oauth: - providers: - google: - client_id: your_google_client_id - client_secret: your_google_client_secret - github: - client_id: your_github_client_id - client_secret: your_github_client_secret - -redis: - url: redis://localhost:6379 - session_ttl: 86400 # 24 hours in seconds diff --git a/gb-auth/src/error.rs b/gb-auth/src/error.rs deleted file mode 100644 index e113833..0000000 --- a/gb-auth/src/error.rs +++ /dev/null @@ -1,26 +0,0 @@ -use gb_core::Error as CoreError; -use redis::RedisError; -use sqlx::Error as SqlxError; -use thiserror::Error; - -#[derive(Debug, Error)] -pub enum AuthError { - #[error("Invalid token")] - InvalidToken, - #[error("Invalid credentials")] - InvalidCredentials, - #[error("Database error: {0}")] - Database(#[from] SqlxError), - #[error("Redis error: {0}")] - Redis(#[from] RedisError), - #[error("Internal error: {0}")] - Internal(String), -} - -impl From for AuthError { - fn from(err: CoreError) -> Self { - match err { - CoreError { .. } => AuthError::Internal(err.to_string()), - } - } -} diff --git a/gb-auth/src/errors.rs b/gb-auth/src/errors.rs deleted file mode 100644 index e709d39..0000000 --- a/gb-auth/src/errors.rs +++ /dev/null @@ -1,24 +0,0 @@ -use gb_core::Error as CoreError; -use thiserror::Error; - -#[derive(Debug, Error)] -pub enum AuthError { - #[error("Invalid token")] - InvalidToken, - #[error("Invalid credentials")] - InvalidCredentials, - #[error("Database error: {0}")] - Database(#[from] sqlx::Error), - #[error("Redis error: {0}")] - Redis(#[from] redis::RedisError), - #[error("Internal error: {0}")] - Internal(String), -} - -impl From for AuthError { - fn from(err: CoreError) -> Self { - match err { - CoreError { .. } => AuthError::Internal(err.to_string()), - } - } -} \ No newline at end of file diff --git a/gb-auth/src/handlers/mod.rs b/gb-auth/src/handlers/mod.rs deleted file mode 100644 index c26b2a1..0000000 --- a/gb-auth/src/handlers/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod auth_handler; - diff --git a/gb-auth/src/lib.rs b/gb-auth/src/lib.rs deleted file mode 100644 index 77eb06f..0000000 --- a/gb-auth/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod error; -pub mod handlers; -pub mod models; -pub mod services; // Make services module public -pub mod middleware; - -pub use error::AuthError; diff --git a/gb-auth/src/middleware/auth_middleware.rs b/gb-auth/src/middleware/auth_middleware.rs deleted file mode 100644 index 277ad4e..0000000 --- a/gb-auth/src/middleware/auth_middleware.rs +++ /dev/null @@ -1,33 +0,0 @@ -use axum::{ - http::{Request, Response}, - middleware::Next, - body::Body, -}; -use headers::{Authorization, authorization::Bearer}; -use jsonwebtoken::{decode, DecodingKey, Validation}; -use serde::{Serialize, Deserialize}; -use crate::AuthError; - -#[derive(Debug, Serialize, Deserialize)] -struct Claims { - sub: String, - exp: i64, -} - -pub async fn auth_middleware( - auth: Authorization, - request: Request, - next: Next, -) -> Result, AuthError> { - let token = auth.token(); - let key = DecodingKey::from_secret(b"secret"); - let validation = Validation::default(); - - match decode::(token, &key, &validation) { - Ok(_claims) => { - let response = next.run(request).await; - Ok(response) - } - Err(_) => Err(AuthError::InvalidToken), - } -} \ No newline at end of file diff --git a/gb-auth/src/middleware/mod.rs b/gb-auth/src/middleware/mod.rs deleted file mode 100644 index 8e901a8..0000000 --- a/gb-auth/src/middleware/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod auth_middleware; - -pub use auth_middleware::*; \ No newline at end of file diff --git a/gb-auth/src/models/auth.rs b/gb-auth/src/models/auth.rs deleted file mode 100644 index 827ac9a..0000000 --- a/gb-auth/src/models/auth.rs +++ /dev/null @@ -1,15 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Deserialize)] -pub struct LoginRequest { - pub email: String, - pub password: String, -} - -#[derive(Debug, Serialize)] -pub struct LoginResponse { - pub access_token: String, - pub refresh_token: String, - pub token_type: String, - pub expires_in: i64, -} \ No newline at end of file diff --git a/gb-auth/src/models/mod.rs b/gb-auth/src/models/mod.rs deleted file mode 100644 index e3585d7..0000000 --- a/gb-auth/src/models/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -mod auth; -pub mod user; - -pub use auth::{LoginRequest, LoginResponse}; \ No newline at end of file diff --git a/gb-auth/src/models/user.rs b/gb-auth/src/models/user.rs deleted file mode 100644 index d537cc6..0000000 --- a/gb-auth/src/models/user.rs +++ /dev/null @@ -1,48 +0,0 @@ -use serde::{Serialize, Deserialize}; -use uuid::Uuid; -use chrono::{DateTime, Utc}; - -#[derive(Debug, Serialize, Deserialize)] -pub enum UserRole { - Admin, - User, - Guest, -} - -#[derive(Debug, Serialize, Deserialize)] -pub enum UserStatus { - Active, - Inactive, - Suspended, -} - -impl From for UserRole { - fn from(s: String) -> Self { - match s.to_lowercase().as_str() { - "admin" => UserRole::Admin, - "guest" => UserRole::Guest, - _ => UserRole::User, - } - } -} - -impl From for UserStatus { - fn from(s: String) -> Self { - match s.to_lowercase().as_str() { - "inactive" => UserStatus::Inactive, - "suspended" => UserStatus::Suspended, - _ => UserStatus::Active, - } - } -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct DbUser { - pub id: Uuid, - pub email: String, - pub password_hash: String, - pub role: UserRole, - pub status: UserStatus, - pub created_at: DateTime, - pub updated_at: DateTime, -} \ No newline at end of file diff --git a/gb-auth/src/services/auth_service.rs b/gb-auth/src/services/auth_service.rs deleted file mode 100644 index e69de29..0000000 diff --git a/gb-auth/src/services/mod.rs b/gb-auth/src/services/mod.rs deleted file mode 100644 index e69de29..0000000 diff --git a/gb-auth/src/utils/mod.rs b/gb-auth/src/utils/mod.rs deleted file mode 100644 index 6d9e419..0000000 --- a/gb-auth/src/utils/mod.rs +++ /dev/null @@ -1 +0,0 @@ -// Auth utilities module \ No newline at end of file diff --git a/gb-auth/tests/auth_service_tests.rs b/gb-auth/tests/auth_service_tests.rs deleted file mode 100644 index e69de29..0000000 diff --git a/gb-automation/Cargo.toml b/gb-automation/Cargo.toml deleted file mode 100644 index 985784e..0000000 --- a/gb-automation/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "gb-automation" -version = { workspace = true } -edition = { workspace = true } -authors = { workspace = true } -license = { workspace = true } - -[dependencies] -gb-core = { path = "../gb-core" } -image = { version = "0.24", features = ["webp", "jpeg", "png", "gif"] } -chromiumoxide = { version = "0.5", features = ["tokio-runtime"] } -futures-util = "0.3" -async-trait= { workspace = true } -tokio= { workspace = true } -serde= { workspace = true } -serde_json= { workspace = true } -thiserror= { workspace = true } -tracing= { workspace = true } -uuid= { workspace = true } -regex = "1.10" -fantoccini = "0.19" -headless_chrome = "1.0" -async-recursion = "1.0" - -[dev-dependencies] -rstest= { workspace = true } -tokio-test = "0.4" -mock_instant = "0.2" \ No newline at end of file diff --git a/gb-automation/src/lib.rs b/gb-automation/src/lib.rs deleted file mode 100644 index b8399dd..0000000 --- a/gb-automation/src/lib.rs +++ /dev/null @@ -1,4 +0,0 @@ -mod web; - -pub use chromiumoxide::element::Element; -pub use web::WebAutomation; \ No newline at end of file diff --git a/gb-automation/src/process.rs b/gb-automation/src/process.rs deleted file mode 100644 index b4c7fcd..0000000 --- a/gb-automation/src/process.rs +++ /dev/null @@ -1,127 +0,0 @@ -use std::{ - path::{Path, PathBuf}, - process::{Child, Command, Stdio}, -}; -use tokio::sync::Mutex; -use tracing::{error, instrument}; -use uuid::Uuid; -use gb_core::{Error, Result}; - -#[derive(Debug)] -struct Process { - id: Uuid, - handle: Child, -} - -pub struct ProcessAutomation { - working_dir: PathBuf, - processes: Mutex>, -} - -impl ProcessAutomation { - pub fn new(working_dir: impl AsRef) -> Self { - Self { - working_dir: working_dir.as_ref().to_path_buf(), - processes: Mutex::new(Vec::new()), - } - } - - #[instrument(skip(self, command))] - pub async fn execute(&self, command: &str, args: &[&str]) -> Result { - let output = Command::new(command) - .args(args) - .current_dir(&self.working_dir) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .output() - .map_err(|e| Error::internal(format!("Failed to execute command: {}", e)))?; - - if !output.status.success() { - let error = String::from_utf8_lossy(&output.stderr); - return Err(Error::internal(format!("Command failed: {}", error))); - } - - let stdout = String::from_utf8_lossy(&output.stdout).to_string(); - Ok(stdout) - } - - pub async fn spawn(&self, command: &str, args: &[&str]) -> Result { - let child = Command::new(command) - .args(args) - .current_dir(&self.working_dir) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn() - .map_err(|e| Error::internal(format!("Failed to spawn process: {}", e)))?; - - let id = Uuid::new_v4(); - let mut processes = self.processes.lock().await; - processes.push(Process { id, handle: child }); - - Ok(id) - } - - pub async fn kill(&self, id: Uuid) -> Result<()> { - let mut processes = self.processes.lock().await; - - if let Some(index) = processes.iter().position(|p| p.id == id) { - let mut process = processes.remove(index); - process.handle.kill() - .map_err(|e| Error::internal(format!("Failed to kill process: {}", e)))?; - } - Ok(()) - } - - pub async fn cleanup(&self) -> Result<()> { - let mut processes = self.processes.lock().await; - - for process in processes.iter_mut() { - if let Err(e) = process.handle.kill() { - error!("Failed to kill process {}: {}", process.id, e); -} - } - - processes.clear(); - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use tempfile::tempdir; - - fn automation() -> ProcessAutomation { - let dir = tempdir().unwrap(); - ProcessAutomation::new(dir.path()) - } - - #[tokio::test] - async fn test_execute() -> Result<()> { - let automation = automation(); - let output = automation.execute("echo", &["Hello, World!"]).await?; - assert!(output.contains("Hello, World!")); - Ok(()) - } - - #[tokio::test] - async fn test_spawn_and_kill() -> Result<()> { - let automation = automation(); - let id = automation.spawn("sleep", &["1"]).await?; - automation.kill(id).await?; - Ok(()) - } - - #[tokio::test] - async fn test_cleanup() -> Result<()> { - let automation = automation(); - automation.spawn("sleep", &["1"]).await?; - automation.spawn("sleep", &["2"]).await?; - automation.cleanup().await?; - - let processes = automation.processes.lock().await; - assert!(processes.is_empty()); - - Ok(()) -} -} diff --git a/gb-automation/src/web.rs b/gb-automation/src/web.rs deleted file mode 100644 index 21ed6ec..0000000 --- a/gb-automation/src/web.rs +++ /dev/null @@ -1,61 +0,0 @@ -use chromiumoxide::{Browser, Element}; -use chromiumoxide::page::Page; -use chromiumoxide::browser::BrowserConfig; -use futures_util::StreamExt; -use gb_core::{Error, Result}; -use std::time::Duration; - -pub struct WebAutomation { - browser: Browser, -} - -impl WebAutomation { - pub async fn new() -> Result { - let config = BrowserConfig::builder() - .build() - .map_err(|e| Error::internal(e.to_string()))?; - - let (browser, handler) = Browser::launch(config) - .await - .map_err(|e| Error::internal(e.to_string()))?; - - // Spawn the handler in the background - tokio::spawn(async move { - handler.for_each(|_| async {}).await; - }); - - Ok(Self { browser }) - } - - pub async fn new_page(&self) -> Result { - self.browser - .new_page("about:blank") - .await - .map_err(|e| Error::internal(e.to_string())) - } - - pub async fn navigate(&self, page: &Page, url: &str) -> Result<()> { - page.goto(url) - .await - .map_err(|e| Error::internal(e.to_string()))?; - Ok(()) - } - - pub async fn take_screenshot(&self, page: &Page) -> Result> { - let params = chromiumoxide::page::ScreenshotParams::builder().build(); - - page.screenshot(params) - .await - .map_err(|e| Error::internal(e.to_string())) - } - - pub async fn find_element(&self, page: &Page, selector: &str, timeout: Duration) -> Result { - tokio::time::timeout( - timeout, - page.find_element(selector) - ) - .await - .map_err(|_| Error::internal("Timeout waiting for element"))? - .map_err(|e| Error::internal(e.to_string())) - } -} \ No newline at end of file diff --git a/gb-calendar/Cargo.toml b/gb-calendar/Cargo.toml deleted file mode 100644 index 0a66474..0000000 --- a/gb-calendar/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "gb-calendar" -version = { workspace = true } -edition = { workspace = true } -authors = { workspace = true } -license = { workspace = true } - -[dependencies] -gb-core = { path = "../gb-core" } diff --git a/gb-calendar/src/lib.rs b/gb-calendar/src/lib.rs deleted file mode 100644 index e69de29..0000000 diff --git a/gb-cloud/Cargo.toml b/gb-cloud/Cargo.toml deleted file mode 100644 index 9b82c92..0000000 --- a/gb-cloud/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "gb-cloud" -version = { workspace = true } -edition = { workspace = true } -authors = { workspace = true } -license = { workspace = true } - -[dependencies] -gb-core = { path = "../gb-core" } -async-trait= { workspace = true } -tokio= { workspace = true } -serde = { version = "1.0", features = ["derive"] } -thiserror= { workspace = true } -tracing= { workspace = true } - -[dev-dependencies] -rstest= { workspace = true } -tokio-test = "0.4" -tempfile = "3.8" diff --git a/gb-cloud/src/lib.rs b/gb-cloud/src/lib.rs deleted file mode 100644 index e69de29..0000000 diff --git a/gb-core/Cargo.toml b/gb-core/Cargo.toml deleted file mode 100644 index b218909..0000000 --- a/gb-core/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "gb-core" -version = { workspace = true } -edition = { workspace = true } -authors = { workspace = true } -license = { workspace = true } - -[dependencies] -tokio-tungstenite = { workspace = true } -async-trait= { workspace = true } -serde= { workspace = true } -uuid= { workspace = true } -tokio= { workspace = true } -thiserror= { workspace = true } -chrono= { workspace = true } -tracing= { workspace = true } -axum = { version = "0.7", features = ["json"] } -serde_json = "1.0" -sqlx = { workspace = true } -redis = { workspace = true } -minio = { workspace = true } -zitadel = { workspace = true } -rdkafka = { workspace = true } -tonic = { workspace = true } -actix-web ={ workspace = true } -anyhow = { workspace = true } -jsonwebtoken = { workspace = true } -lettre= { workspace = true } - -[dev-dependencies] -mockall= { workspace = true } -rstest= { workspace = true } -tokio-test = { workspace = true } \ No newline at end of file diff --git a/gb-core/src/config.rs b/gb-core/src/config.rs deleted file mode 100644 index f8b6d0e..0000000 --- a/gb-core/src/config.rs +++ /dev/null @@ -1,114 +0,0 @@ -use serde::Deserialize; -use std::env; - -#[derive(Clone, Debug, Deserialize)] -pub struct AppConfig { - pub server: ServerConfig, - pub database: DatabaseConfig, - pub redis: RedisConfig, - pub kafka: KafkaConfig, - // pub zitadel: ZitadelConfig, - pub minio: MinioConfig, - pub email: EmailConfig, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct ServerConfig { - pub host: String, - pub port: u16, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct DatabaseConfig { - pub url: String, - pub max_connections: u32, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct RedisConfig { - pub url: String, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct KafkaConfig { - pub brokers: String, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct ZitadelConfig { - pub domain: String, - pub client_id: String, - pub client_secret: String, - pub access_token: String, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct MinioConfig { - pub endpoint: String, - pub access_key: String, - pub secret_key: String, - pub use_ssl: bool, - pub bucket: String, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct EmailConfig { - pub smtp_server: String, - pub smtp_port: u16, - pub username: String, - pub password: String, - pub from_email: String, -} - -impl AppConfig { - pub fn from_env() -> Self { - Self { - server: ServerConfig { - host: env::var("SERVER_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()), - port: env::var("SERVER_PORT") - .unwrap_or_else(|_| "8080".to_string()) - .parse() - .expect("Invalid SERVER_PORT"), - }, - database: DatabaseConfig { - url: env::var("DATABASE_URL").expect("DATABASE_URL must be set"), - max_connections: env::var("DATABASE_MAX_CONNECTIONS") - .unwrap_or_else(|_| "5".to_string()) - .parse() - .expect("Invalid DATABASE_MAX_CONNECTIONS"), - }, - redis: RedisConfig { - url: env::var("REDIS_URL").expect("REDIS_URL must be set"), - }, - kafka: KafkaConfig { - brokers: env::var("KAFKA_BROKERS").expect("KAFKA_BROKERS must be set"), - }, - // zitadel: ZitadelConfig { - // domain: env::var("ZITADEL_DOMAIN").expect("ZITADEL_DOMAIN must be set"), - // client_id: env::var("ZITADEL_CLIENT_ID").expect("ZITADEL_CLIENT_ID must be set"), - // client_secret: env::var("ZITADEL_CLIENT_SECRET") - // .expect("ZITADEL_CLIENT_SECRET must be set"), - // }, - minio: MinioConfig { - endpoint: env::var("MINIO_ENDPOINT").expect("MINIO_ENDPOINT must be set"), - access_key: env::var("MINIO_ACCESS_KEY").expect("MINIO_ACCESS_KEY must be set"), - secret_key: env::var("MINIO_SECRET_KEY").expect("MINIO_SECRET_KEY must be set"), - use_ssl: env::var("MINIO_USE_SSL") - .unwrap_or_else(|_| "false".to_string()) - .parse() - .expect("Invalid MINIO_USE_SSL"), - bucket: env::var("MINIO_BUCKET").expect("MINIO_BUCKET must be set"), - }, - email: EmailConfig { - smtp_server: env::var("EMAIL_SMTP_SERVER").expect("EMAIL_SMTP_SERVER must be set"), - smtp_port: env::var("EMAIL_SMTP_PORT") - .unwrap_or_else(|_| "587".to_string()) - .parse() - .expect("Invalid EMAIL_SMTP_PORT"), - username: env::var("EMAIL_USERNAME").expect("EMAIL_USERNAME must be set"), - password: env::var("EMAIL_PASSWORD").expect("EMAIL_PASSWORD must be set"), - from_email: env::var("EMAIL_FROM").expect("EMAIL_FROM must be set"), - }, - } - } -} diff --git a/gb-core/src/db.rs b/gb-core/src/db.rs deleted file mode 100644 index eddf5ff..0000000 --- a/gb-core/src/db.rs +++ /dev/null @@ -1,69 +0,0 @@ -use crate::config::AppConfig; -use anyhow::Result; -use minio::s3::client::{Client as MinioClient, ClientBuilder as MinioClientBuilder}; -use minio::s3::creds::StaticProvider; -use minio::s3::http::BaseUrl; -use rdkafka::producer::FutureProducer; -use rdkafka::ClientConfig; -use redis::aio::ConnectionManager as RedisConnectionManager; -use sqlx::postgres::{PgPool, PgPoolOptions}; -use std::str::FromStr; -// use zitadel::api::clients::ClientBuilder; -// use zitadel::api::interceptors::AccessTokenInterceptor; -// use zitadel::api::zitadel::auth::v1::auth_service_client::AuthServiceClient; - -pub async fn init_postgres(config: &AppConfig) -> Result { - let pool = PgPoolOptions::new() - .max_connections(config.database.max_connections) - .connect(&config.database.url) - .await - .map_err(|e| anyhow::anyhow!(e))?; - - Ok(pool) -} - -pub async fn init_redis(config: &AppConfig) -> Result { - let client = redis::Client::open(config.redis.url.as_str())?; - let connection_manager = RedisConnectionManager::new(client).await?; - - Ok(connection_manager) -} - -pub async fn init_kafka(config: &AppConfig) -> Result { - let producer: FutureProducer = ClientConfig::new() - .set("bootstrap.servers", &config.kafka.brokers) - .set("message.timeout.ms", "5000") - .create()?; - - Ok(producer) -} - -pub async fn init_zitadel( - _config: &AppConfig, -) -> Result< - (), - Box> - { - - // TODO: https://github.com/smartive/zitadel-rust/blob/be389ca08c7f82d36fc1bcc36d2d9eb8666b22cd/examples/fetch_profile_with_service_account.rs#L18 - Ok(()) -} - -pub async fn init_minio( - config: &AppConfig, -) -> Result> { - // Construct the base URL - let base_url = format!("https://{}", config.minio.endpoint); - let base_url = BaseUrl::from_str(&base_url)?; - - // Create credentials provider - let credentials = StaticProvider::new(&config.minio.access_key, &config.minio.secret_key, None); - - // Build the MinIO client - let client = MinioClientBuilder::new(base_url.clone()) - .provider(Some(Box::new(credentials))) - //.secure(config.minio.use_ssl) - .build()?; - - Ok(client) -} diff --git a/gb-core/src/errors.rs b/gb-core/src/errors.rs deleted file mode 100644 index aca874d..0000000 --- a/gb-core/src/errors.rs +++ /dev/null @@ -1,123 +0,0 @@ -use thiserror::Error; -use axum::{ - response::{IntoResponse, Response}, - http::StatusCode, - Json, -}; -use serde_json::json; - -#[derive(Error, Debug)] -pub enum ErrorKind { - - #[error("Database error: {0}")] - Database(String), - - #[error("Configuration error: {0}")] - Configuration(String), - - #[error("Redis error: {0}")] - Redis(String), - - #[error("Kafka error: {0}")] - Kafka(String), - - #[error("Invalid input: {0}")] - InvalidInput(String), - - #[error("Not found: {0}")] - NotFound(String), - - #[error("Authentication error: {0}")] - Authentication(String), - - #[error("Authorization error: {0}")] - Authorization(String), - - #[error("Internal error: {0}")] - Internal(String), - - #[error("External service error: {0}")] - ExternalService(String), - - #[error("WebSocket error: {0}")] - WebSocket(String), - - #[error("Messaging error: {0}")] - Messaging(String), - - #[error("API HTTP Server error: {0}")] - Server(String), - -} - -#[derive(Debug)] -pub struct Error { - pub kind: ErrorKind, - pub message: String, -} - -impl Error { - pub fn new(kind: ErrorKind, message: impl Into) -> Self { - Self { - kind, - message: message.into(), - } - } - - pub fn internal(msg: T) -> Self { - Self::new(ErrorKind::Internal(msg.to_string()), msg.to_string()) - } - - pub fn redis(msg: T) -> Self { - Self::new(ErrorKind::Redis(msg.to_string()), msg.to_string()) - } - - pub fn kafka(msg: T) -> Self { - Self::new(ErrorKind::Kafka(msg.to_string()), msg.to_string()) - } - - pub fn database(msg: T) -> Self { - Self::new(ErrorKind::Database(msg.to_string()), msg.to_string()) - } - - pub fn websocket(msg: T) -> Self { - Self::new(ErrorKind::WebSocket(msg.to_string()), msg.to_string()) - } -} - -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}: {}", self.kind, self.message) - } -} - -impl std::error::Error for Error {} - -pub type Result = std::result::Result; - -#[derive(Debug)] -pub enum AuthError { - InvalidToken, - MissingToken, - InvalidCredentials, - Internal(String), -} - -impl IntoResponse for Error { - fn into_response(self) -> Response { - let status = match self.kind { - ErrorKind::NotFound(_) => StatusCode::NOT_FOUND, - ErrorKind::Authentication(_) => StatusCode::UNAUTHORIZED, - ErrorKind::Authorization(_) => StatusCode::FORBIDDEN, - ErrorKind::InvalidInput(_) => StatusCode::BAD_REQUEST, - _ => StatusCode::INTERNAL_SERVER_ERROR, - }; - - let body = Json(json!({ - "error": self.message, - "kind": format!("{:?}", self.kind) - })); - - (status, body).into_response() - } -} diff --git a/gb-core/src/lib.rs b/gb-core/src/lib.rs deleted file mode 100644 index bf1d0da..0000000 --- a/gb-core/src/lib.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod db; -pub mod errors; -pub mod models; -pub mod traits; -pub mod config; -pub mod utils; -pub use errors::{Error, ErrorKind, Result}; -pub use utils::{create_response, extract_user_id}; - diff --git a/gb-core/src/models.rs b/gb-core/src/models.rs deleted file mode 100644 index a187a26..0000000 --- a/gb-core/src/models.rs +++ /dev/null @@ -1,396 +0,0 @@ -use chrono::{DateTime, Utc}; -use minio::s3::client::Client as MinioClient; -use rdkafka::producer::FutureProducer; -use redis::aio::ConnectionManager as RedisConnectionManager; -use serde::{Deserialize, Serialize}; -use sqlx::PgPool; -use uuid::Uuid; -//use zitadel::api::zitadel::auth::v1::auth_service_client::AuthServiceClient; -use serde_json::Value as JsonValue; -use std::str::FromStr; - -use crate::config::AppConfig; - -#[derive(Debug)] -pub struct CoreError(pub String); - -// Add these near the top with other type definitions -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum CustomerStatus { - Active, - Inactive, - Suspended, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum SubscriptionTier { - Free, - Pro, - Enterprise, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct Instance { - pub id: Uuid, - pub customer_id: Uuid, - pub name: String, - pub status: String, - pub shard_id: i32, - pub region: String, - pub config: JsonValue, - pub created_at: DateTime, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct Room { - pub id: Uuid, - pub instance_id: Uuid, - pub name: String, - pub kind: String, - pub status: String, - pub config: JsonValue, - pub created_at: DateTime, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Message { - pub id: Uuid, - pub customer_id: Uuid, - pub instance_id: Uuid, - pub conversation_id: Uuid, - pub sender_id: Uuid, - pub kind: String, - pub content: String, - pub metadata: JsonValue, - pub created_at: Option>, - pub shard_key: Option, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct MessageFilter { - pub conversation_id: Option, - pub sender_id: Option, - pub from_date: Option>, - pub to_date: Option>, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct SearchQuery { - pub query: String, - pub conversation_id: Option, - pub from_date: Option>, - pub to_date: Option>, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct FileUpload { - pub content: Vec, - pub filename: String, - pub content_type: String, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct FileContent { - pub content: Vec, - pub content_type: String, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct Status { - pub code: String, - pub timestamp: DateTime, -} - -#[derive(Debug, Serialize, Deserialize)] -pub enum UserStatus { - Active, - Inactive, - Suspended, -} - -impl FromStr for UserStatus { - type Err = CoreError; - - fn from_str(s: &str) -> Result { - match s { - "active" => Ok(UserStatus::Active), - "inactive" => Ok(UserStatus::Inactive), - "suspended" => Ok(UserStatus::Suspended), - _ => Ok(UserStatus::Inactive), - } - } -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Track { - pub id: Uuid, - pub room_id: Uuid, - pub user_id: Uuid, - pub media_type: String, - pub created_at: DateTime, - pub updated_at: DateTime, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct User { - pub id: Uuid, - pub customer_id: Uuid, - pub instance_id: Uuid, - pub name: String, - pub email: String, - pub password_hash: String, - pub status: UserStatus, - pub metadata: JsonValue, - pub created_at: DateTime, -} - -// Update the Customer struct to include these fields -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Customer { - pub id: Uuid, - pub name: String, - pub max_instances: u32, - pub email: String, - pub status: CustomerStatus, // Add this field - pub subscription_tier: SubscriptionTier, // Add this field - pub created_at: DateTime, - pub updated_at: DateTime, -} - -impl Customer { - pub fn new( - name: String, - email: String, - subscription_tier: SubscriptionTier, - max_instances: u32, - ) -> Self { - Customer { - id: Uuid::new_v4(), - name, - email, - max_instances, - subscription_tier, - status: CustomerStatus::Active, // Default to Active - created_at: Utc::now(), - updated_at: Utc::now(), - } - } -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct RoomConfig { - pub instance_id: Uuid, - pub name: String, - pub max_participants: u32, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Connection { - pub id: Uuid, - pub room_id: Uuid, - pub user_id: Uuid, - pub connected_at: DateTime, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct TrackInfo { - pub room_id: Uuid, - pub user_id: Uuid, - pub media_type: String, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Subscription { - pub id: Uuid, - pub track_id: Uuid, - pub subscriber_id: Uuid, - pub created_at: DateTime, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Participant { - pub user_id: Uuid, - pub room_id: Uuid, - pub joined_at: DateTime, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct RoomStats { - pub participant_count: u32, - pub track_count: u32, - pub duration: i64, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct MessageId(pub Uuid); - -#[derive(Debug, Serialize, Deserialize)] -pub struct FileInfo { - pub id: Uuid, - pub filename: String, - pub content_type: String, - pub size: usize, - pub url: String, - pub created_at: DateTime, -} - -// App state shared across all handlers - - -// App state shared across all handlers -pub struct AppState { - pub minio_client: Option, - pub config: Option, - pub db_pool: Option, -} - -// File models -#[derive(Debug, Serialize, Deserialize)] -pub struct File { - pub id: Uuid, - pub user_id: Uuid, - pub folder_id: Option, - pub name: String, - pub path: String, - pub mime_type: String, - pub size: i64, - pub created_at: DateTime, - pub updated_at: DateTime, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct Folder { - pub id: Uuid, - pub user_id: Uuid, - pub parent_id: Option, - pub name: String, - pub path: String, - pub created_at: DateTime, - pub updated_at: DateTime, -} - -// Conversation models -#[derive(Debug, Serialize, Deserialize)] -pub struct Conversation { - pub id: Uuid, - pub name: String, - pub created_by: Uuid, - pub created_at: DateTime, - pub updated_at: DateTime, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct ConversationMember { - pub conversation_id: Uuid, - pub user_id: Uuid, - pub joined_at: DateTime, -} - -// Calendar models -#[derive(Debug, Serialize, Deserialize)] -pub struct CalendarEvent { - pub id: Uuid, - pub title: String, - pub description: Option, - pub location: Option, - pub start_time: DateTime, - pub end_time: DateTime, - pub user_id: Uuid, - pub created_at: DateTime, - pub updated_at: DateTime, -} - -// Task models -#[derive(Debug, Serialize, Deserialize)] -pub struct Task { - pub id: Uuid, - pub title: String, - pub description: Option, - pub due_date: Option>, - pub status: TaskStatus, - pub priority: TaskPriority, - pub user_id: Uuid, - pub created_at: DateTime, - pub updated_at: DateTime, -} - -#[derive(Debug, Serialize, Deserialize)] -pub enum TaskStatus { - Pending, - InProgress, - Completed, - Cancelled, -} - -#[derive(Debug, Serialize, Deserialize)] -pub enum TaskPriority { - Low, - Medium, - High, - Urgent, -} - -// Response models -#[derive(Debug, Serialize)] -pub struct ApiResponse { - pub success: bool, - pub message: Option, - pub data: Option, -} - -// Error models -#[derive(Debug, thiserror::Error)] -pub enum AppError { - #[error("Database error: {0}")] - Database(#[from] sqlx::Error), - - #[error("Redis error: {0}")] - Redis(#[from] redis::RedisError), - - #[error("Kafka error: {0}")] - Kafka(String), - - #[error("Zitadel error: {0}")] - Zitadel(#[from] tonic::Status), - - #[error("Minio error: {0}")] - Minio(String), - - #[error("Validation error: {0}")] - Validation(String), - - #[error("Not found: {0}")] - NotFound(String), - - #[error("Unauthorized: {0}")] - Unauthorized(String), - - #[error("Forbidden: {0}")] - Forbidden(String), - - #[error("Internal server error: {0}")] - Internal(String), -} - -impl actix_web::ResponseError for AppError { - fn error_response(&self) -> actix_web::HttpResponse { - let (status, error_message) = match self { - AppError::Validation(_) => (actix_web::http::StatusCode::BAD_REQUEST, self.to_string()), - AppError::NotFound(_) => (actix_web::http::StatusCode::NOT_FOUND, self.to_string()), - AppError::Unauthorized(_) => { - (actix_web::http::StatusCode::UNAUTHORIZED, self.to_string()) - } - AppError::Forbidden(_) => (actix_web::http::StatusCode::FORBIDDEN, self.to_string()), - _ => ( - actix_web::http::StatusCode::INTERNAL_SERVER_ERROR, - "Internal server error".to_string(), - ), - }; - - actix_web::HttpResponse::build(status).json(ApiResponse::<()> { - success: false, - message: Some(error_message), - data: None, - }) - } -} diff --git a/gb-core/src/traits.rs b/gb-core/src/traits.rs deleted file mode 100644 index e69de29..0000000 diff --git a/gb-core/src/utils.rs b/gb-core/src/utils.rs deleted file mode 100644 index e6bd42b..0000000 --- a/gb-core/src/utils.rs +++ /dev/null @@ -1,155 +0,0 @@ -use actix_web::{HttpRequest, HttpResponse}; -use chrono::{DateTime, Utc}; -use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation}; -use lettre::message::header::ContentType; -use lettre::transport::smtp::authentication::Credentials; -use lettre::{Message, SmtpTransport, Transport}; -use rdkafka::producer::{FutureProducer, FutureRecord}; -use rdkafka::util::Timeout; -use serde::{Deserialize, Serialize}; -use std::time::{Duration, SystemTime}; -use uuid::Uuid; - -use crate::config::AppConfig; -use crate::models::{ApiResponse, AppError, User}; - -// JWT Claims -#[derive(Debug, Serialize, Deserialize)] -pub struct Claims { - pub sub: String, // subject (user ID) - pub exp: usize, // expiration time - pub iat: usize, // issued at - pub email: String, // user email - pub username: String, // username -} - -// Generate JWT token -pub fn generate_jwt(user: &User, secret: &str) -> Result { - let expiration = SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .unwrap() - .as_secs() as usize + 86400; // 24 hours - - let issued_at = SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .unwrap() - .as_secs() as usize; - - let claims = Claims { - sub: user.id.to_string(), - exp: expiration, - iat: issued_at, - email: user.email.clone(), - username: user.email.clone(), - }; - - encode( - &Header::default(), - &claims, - &EncodingKey::from_secret(secret.as_bytes()), - ) - .map_err(|e| AppError::Internal(format!("Failed to generate JWT: {}", e))) -} - -// Validate JWT token -pub fn validate_jwt(token: &str, secret: &str) -> Result { - let validation = Validation::default(); - - decode::( - token, - &DecodingKey::from_secret(secret.as_bytes()), - &validation, - ) - .map(|data| data.claims) - .map_err(|e| AppError::Unauthorized(format!("Invalid token: {}", e))) -} - -// Extract user ID from request -pub fn extract_user_id(req: &HttpRequest) -> Result { - let auth_header = req - .headers() - .get("Authorization") - .ok_or_else(|| AppError::Unauthorized("Missing Authorization header".to_string()))? - .to_str() - .map_err(|_| AppError::Unauthorized("Invalid Authorization header".to_string()))?; - - if !auth_header.starts_with("Bearer ") { - return Err(AppError::Unauthorized("Invalid Authorization header format".to_string())); - } - - let token = &auth_header[7..]; - let claims = validate_jwt(token, "your-secret-key")?; - - Uuid::parse_str(&claims.sub) - .map_err(|_| AppError::Unauthorized("Invalid user ID in token".to_string())) -} - -// Send email -pub async fn send_email( - config: &AppConfig, - to_email: &str, - subject: &str, - body: &str, -) -> Result<(), AppError> { - let email = Message::builder() - .from(config.email.from_email.parse().unwrap()) - .to(to_email.parse().unwrap()) - .subject(subject) - .header(ContentType::TEXT_PLAIN) - .body(body.to_string()) - .map_err(|e| AppError::Internal(format!("Failed to create email: {}", e)))?; - - let creds = Credentials::new( - config.email.username.clone(), - config.email.password.clone(), - ); - - // Open a remote connection to the SMTP server - let mailer = SmtpTransport::relay(&config.email.smtp_server) - .unwrap() - .credentials(creds) - .build(); - - // Send the email - mailer.send(&email) - .map_err(|e| AppError::Internal(format!("Failed to send email: {}", e)))?; - - Ok(()) -} - -// Send message to Kafka -pub async fn send_to_kafka( - producer: &FutureProducer, - topic: &str, - key: &str, - payload: &str, -) -> Result<(), AppError> { - producer - .send( - FutureRecord::to(topic) - .key(key) - .payload(payload), - Timeout::After(Duration::from_secs(5)), - ) - .await - .map_err(|(e, _)| AppError::Kafka(format!("Failed to send message to Kafka: {}", e)))?; - - Ok(()) -} - -// Format datetime for JSON responses -pub fn format_datetime(dt: DateTime) -> String { - dt.to_rfc3339() -} - -// Create a standard API response -pub fn create_response( - data: T, - message: Option, -) -> HttpResponse { - HttpResponse::Ok().json(ApiResponse { - success: true, - message, - data: Some(data), - }) -} diff --git a/gb-document/Cargo.toml b/gb-document/Cargo.toml deleted file mode 100644 index 3c54f78..0000000 --- a/gb-document/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -name = "gb-document" -version = { workspace = true } -edition = { workspace = true } -authors = { workspace = true } -license = { workspace = true } - -[dependencies] -gb-core = { path = "../gb-core" } -lopdf = "0.31" -docx-rs = "0.4" -calamine = "0.21" -async-trait= { workspace = true } -tokio= { workspace = true } -serde= { workspace = true } -serde_json= { workspace = true } -thiserror= { workspace = true } -tracing= { workspace = true } -encoding_rs = "0.8" -zip = "0.6" - -[dev-dependencies] -rstest= { workspace = true } -tokio-test = "0.4" -tempfile = "3.8" diff --git a/gb-document/src/excel.rs b/gb-document/src/excel.rs deleted file mode 100644 index cb774e8..0000000 --- a/gb-document/src/excel.rs +++ /dev/null @@ -1,35 +0,0 @@ -use gb_core::{Result, Error}; -use calamine::{Reader, Xlsx, RangeDeserializerBuilder}; -use std::io::Cursor; -use tracing::{instrument, error}; - -pub struct ExcelProcessor; - -impl ExcelProcessor { - #[instrument(skip(data))] - pub fn extract_data(data: &[u8]) -> Result>> { - let cursor = Cursor::new(data); - let mut workbook = Xlsx::new(cursor) - .map_err(|e| Error::internal(format!("Failed to read Excel file: {}", e)))?; - - let sheet_name = workbook.sheet_names()[0].clone(); - let range = workbook.worksheet_range(&sheet_name) - .ok_or_else(|| Error::internal("Failed to get worksheet".to_string()))? - .map_err(|e| Error::internal(format!("Failed to read range: {}", e)))?; - - let mut result = Vec::new(); - for row in range.rows() { - let row_data: Vec = row.iter() - .map(|cell| cell.to_string()) - .collect(); - result.push(row_data); - } - - Ok(result) - } - - #[instrument(skip(headers, data))] - pub fn create_excel(headers: &[&str], data: &[Vec]) -> Result> { - todo!("Implement Excel creation using a suitable library"); - } - diff --git a/gb-document/src/lib.rs b/gb-document/src/lib.rs deleted file mode 100644 index e69de29..0000000 diff --git a/gb-document/src/pdf.rs b/gb-document/src/pdf.rs deleted file mode 100644 index c6f8073..0000000 --- a/gb-document/src/pdf.rs +++ /dev/null @@ -1,127 +0,0 @@ -use gb_core::{Result, Error}; -use lopdf::{Document, Object, StringFormat}; -use std::io::Cursor; -use tracing::{instrument, error}; - -pub struct PdfProcessor; - -impl PdfProcessor { - #[instrument(skip(data))] - pub fn extract_text(data: &[u8]) -> Result { - let doc = Document::load_from(Cursor::new(data)) - .map_err(|e| Error::internal(format!("Failed to load PDF: {}", e)))?; - - let mut text = String::new(); - for page_num in 1..=doc.get_pages().len() { - if let Ok(page_text) = Self::extract_page_text(&doc, page_num) { - text.push_str(&page_text); - text.push('\n'); - } - } - - Ok(text) - } - - #[instrument(skip(doc))] - fn extract_page_text(doc: &Document, page_num: u32) -> Result { - let page = doc.get_page(page_num) - .map_err(|e| Error::internal(format!("Failed to get page {}: {}", page_num, e)))?; - - let contents = doc.get_page_content(page) - .map_err(|e| Error::internal(format!("Failed to get page content: {}", e)))?; - - let mut text = String::new(); - for content in contents.iter() { - if let Ok(Object::String(s, StringFormat::Literal)) = content { - if let Ok(decoded) = String::from_utf8(s.clone()) { - text.push_str(&decoded); - } - } - } - - Ok(text) - } - - #[instrument(skip(data))] - pub fn merge_pdfs(pdfs: Vec<&[u8]>) -> Result> { - let mut merged = Document::new(); - let mut current_page = 1; - - for pdf_data in pdfs { - let doc = Document::load_from(Cursor::new(pdf_data)) - .map_err(|e| Error::internal(format!("Failed to load PDF: {}", e)))?; - - for (_, page) in doc.get_pages() { - merged.add_page(page.clone()); - current_page += 1; - } - } - - let mut output = Vec::new(); - merged.save_to(&mut Cursor::new(&mut output)) - .map_err(|e| Error::internal(format!("Failed to save merged PDF: {}", e)))?; - - Ok(output) - } - - #[instrument(skip(data))] - pub fn split_pdf(data: &[u8], pages: &[u32]) -> Result>> { - let doc = Document::load_from(Cursor::new(data)) - .map_err(|e| Error::internal(format!("Failed to load PDF: {}", e)))?; - - let mut result = Vec::new(); - for &page_num in pages { - let mut new_doc = Document::new(); - if let Ok(page) = doc.get_page(page_num) { - new_doc.add_page(page.clone()); - let mut output = Vec::new(); - new_doc.save_to(&mut Cursor::new(&mut output)) - .map_err(|e| Error::internal(format!("Failed to save split PDF: {}", e)))?; - result.push(output); - } - } - - Ok(result) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use rstest::*; - - fn create_test_pdf() -> Vec { - let mut doc = Document::new(); - doc.add_page(lopdf::dictionary! { - "Type" => "Page", - "Contents" => Object::String(b"BT /F1 12 Tf 72 712 Td (Test Page) Tj ET".to_vec(), StringFormat::Literal), - }); - let mut output = Vec::new(); - doc.save_to(&mut Cursor::new(&mut output)).unwrap(); - output - } - - #[rstest] - fn test_extract_text() -> Result<()> { - let pdf_data = create_test_pdf(); - let text = PdfProcessor::extract_text(&pdf_data)?; - assert!(text.contains("Test Page")); - Ok(()) - } - - #[rstest] - fn test_merge_pdfs() -> Result<()> { - let pdf1 = create_test_pdf(); - let pdf2 = create_test_pdf(); - let merged = PdfProcessor::merge_pdfs(vec[build-dependencies]&pdf1, &pdf2])?; - Ok(()) - } - - #[rstest] - fn test_split_pdf() -> Result<()> { - let pdf_data = create_test_pdf(); - let split = PdfProcessor::split_pdf(&pdf_data, &[1])?; - assert_eq!(split.len(), 1); - Ok(()) - } -} diff --git a/gb-document/src/word.rs b/gb-document/src/word.rs deleted file mode 100644 index 4607a91..0000000 --- a/gb-document/src/word.rs +++ /dev/null @@ -1,105 +0,0 @@ -use gb_core::{Result, Error}; -use docx_rs::{Docx, Paragraph, Run, RunText}; -use std::io::{Cursor, Read}; -use tracing::{instrument, error}; - -pub struct WordProcessor; - -impl WordProcessor { - #[instrument(skip(data))] - pub fn extract_text(data: &[u8]) -> Result { - let doc = Docx::from_reader(Cursor::new(data)) - .map_err(|e| Error::internal(format!("Failed to read DOCX: {}", e)))?; - - let mut text = String::new(); - for para in doc.document.paragraphs() { - for run in para.runs() { - if let Some(text_content) = run.text() { - text.push_str(text_content); - } - text.push(' '); - } - text.push('\n'); - } - - Ok(text) - } - - #[instrument(skip(content))] - pub fn create_document(content: &str) -> Result> { - let mut docx = Docx::new(); - - for line in content.lines() { - let paragraph = Paragraph::new() - .add_run( - Run::new().add_text(RunText::new(line)) - ); - docx = docx.add_paragraph(paragraph); - } - - let mut output = Vec::new(); - docx.build() - .pack(&mut Cursor::new(&mut output)) - .map_err(|e| Error::internal(format!("Failed to create DOCX: {}", e)))?; - - Ok(output) - } - - #[instrument(skip(template_data, variables))] - pub fn fill_template(template_data: &[u8], variables: &serde_json::Value) -> Result> { - let doc = Docx::from_reader(Cursor::new(template_data)) - .map_err(|e| Error::internal(format!("Failed to read template: {}", e)))?; - - let mut new_doc = doc.clone(); - - for para in new_doc.document.paragraphs_mut() { - for run in para.runs_mut() { - if let Some(text) = run.text_mut() { - let mut new_text = text.clone(); - for (key, value) in variables.as_object().unwrap() { - let placeholder = format!("{{{}}}", key); - new_text = new_text.replace(&placeholder, value.as_str().unwrap_or("")); - } - *text = new_text; - } - } - } - - let mut output = Vec::new(); - new_doc.build() - .pack(&mut Cursor::new(&mut output)) - .map_err(|e| Error::internal(format!("Failed to save filled template: {}", e)))?; - - Ok(output) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use rstest::*; - use serde_json::json; - - #[rstest] - fn test_create_document() -> Result<()> { - let content = "Test document\nSecond line"; - let doc_data = WordProcessor::create_document(content)?; - - let extracted_text = WordProcessor::extract_text(&doc_data)?; - assert!(extracted_text.contains("Test document")); - assert!(extracted_text.contains("Second line")); - Ok(()) - } - - #[rstest] - fn test_fill_template() -> Result<()> { - let template = WordProcessor::create_document("Hello, {name}!")?; - "name": "World" - }); - - let filled = WordProcessor::fill_template(&template, &variables)?; - let text = WordProcessor::extract_text(&filled)?; - assert!(text.contains("Hello, World!")); - Ok(()) - } -} diff --git a/gb-file/Cargo.toml b/gb-file/Cargo.toml deleted file mode 100644 index 3d0b223..0000000 --- a/gb-file/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "gb-file" -version = { workspace = true } -edition = { workspace = true } -authors = { workspace = true } -license = { workspace = true } - -[dependencies] -gb-core = { path = "../gb-core" } -async-trait= { workspace = true } -tokio= { workspace = true } -serde = { workspace = true , features = ["derive"] } -serde_json ={ workspace = true } -thiserror= { workspace = true } -tracing= { workspace = true } -futures ={ workspace = true } -uuid = { workspace = true } -jsonwebtoken = { workspace = true } -lettre= { workspace = true } -minio = { workspace = true } -actix-web ={ workspace = true } -actix-multipart ={ workspace = true } -sanitize-filename = { workspace = true } -tempfile = { workspace = true } -log = { workspace = true } -env_logger = { workspace = true } -tokio-stream = { workspace = true } - -[dev-dependencies] -rstest= { workspace = true } -tokio-test = "0.4" -tempfile = "3.8" diff --git a/gb-file/src/lib.rs b/gb-file/src/lib.rs deleted file mode 100644 index 30ef99f..0000000 --- a/gb-file/src/lib.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod handlers; \ No newline at end of file diff --git a/gb-image/Cargo.toml b/gb-image/Cargo.toml deleted file mode 100644 index 43ad260..0000000 --- a/gb-image/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "gb-image" -version = { workspace = true } -edition = { workspace = true } -authors = { workspace = true } -license = { workspace = true } - -[dependencies] -gb-core = { path = "../gb-core" } -image = { version = "0.24", features = ["webp", "jpeg", "png", "gif"] } -imageproc = "0.23" -rusttype = "0.9" -async-trait= { workspace = true } -tokio= { workspace = true } -serde= { workspace = true } -serde_json= { workspace = true } -thiserror= { workspace = true } -tracing= { workspace = true } -tempfile = "3.8" - -[dev-dependencies] -rstest= { workspace = true } -tokio-test = "0.4" - - -[build-dependencies] -reqwest = { version = "0.11", features = ["blocking"] } \ No newline at end of file diff --git a/gb-image/assets/DejaVuSans.ttf b/gb-image/assets/DejaVuSans.ttf deleted file mode 100644 index 216e450..0000000 --- a/gb-image/assets/DejaVuSans.ttf +++ /dev/null @@ -1,1794 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Page not found · GitHub · GitHub - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- Skip to content - - - - - - - - - - - - - - - - - - - - -
-
- - - - - - - - - - - - - - -
- -
- - - - - - - - -
- - - - - -
- - - - - - - - - -
-
- - - -
-
- -
-
- 404 “This is not the web page you are looking for” - - - - - - - - - - - - -
-
- -
-
- -
- - -
-
- -
- -
- -
- - - - - - - - - - - - - - - - - - - - - -
- -
-
- - - diff --git a/gb-image/src/build.rs b/gb-image/src/build.rs deleted file mode 100644 index ff4fa99..0000000 --- a/gb-image/src/build.rs +++ /dev/null @@ -1,21 +0,0 @@ -use std::fs; -use std::path::Path; - -fn main() { - let assets_dir = Path::new("assets"); - if !assets_dir.exists() { - fs::create_dir(assets_dir).expect("Failed to create assets directory"); - } - - let font_path = assets_dir.join("DejaVuSans.ttf"); - if !font_path.exists() { - let font_url = "https://github.com/dejavu-fonts/dejavu-fonts/raw/master/ttf/DejaVuSans.ttf"; - let response = reqwest::blocking::get(font_url) - .expect("Failed to download font") - .bytes() - .expect("Failed to get font bytes"); - - fs::write(font_path, response) - .expect("Failed to save font file"); - } -} \ No newline at end of file diff --git a/gb-image/src/converter.rs b/gb-image/src/converter.rs deleted file mode 100644 index 7bf9a6d..0000000 --- a/gb-image/src/converter.rs +++ /dev/null @@ -1,74 +0,0 @@ -use std::io::Cursor; -use gb_core::{Result, Error}; -use image::{ImageOutputFormat, DynamicImage}; -use tracing::instrument; - -pub struct ImageConverter; - -impl ImageConverter { - #[instrument] - pub fn to_jpeg(img: &DynamicImage, quality: u8) -> Result> { - let mut buffer = Cursor::new(Vec::new()); - img.write_to(&mut buffer, ImageOutputFormat::Jpeg(quality)) - .map_err(|e| Error::internal(format!("JPEG conversion failed: {}", e)))?; - Ok(buffer.into_inner()) - } - - #[instrument] - pub fn to_png(img: &DynamicImage) -> Result> { - let mut buffer = Cursor::new(Vec::new()); - img.write_to(&mut buffer, ImageOutputFormat::Png) - .map_err(|e| Error::internal(format!("PNG conversion failed: {}", e)))?; - Ok(buffer.into_inner()) - } - - #[instrument] - pub fn to_webp(img: &DynamicImage, quality: u8) -> Result> { - let mut buffer = Cursor::new(Vec::new()); - img.write_to(&mut buffer, ImageOutputFormat::WebP) - .map_err(|e| Error::internal(format!("WebP conversion failed: {}", e)))?; - Ok(buffer.into_inner()) - } - - #[instrument] - pub fn to_gif(img: &DynamicImage) -> Result> { - let mut buffer = Cursor::new(Vec::new()); - img.write_to(&mut buffer, ImageOutputFormat::Gif) - .map_err(|e| Error::internal(format!("GIF conversion failed: {}", e)))?; - Ok(buffer.into_inner()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use rstest::*; - - #[fixture] - fn test_image() -> DynamicImage { - DynamicImage::new_rgb8(100, 100) - } - - #[rstest] - fn test_jpeg_conversion(test_image: DynamicImage) -> Result<()> { - let jpeg_data = ImageConverter::to_jpeg(&test_image, 80)?; - assert!(!jpeg_data.is_empty()); - assert_eq!(image::guess_format(&jpeg_data).unwrap(), image::ImageFormat::Jpeg); - Ok(()) - } - - #[rstest] - fn test_png_conversion(test_image: DynamicImage) -> Result<()> { - let png_data = ImageConverter::to_png(&test_image)?; - assert!(!png_data.is_empty()); - assert_eq!(image::guess_format(&png_data).unwrap(), image::ImageFormat::Png); - Ok(()) - } - - #[rstest] - fn test_webp_conversion(test_image: DynamicImage) -> Result<()> { - let webp_data = ImageConverter::to_webp(&test_image, 80)?; - assert!(!webp_data.is_empty()); - Ok(()) - } -} diff --git a/gb-image/src/lib.rs b/gb-image/src/lib.rs deleted file mode 100644 index e2db2cb..0000000 --- a/gb-image/src/lib.rs +++ /dev/null @@ -1,54 +0,0 @@ -pub mod processor; -pub mod converter; - -pub use processor::ImageProcessor; -pub use converter::ImageConverter; -// Remove the ImageFormat re-export since it's private in the image crate -pub use image::ImageFormat; - -#[cfg(test)] -mod tests { - use super::*; - use gb_core::Result; - use image::{DynamicImage, Rgba}; - - #[tokio::test] - async fn test_image_processing_integration() -> Result<()> { - // Initialize components - let processor = ImageProcessor::new(); - - // Create test image - let mut image = DynamicImage::new_rgb8(200, 200); - - // Test image processing operations - let resized = processor.resize(&image, 100, 100); - assert_eq!(resized.width(), 100); - assert_eq!(resized.height(), 100); - - let cropped = processor.crop(&image, 50, 50, 100, 100)?; - assert_eq!(cropped.width(), 100); - assert_eq!(cropped.height(), 100); - - let _blurred = processor.apply_blur(&image, 1.0); - let _brightened = processor.adjust_brightness(&image, 10); - let _contrasted = processor.adjust_contrast(&image, 1.2); - - // Test text addition - processor.add_text( - &mut image, - "Integration Test", - 10, - 10, - 24.0, - Rgba([0, 0, 0, 255]), - )?; - - // Test format conversion - let _webp_data = ImageConverter::to_webp(&image, 80)?; - let _jpeg_data = ImageConverter::to_jpeg(&image, 80)?; - let _png_data = ImageConverter::to_png(&image)?; - let _gif_data = ImageConverter::to_gif(&image)?; - - Ok(()) - } -} diff --git a/gb-image/src/processor.rs b/gb-image/src/processor.rs deleted file mode 100644 index 84727aa..0000000 --- a/gb-image/src/processor.rs +++ /dev/null @@ -1,74 +0,0 @@ -use gb_core::{Error, Result}; -use image::{DynamicImage, Rgba}; -use imageproc::drawing::draw_text_mut; -use rusttype::{Font, Scale}; -use std::fs; - - -pub struct ImageProcessor; - -impl ImageProcessor { - pub fn new() -> Self { - Self - } - - - - pub fn resize(&self, image: &DynamicImage, width: u32, height: u32) -> DynamicImage { - image.resize(width, height, image::imageops::FilterType::Lanczos3) - } - - pub fn crop(&self, image: &DynamicImage, x: u32, y: u32, width: u32, height: u32) -> Result { - if x + width > image.width() || y + height > image.height() { - return Err(Error::internal("Crop dimensions exceed image bounds".to_string())); - } - Ok(image.crop_imm(x, y, width, height)) - } - - pub fn apply_blur(&self, image: &DynamicImage, sigma: f32) -> DynamicImage { - image.blur(sigma) - } - - pub fn adjust_brightness(&self, image: &DynamicImage, value: i32) -> DynamicImage { - image.brighten(value) - } - - pub fn adjust_contrast(&self, image: &DynamicImage, value: f32) -> DynamicImage { - image.adjust_contrast(value) - } - - pub fn add_text( - &self, - image: &mut DynamicImage, - text: &str, - x: i32, - y: i32, - size: f32, - color: Rgba, - ) -> Result<()> { - // Load the font file from assets (downloaded in build.rs) - let font_data = fs::read("assets/DejaVuSans.ttf") - .map_err(|e| Error::internal(format!("Failed to load font: {}", e)))?; - - let font = Font::try_from_vec(font_data) - .ok_or_else(|| Error::internal("Failed to parse font data".to_string()))?; - - let scale = Scale::uniform(size); - let image_buffer = image.as_mut_rgba8() - .ok_or_else(|| Error::internal("Failed to convert image to RGBA".to_string()))?; - - draw_text_mut( - image_buffer, - color, - x, - y, - scale, - &font, - text - ); - - Ok(()) - } - - -} \ No newline at end of file diff --git a/gb-infra/Cargo.toml b/gb-infra/Cargo.toml deleted file mode 100644 index 6bb8ff9..0000000 --- a/gb-infra/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "gb-infra" -version.workspace = true -edition.workspace = true -authors.workspace = true -license.workspace = true - -[dependencies] -dotenv = { workspace = true } -ctrlc = { workspace = true } -tokio = { workspace = true } -serde = { workspace = true } -serde_json = { workspace = true } -reqwest = { workspace = true } -flate2 = { workspace = true } -tar = { workspace = true } -zip = { workspace = true } - diff --git a/gb-infra/README.md b/gb-infra/README.md deleted file mode 100644 index 91f5cae..0000000 --- a/gb-infra/README.md +++ /dev/null @@ -1,20 +0,0 @@ - -# Backup - -## Fastest way to tranfer files between servers over TCP/IP - -rsync -avz --progress --bwlimit=0 -e "ssh -p 22 -T -c aes128-gcm@openssh.com -o Compression=no -o IPQoS=throughput" gbbackup@host.com.br:/opt/gbo/backup /home/user/Desktop - - -# Security -apt update && apt install -y fail2ban -systemctl enable fail2ban - - -apt update && apt install -y fail2ban iptables-persistent - -systemctl enable fail2ban -systemctl enable netfilter-persistent - -# Add -Docusign: https://www.docuseal.com/on-premises \ No newline at end of file diff --git a/gb-infra/architecture.png b/gb-infra/architecture.png deleted file mode 100644 index 3d46ac30ce2e07edadc4018fcbccea57bbd064c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 152065 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
A~z3kJ_F5vVlsNv|*6q*^aF&aAed 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� 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"] - Stalwart["✉️ Mail Server
(Stalwart)"] - end - - subgraph "Content & Collaboration" - Forgejo["📊 ALM Server
(Forgejo)"] - Static["🌐 Static Site Generator
(Website Static)"] - Minio["💾 Object Storage
(MinIO)"] - end - - subgraph "Communication & Delivery" - Caddy["🔄 Reverse Proxy
(Caddy)"] - LiveKit["💬 Real-time Communication
(LiveKit)"] - end - - subgraph "AI & Integration Layer" - LLM["🧠 LLM Engine
(Nomic LLM)"] - - subgraph "Bot Framework" - BotFramework["🤖 Bot Framework"] - - subgraph "Bot Capabilities" - MCP["📨 Message Control Protocol
(MCP)"] - GET["🔗 GET Web Service Calls"] - BASIC["⚙️ BASIC Engine"] - end - end - end - - %% Connection lines with colors - User --> |"User Access"| Caddy - Caddy --> |"Auth"| Zitadel - Caddy --> |"Code & Issues"| Forgejo - Caddy --> |"Content"| Static - Caddy --> |"Real-time"| LiveKit - Caddy --> |"AI & Bots"| BotFramework - - Zitadel --> |"SSO"| Forgejo - Zitadel --> |"Auth"| LiveKit - Zitadel --> |"Identity"| BotFramework - - Forgejo --> |"Store"| Minio - Static --> |"Assets"| Minio - - BotFramework --> MCP - BotFramework --> GET - BotFramework --> BASIC - BotFramework --> |"NLP"| LLM - - Stalwart --> |"Email"| BotFramework - LiveKit --> |"Messaging"| BotFramework - - %% Integration flows - dashed lines with colors - MCP -.-> |"Message Routing"| Stalwart - GET -.-> |"API Calls"| Forgejo - BASIC -.-> |"Scripting"| Minio - LLM -.-> |"Content Generation"| Static - - %% Apply styles - class User users - class Zitadel,Stalwart identity - class Forgejo,Static,Minio content - class Caddy,LiveKit communication - class LLM ai - class BotFramework,MCP,GET,BASIC bot \ No newline at end of file diff --git a/gb-infra/src/lib.rs b/gb-infra/src/lib.rs deleted file mode 100644 index de2a549..0000000 --- a/gb-infra/src/lib.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod manager; -pub mod setup; -pub mod services { - pub mod minio; - pub mod nginx; - pub mod postgresql; - pub mod stalwart; - pub mod zitadel; -} \ No newline at end of file diff --git a/gb-infra/src/manager.rs b/gb-infra/src/manager.rs deleted file mode 100644 index d125d38..0000000 --- a/gb-infra/src/manager.rs +++ /dev/null @@ -1,60 +0,0 @@ -use crate::services::{zitadel, stalwart, minio, postgresql, nginx}; -use dotenv::dotenv; -use std::sync::{Arc, Mutex}; -use std::thread; -use std::time::Duration; - -pub struct ServiceManager { - services: Vec>, -} - -impl ServiceManager { - pub fn new() -> Self { - dotenv().ok(); - ServiceManager { - services: vec![ - Box::new(zitadel::Zitadel::new()), - Box::new(stalwart::Stalwart::new()), - Box::new(minio::MinIO::new()), - Box::new(postgresql::PostgreSQL::new()), - Box::new(nginx::NGINX::new()), - ], - } - } - - pub fn start(&mut self) { - for service in &mut self.services { - service.start().unwrap(); - } - } - - pub fn stop(&mut self) { - for service in &mut self.services { - service.stop().unwrap(); - } - } - - pub fn run(&mut self) { - self.start(); - let running = Arc::new(Mutex::new(true)); - let running_clone = Arc::clone(&running); - - ctrlc::set_handler(move || { - println!("Exiting service manager..."); - let mut running = running_clone.lock().unwrap(); - *running = false; - }) - .expect("Failed to set Ctrl+C handler."); - - while *running.lock().unwrap() { - thread::sleep(Duration::from_secs(1)); - } - - self.stop(); - } -} - -pub trait Service { - fn start(&mut self) -> Result<(), String>; - fn stop(&mut self) -> Result<(), String>; -} diff --git a/gb-infra/src/services/minio.rs b/gb-infra/src/services/minio.rs deleted file mode 100644 index b46bdd4..0000000 --- a/gb-infra/src/services/minio.rs +++ /dev/null @@ -1,54 +0,0 @@ -use crate::manager::Service; -use std::env; -use std::process::Command; -use std::collections::HashMap; -use dotenv::dotenv; - -pub struct MinIO { - env_vars: HashMap, - process: Option, -} - -impl MinIO { - pub fn new() -> Self { - dotenv().ok(); - let env_vars = vec![ - "MINIO_ROOT_USER", - "MINIO_ROOT_PASSWORD", - "MINIO_VOLUMES", - "MINIO_ADDRESS", - ] - .into_iter() - .filter_map(|key| env::var(key).ok().map(|value| (key.to_string(), value))) - .collect(); - - MinIO { - env_vars, - process: None, - } - } -} - -impl Service for MinIO { - fn start(&mut self) -> Result<(), String> { - if self.process.is_some() { - return Err("MinIO is already running.".to_string()); - } - - let mut command = Command::new("/opt/gbo/bin/minio"); - for (key, value) in &self.env_vars { - command.env(key, value); - } - - self.process = Some(command.spawn().map_err(|e| e.to_string())?); - Ok(()) - } - - fn stop(&mut self) -> Result<(), String> { - if let Some(mut child) = self.process.take() { - child.kill().map_err(|e| e.to_string())?; - child.wait().map_err(|e| e.to_string())?; - } - Ok(()) - } -} diff --git a/gb-infra/src/services/nginx.rs b/gb-infra/src/services/nginx.rs deleted file mode 100644 index 48a7be1..0000000 --- a/gb-infra/src/services/nginx.rs +++ /dev/null @@ -1,83 +0,0 @@ -use crate::manager::Service; -use std::env; -use std::process::Command; -use std::collections::HashMap; -use dotenv::dotenv; - -pub struct NGINX { - env_vars: HashMap, - process: Option, -} - -impl NGINX { - pub fn new() -> Self { - dotenv().ok(); - let env_vars = vec![ - "NGINX_ERROR_LOG", - "NGINX_ACCESS_LOG", - ] - .into_iter() - .filter_map(|key| env::var(key).ok().map(|value| (key.to_string(), value))) - .collect(); - - NGINX { - env_vars, - process: None, - } - } -} - -impl Service for NGINX { - fn start(&mut self) -> Result<(), String> { - if self.process.is_some() { - return Err("NGINX is already running.".to_string()); - } - - // Configure NGINX logs - let error_log = self.env_vars.get("NGINX_ERROR_LOG").unwrap(); - let access_log = self.env_vars.get("NGINX_ACCESS_LOG").unwrap(); - - // Update NGINX configuration - let nginx_conf = format!( - r#" -error_log {} debug; -access_log {}; -events {{}} -http {{ - server {{ - listen 80; - server_name localhost; - location / {{ - root /var/www/html; - }} - }} -}} -"#, - error_log, access_log - ); - - // Write the configuration to /etc/nginx/nginx.conf - std::fs::write("/etc/nginx/nginx.conf", nginx_conf).map_err(|e| e.to_string())?; - - // Start NGINX - let mut command = Command::new("nginx"); - self.process = Some(command.spawn().map_err(|e| e.to_string())?); - Ok(()) - } - - fn stop(&mut self) -> Result<(), String> { - if let Some(mut child) = self.process.take() { - child.kill().map_err(|e| e.to_string())?; - child.wait().map_err(|e| e.to_string())?; - } - - // Stop NGINX - Command::new("nginx") - .arg("-s") - .arg("stop") - .status() - .map_err(|e| e.to_string())?; - - Ok(()) - } -} \ No newline at end of file diff --git a/gb-infra/src/services/postgresql.rs b/gb-infra/src/services/postgresql.rs deleted file mode 100644 index c29ac99..0000000 --- a/gb-infra/src/services/postgresql.rs +++ /dev/null @@ -1,89 +0,0 @@ -use crate::manager::Service; -use std::env; -use std::process::Command; -use std::collections::HashMap; -use dotenv::dotenv; - -pub struct PostgreSQL { - env_vars: HashMap, - process: Option, -} - -impl PostgreSQL { - pub fn new() -> Self { - dotenv().ok(); - let env_vars = vec![ - "POSTGRES_DATA_DIR", - "POSTGRES_PORT", - "POSTGRES_USER", - "POSTGRES_PASSWORD", - ] - .into_iter() - .filter_map(|key| env::var(key).ok().map(|value| (key.to_string(), value))) - .collect(); - - PostgreSQL { - env_vars, - process: None, - } - } -} - -impl Service for PostgreSQL { - fn start(&mut self) -> Result<(), String> { - if self.process.is_some() { - return Err("PostgreSQL is already running.".to_string()); - } - - // Initialize PostgreSQL data directory if it doesn't exist - let data_dir = self.env_vars.get("POSTGRES_DATA_DIR").unwrap(); - if !std::path::Path::new(data_dir).exists() { - Command::new("sudo") - .arg("-u") - .arg("postgres") - .arg("/usr/lib/postgresql/14/bin/initdb") - .arg("-D") - .arg(data_dir) - .status() - .map_err(|e| e.to_string())?; - } - - // Start PostgreSQL - let mut command = Command::new("sudo"); - command - .arg("-u") - .arg("postgres") - .arg("/usr/lib/postgresql/14/bin/pg_ctl") - .arg("start") - .arg("-D") - .arg(data_dir); - - for (key, value) in &self.env_vars { - command.env(key, value); - } - - self.process = Some(command.spawn().map_err(|e| e.to_string())?); - Ok(()) - } - - fn stop(&mut self) -> Result<(), String> { - if let Some(mut child) = self.process.take() { - child.kill().map_err(|e| e.to_string())?; - child.wait().map_err(|e| e.to_string())?; - } - - // Stop PostgreSQL - let data_dir = self.env_vars.get("POSTGRES_DATA_DIR").unwrap(); - Command::new("sudo") - .arg("-u") - .arg("postgres") - .arg("/usr/lib/postgresql/14/bin/pg_ctl") - .arg("stop") - .arg("-D") - .arg(data_dir) - .status() - .map_err(|e| e.to_string())?; - - Ok(()) - } -} \ No newline at end of file diff --git a/gb-infra/src/services/stalwart.rs b/gb-infra/src/services/stalwart.rs deleted file mode 100644 index 89dff63..0000000 --- a/gb-infra/src/services/stalwart.rs +++ /dev/null @@ -1,58 +0,0 @@ -use crate::manager::Service; -use std::env; -use std::process::Command; -use std::collections::HashMap; -use dotenv::dotenv; - -pub struct Stalwart { - env_vars: HashMap, - process: Option, -} - -impl Stalwart { - pub fn new() -> Self { - dotenv().ok(); - let env_vars = vec![ - "STALWART_LOG_LEVEL", - "STALWART_OAUTH_PROVIDER", - "STALWART_OAUTH_CLIENT_ID", - "STALWART_OAUTH_CLIENT_SECRET", - "STALWART_OAUTH_AUTHORIZATION_ENDPOINT", - "STALWART_OAUTH_TOKEN_ENDPOINT", - "STALWART_OAUTH_USERINFO_ENDPOINT", - "STALWART_OAUTH_SCOPE", - ] - .into_iter() - .filter_map(|key| env::var(key).ok().map(|value| (key.to_string(), value))) - .collect(); - - Stalwart { - env_vars, - process: None, - } - } -} - -impl Service for Stalwart { - fn start(&mut self) -> Result<(), String> { - if self.process.is_some() { - return Err("Stalwart Mail is already running.".to_string()); - } - - let mut command = Command::new("/opt/gbo/bin/stalwart"); - for (key, value) in &self.env_vars { - command.env(key, value); - } - - self.process = Some(command.spawn().map_err(|e| e.to_string())?); - Ok(()) - } - - fn stop(&mut self) -> Result<(), String> { - if let Some(mut child) = self.process.take() { - child.kill().map_err(|e| e.to_string())?; - child.wait().map_err(|e| e.to_string())?; - } - Ok(()) - } -} diff --git a/gb-infra/src/services/zitadel.rs b/gb-infra/src/services/zitadel.rs deleted file mode 100644 index ce5e22b..0000000 --- a/gb-infra/src/services/zitadel.rs +++ /dev/null @@ -1,63 +0,0 @@ -use crate::manager::Service; -use std::env; -use std::process::Command; -use std::collections::HashMap; -use dotenv::dotenv; - -pub struct Zitadel { - env_vars: HashMap, - process: Option, -} - -impl Zitadel { - pub fn new() -> Self { - dotenv().ok(); - let env_vars = vec![ - "ZITADEL_DEFAULTINSTANCE_INSTANCENAME", - "ZITADEL_DEFAULTINSTANCE_ORG_NAME", - "ZITADEL_DATABASE_POSTGRES_HOST", - "ZITADEL_DATABASE_POSTGRES_PORT", - "ZITADEL_DATABASE_POSTGRES_DATABASE", - "ZITADEL_DATABASE_POSTGRES_USER_USERNAME", - "ZITADEL_DATABASE_POSTGRES_USER_PASSWORD", - "ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE", - "ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE", - "ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME", - "ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD", - "ZITADEL_EXTERNALSECURE", - "ZITADEL_MASTERKEY", - ] - .into_iter() - .filter_map(|key| env::var(key).ok().map(|value| (key.to_string(), value))) - .collect(); - - Zitadel { - env_vars, - process: None, - } - } -} - -impl Service for Zitadel { - fn start(&mut self) -> Result<(), String> { - if self.process.is_some() { - return Err("Zitadel is already running.".to_string()); - } - - let mut command = Command::new("/opt/gbo/bin/zitadel"); - for (key, value) in &self.env_vars { - command.env(key, value); - } - - self.process = Some(command.spawn().map_err(|e| e.to_string())?); - Ok(()) - } - - fn stop(&mut self) -> Result<(), String> { - if let Some(mut child) = self.process.take() { - child.kill().map_err(|e| e.to_string())?; - child.wait().map_err(|e| e.to_string())?; - } - Ok(()) - } -} diff --git a/gb-infra/src/setup.rs b/gb-infra/src/setup.rs deleted file mode 100644 index 0413bbc..0000000 --- a/gb-infra/src/setup.rs +++ /dev/null @@ -1,276 +0,0 @@ -use std::{ - fs::{self, File}, - io::{self, Write}, - path::{Path, PathBuf}, - process::Command, - env, -}; - -use reqwest::blocking::Client; -use flate2::read::GzDecoder; -use tar::Archive; -use zip::ZipArchive; - -// TODO: https://helpcenter.onlyoffice.com/docs/installation/docs-community-install-ubuntu.aspx - - -const INSTALL_DIR: &str = "/opt/gbo"; -const TEMP_DIR: &str = "/tmp/gbotemp"; - -#[derive(Debug)] -struct Component { - name: &'static str, - bin_dir: &'static str, - download_url: Option<&'static str>, - archive_type: ArchiveType, - binaries: Vec<&'static str>, - config_files: Vec, -} - -#[derive(Debug)] -struct ConfigFile { - src_url: Option<&'static str>, - src_path: Option<&'static str>, - dest_name: &'static str, -} - -#[derive(Debug)] -enum ArchiveType { - TarGz, - Zip, - Binary, -} - -pub fn doIt() -> io::Result<()> { - // Define all components - let components = [ - // Directory (Zitadel) - Component { - name: "zitadel", - bin_dir: "directory", - download_url: Some("https://github.com/zitadel/zitadel/releases/latest/download/zitadel_Linux_x86_64.tar.gz"), - archive_type: ArchiveType::TarGz, - binaries: vec!["zitadel"], - config_files: vec![ConfigFile { - src_url: None, - src_path: Some("src/config/directory/zitadel.yaml"), - dest_name: "zitadel.yaml", - }], - }, - // Mail (Stalwart) - Component { - name: "stalwart-mail", - bin_dir: "mail", - download_url: Some("https://github.com/stalwartlabs/mail-server/releases/latest/download/stalwart-linux-x86_64.tar.gz"), - archive_type: ArchiveType::TarGz, - binaries: vec!["stalwart-mail"], - config_files: vec![ConfigFile { - src_url: Some("https://raw.githubusercontent.com/stalwartlabs/mail-server/main/resources/config/config.toml"), - src_path: None, - dest_name: "config.toml", - }], - }, - // Tabular (PostgreSQL) - Component { - name: "postgresql", - bin_dir: "tabular", - download_url: Some("https://get.enterprisedb.com/postgresql/postgresql-14.10-1-linux-x64-binaries.tar.gz"), - archive_type: ArchiveType::TarGz, - binaries: vec!["postgres", "pg_ctl", "psql", "pg_dump", "pg_restore"], - config_files: vec![], - }, - // Object (MinIO) - Component { - name: "minio", - bin_dir: "object", - download_url: Some("https://dl.min.io/server/minio/release/linux-amd64/minio"), - archive_type: ArchiveType::Binary, - binaries: vec!["minio"], - config_files: vec![], - }, - // Webserver (Caddy) - Component { - name: "caddy", - bin_dir: "webserver", - download_url: Some("https://github.com/caddyserver/caddy/releases/latest/download/caddy_linux_amd64.tar.gz"), - archive_type: ArchiveType::TarGz, - binaries: vec!["caddy"], - config_files: vec![ConfigFile { - src_url: None, - src_path: Some("src/config/webserver/Caddyfile"), - dest_name: "Caddyfile", - }], - }, - ]; - - // Create directories - create_directories()?; - - // Install dependencies - install_dependencies()?; - - // Create HTTP client - let client = Client::new(); - - // Process all components - for component in components.iter() { - install_component(&component, &client)?; - } - - // Clean up temp directory - fs::remove_dir_all(TEMP_DIR)?; - - println!("All binaries downloaded to {}", INSTALL_DIR); - println!("Use the start-stop script to manually control all components"); - - Ok(()) -} - -fn create_directories() -> io::Result<()> { - println!("Creating directories..."); - - // Main directories - fs::create_dir_all(INSTALL_DIR)?; - Command::new("chmod").args(["777", INSTALL_DIR]).status()?; - fs::create_dir_all(TEMP_DIR)?; - - // Component directories - let dirs = [ - "bin/bot", "bin/mail", "bin/tabular", "bin/object", - "bin/directory", "bin/alm", "bin/webserver", "bin/meeting", - "config/bot", "config/mail", "config/tabular", "config/object", - "config/directory", "config/alm", "config/webserver", "config/meeting", - "data/bot", "data/mail", "data/tabular", "data/object", - "data/directory", "data/alm", "data/webserver", "data/meeting", - "logs", "certs" - ]; - - for dir in dirs { - fs::create_dir_all(format!("{}/{}", INSTALL_DIR, dir))?; - } - - Ok(()) -} - -fn install_dependencies() -> io::Result<()> { - println!("Installing system dependencies..."); - Command::new("apt-get").args(["update"]).status()?; - Command::new("apt-get").args(["install", "-y", - "apt-transport-https", "ca-certificates", "curl", - "software-properties-common", "gnupg", "wget", - "unzip", "tar", "postgresql-client", "redis-tools" - ]).status()?; - Ok(()) -} - -fn install_component(component: &Component, client: &Client) -> io::Result<()> { - println!("Installing {}...", component.name); - - if let Some(url) = component.download_url { - let temp_path = format!("{}/{}", TEMP_DIR, component.name); - let target_dir = format!("{}/bin/{}", INSTALL_DIR, component.bin_dir); - - // Download the file - download_file(client, url, &temp_path)?; - - match component.archive_type { - ArchiveType::TarGz => { - // Extract tar.gz archive - let tar_gz = File::open(&temp_path)?; - let tar = GzDecoder::new(tar_gz); - let mut archive = Archive::new(tar); - archive.unpack(TEMP_DIR)?; - - // Move binaries to target directory - for binary in &component.binaries { - let src = format!("{}/{}", TEMP_DIR, binary); - let dest = format!("{}/{}", target_dir, binary); - - if Path::new(&src).exists() { - fs::rename(&src, &dest)?; - set_executable(&dest)?; - } else { - // For PostgreSQL which has binaries in pgsql/bin/ - let pg_src = format!("{}/pgsql/bin/{}", TEMP_DIR, binary); - if Path::new(&pg_src).exists() { - fs::rename(&pg_src, &dest)?; - set_executable(&dest)?; - } - } - } - }, - ArchiveType::Zip => { - // Extract zip archive - let file = File::open(&temp_path)?; - let mut archive = ZipArchive::new(file)?; - archive.extract(TEMP_DIR)?; - - // Move binaries to target directory - for binary in &component.binaries { - let src = format!("{}/{}", TEMP_DIR, binary); - let dest = format!("{}/{}", target_dir, binary); - - if Path::new(&src).exists() { - fs::rename(&src, &dest)?; - set_executable(&dest)?; - } - } - }, - ArchiveType::Binary => { - // Single binary - just move to target location - let dest = format!("{}/{}", target_dir, component.name); - fs::rename(&temp_path, &dest)?; - set_executable(&dest)?; - }, - } - - // Clean up downloaded file - fs::remove_file(temp_path)?; - } - - // Handle config files - for config in &component.config_files { - let config_dir = format!("{}/config/{}", INSTALL_DIR, component.bin_dir); - let dest_path = format!("{}/{}", config_dir, config.dest_name); - - if let Some(url) = config.src_url { - // Download config from URL - download_file(client, url, &dest_path)?; - } else if let Some(src_path) = config.src_path { - // Copy config from local source (placeholder) - println!("Would copy config from {} to {}", src_path, dest_path); - // fs::copy(src_path, dest_path)?; - } - } - - println!("{} installed successfully!", component.name); - Ok(()) -} - -fn download_file(client: &Client, url: &str, dest_path: &str) -> io::Result<()> { - println!("Downloading {} to {}", url, dest_path); - - let mut response = client.get(url) - .send() - .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; - - if !response.status().is_success() { - return Err(io::Error::new( - io::ErrorKind::Other, - format!("Failed to download file: HTTP {}", response.status()) - )); - } - - let mut dest_file = File::create(dest_path)?; - response.copy_to(&mut dest_file) - .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; - - Ok(()) -} - -fn set_executable(path: &str) -> io::Result<()> { - Command::new("chmod") - .args(["+x", path]) - .status()?; - Ok(()) -} \ No newline at end of file diff --git a/gb-infra/src/templates/opt/gbo/tenants/default/shared/scripts/check-space.sh b/gb-infra/src/templates/opt/gbo/tenants/default/shared/scripts/check-space.sh deleted file mode 100644 index 173252b..0000000 --- a/gb-infra/src/templates/opt/gbo/tenants/default/shared/scripts/check-space.sh +++ /dev/null @@ -1,5 +0,0 @@ -printf "%-20s %-10s %-10s %-10s %-6s %s\n" "CONTAINER" "USED" "AVAIL" "TOTAL" "USE%" "MOUNT" -for container in $(lxc list -c n --format csv); do - disk_info=$(lxc exec $container -- df -h / --output=used,avail,size,pcent | tail -n 1) - printf "%-20s %s\n" "$container" "$disk_info" -done \ No newline at end of file diff --git a/gb-llm/Cargo.toml b/gb-llm/Cargo.toml deleted file mode 100644 index a5018be..0000000 --- a/gb-llm/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "gb-llm" -version = { workspace = true } -edition = { workspace = true } -authors = { workspace = true } -license = { workspace = true } - -[dependencies] -gb-core = { path = "../gb-core" } -async-trait= { workspace = true } -tokio= { workspace = true } -thiserror= { workspace = true } -tracing= { workspace = true } - -[dev-dependencies] -rstest= { workspace = true } diff --git a/gb-llm/src/lib.rs b/gb-llm/src/lib.rs deleted file mode 100644 index e69de29..0000000 diff --git a/gb-media/Cargo.toml b/gb-media/Cargo.toml deleted file mode 100644 index 4656a5d..0000000 --- a/gb-media/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "gb-media" -version = { workspace = true } -edition = { workspace = true } -authors = { workspace = true } -license = { workspace = true } - -[dependencies] -gb-core = { path = "../gb-core" } -tokio= { workspace = true } -webrtc= { workspace = true } -gstreamer= { workspace = true } -opus= { workspace = true } -tracing= { workspace = true } -async-trait= { workspace = true } -serde= { workspace = true } -uuid= { workspace = true } -anyhow= { workspace = true } - -[dev-dependencies] -rstest= { workspace = true } -mockall= { workspace = true } -tokio-test = "0.4" diff --git a/gb-media/src/audio.rs b/gb-media/src/audio.rs deleted file mode 100644 index 356fcf2..0000000 --- a/gb-media/src/audio.rs +++ /dev/null @@ -1,56 +0,0 @@ -use gb_core::{Result, Error}; -use opus::{Encoder, Decoder, Application, Channels}; - -pub struct AudioProcessor { - encoder: Encoder, - decoder: Decoder, - sample_rate: u32, - channels: Channels, -} - -impl AudioProcessor { - pub fn new(sample_rate: u32, channels: Channels) -> Result { - let encoder = Encoder::new( - sample_rate, - channels, - Application::Audio - ).map_err(|e| Error::internal(format!("Failed to create Opus encoder: {}", e)))?; - - let decoder = Decoder::new( - sample_rate, - channels - ).map_err(|e| Error::internal(format!("Failed to create Opus decoder: {}", e)))?; - - Ok(Self { - encoder, - decoder, - sample_rate, - channels, - }) - } - - pub fn encode(&self, input: &[i16]) -> Result> { - let mut output = vec![0u8; 1024]; - let encoded_size = self.encoder.encode( - input, - &mut output - ).map_err(|e| Error::internal(format!("Failed to encode audio: {}", e)))?; - - output.truncate(encoded_size); - Ok(output) - } - - pub fn decode(&self, input: &[u8]) -> Result> { - let max_size = (self.sample_rate as usize / 50) * self.channels.count(); - let mut output = vec![0i16; max_size]; - - let decoded_size = self.decoder.decode( - Some(input), - &mut output, - false - ).map_err(|e| Error::internal(format!("Failed to decode audio: {}", e)))?; - - output.truncate(decoded_size); - Ok(output) - } -} \ No newline at end of file diff --git a/gb-media/src/lib.rs b/gb-media/src/lib.rs deleted file mode 100644 index 61da984..0000000 --- a/gb-media/src/lib.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod processor; -mod webrtc; - -pub use processor::MediaProcessor; -pub use webrtc::WebRTCService; \ No newline at end of file diff --git a/gb-media/src/processor.rs b/gb-media/src/processor.rs deleted file mode 100644 index c9b2154..0000000 --- a/gb-media/src/processor.rs +++ /dev/null @@ -1,82 +0,0 @@ -use gb_core::{Result, Error}; -use gstreamer as gst; -use gstreamer::prelude::*; -use std::path::PathBuf; -use tracing::{error, instrument}; - -pub struct MediaProcessor { - pipeline: gst::Pipeline, -} - -impl MediaProcessor { - pub fn new() -> Result { - gst::init().map_err(|e| Error::internal(format!("Failed to initialize GStreamer: {}", e)))?; - - let pipeline = gst::Pipeline::new(); - Ok(Self { pipeline }) - } - - fn setup_pipeline(&mut self) -> Result<()> { - self.pipeline.set_state(gst::State::Playing) - .map_err(|e| Error::internal(format!("Failed to start pipeline: {}", e)))?; - - Ok(()) - } - - fn process_messages(&self) -> Result<()> { - let bus = self.pipeline.bus().unwrap(); - - while let Some(msg) = bus.timed_pop(gst::ClockTime::from_seconds(1)) { - match msg.view() { - gst::MessageView::Error(err) => { - error!("Error from {:?}: {} ({:?})", - err.src().map(|s| s.path_string()), - err.error(), - err.debug() - ); - return Err(Error::internal(format!("Pipeline error: {}", err.error()))); - } - gst::MessageView::Eos(_) => break, - _ => () - } - } - - self.pipeline.set_state(gst::State::Null) - .map_err(|e| Error::internal(format!("Failed to stop pipeline: {}", e)))?; - - Ok(()) - } - - #[instrument(skip(self, input_path, output_path))] - pub async fn transcode( - &mut self, - input_path: PathBuf, - output_path: PathBuf, - format: &str - ) -> Result<()> { - let source = gst::ElementFactory::make("filesrc") - .build() - .map_err(|e| Error::internal(format!("Failed to create source element: {}", e)))?; - source.set_property("location", input_path.to_str().unwrap()); - - let sink = gst::ElementFactory::make("filesink") - .build() - .map_err(|e| Error::internal(format!("Failed to create sink element: {}", e)))?; - sink.set_property("location", output_path.to_str().unwrap()); - - let decoder = match format.to_lowercase().as_str() { - "mp4" => gst::ElementFactory::make("qtdemux").build(), - "webm" => gst::ElementFactory::make("matroskademux").build(), - _ => return Err(Error::internal(format!("Unsupported format: {}", format))) - }.map_err(|e| Error::internal(format!("Failed to create decoder: {}", e)))?; - - self.pipeline.add_many(&[&source, &decoder, &sink]) - .map_err(|e| Error::internal(format!("Failed to add elements: {}", e)))?; - - gst::Element::link_many(&[&source, &decoder, &sink]) - .map_err(|e| Error::internal(format!("Failed to link elements: {}", e)))?; - - self.setup_pipeline()?; - self.process_messages() - } -} \ No newline at end of file diff --git a/gb-media/src/webrtc.rs b/gb-media/src/webrtc.rs deleted file mode 100644 index 0dc8bc3..0000000 --- a/gb-media/src/webrtc.rs +++ /dev/null @@ -1,85 +0,0 @@ -use gb_core::{Result, Error}; -use webrtc::{ - api::{API, APIBuilder}, - peer_connection::{ - RTCPeerConnection, - configuration::RTCConfiguration, - }, - track::{ - track_local::TrackLocal, - track_remote::TrackRemote, - }, -}; -use tokio::sync::mpsc; -use tracing::instrument; -use std::sync::Arc; - -pub struct WebRTCService { - api: Arc, - peer_connections: Vec>, -} - -impl WebRTCService { - pub fn new() -> Result { - let api = APIBuilder::new().build(); - - Ok(Self { - api: Arc::new(api), - peer_connections: Vec::new(), - }) - } - - pub async fn create_peer_connection(&mut self) -> Result> { - let config = RTCConfiguration::default(); - - let peer_connection = self.api.new_peer_connection(config) - .await - .map_err(|e| Error::internal(format!("Failed to create peer connection: {}", e)))?; - - let pc_arc = Arc::new(peer_connection); - self.peer_connections.push(pc_arc.clone()); - - Ok(pc_arc) - } - - pub async fn add_track( - &self, - pc: &RTCPeerConnection, - track: Arc, - ) -> Result<()> { - pc.add_track(track) - .await - .map_err(|e| Error::internal(format!("Failed to add track: {}", e)))?; - - Ok(()) - } - - pub async fn on_track(&self, pc: &RTCPeerConnection, mut callback: F) - where - F: FnMut(Arc) + Send + 'static, - { - let (tx, mut rx) = mpsc::channel(100); - - pc.on_track(Box::new(move |track, _, _| { - let track_clone = track.clone(); - let tx = tx.clone(); - Box::pin(async move { - let _ = tx.send(track_clone).await; - }) - })); - - while let Some(track) = rx.recv().await { - callback(track); - } - } - - #[instrument(skip(self))] - pub async fn close(&mut self) -> Result<()> { - for pc in self.peer_connections.iter() { - pc.close().await - .map_err(|e| Error::internal(format!("Failed to close peer connection: {}", e)))?; - } - self.peer_connections.clear(); - Ok(()) - } -} \ No newline at end of file diff --git a/gb-messaging/Cargo.toml b/gb-messaging/Cargo.toml deleted file mode 100644 index 9581c24..0000000 --- a/gb-messaging/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "gb-messaging" -version = { workspace = true } -edition = { workspace = true } -authors = { workspace = true } -license = { workspace = true } - -[dependencies] -gb-core = { path = "../gb-core" } -tokio= { workspace = true } -rdkafka= { workspace = true } -redis= { workspace = true } -serde= { workspace = true } -serde_json= { workspace = true } -uuid= { workspace = true } -async-trait= { workspace = true } -tracing= { workspace = true } -futures= { workspace = true } -futures-util = "0.3" -chrono = { version = "0.4", features = ["serde"] } -lapin = "2.3" -tokio-tungstenite = { workspace= true, features = ["native-tls"] } - -[dev-dependencies] -rstest= { workspace = true } -tokio-test = "0.4" diff --git a/gb-messaging/src/broker.rs b/gb-messaging/src/broker.rs deleted file mode 100644 index 5caccaf..0000000 --- a/gb-messaging/src/broker.rs +++ /dev/null @@ -1,53 +0,0 @@ -use gb_core::Error; -use rdkafka::producer::{FutureProducer, FutureRecord}; -use rdkafka::config::ClientConfig; -use std::time::Duration; -use serde::Serialize; - -#[allow(dead_code)] -pub struct KafkaBroker { - producer: FutureProducer, - // Stored for reconnection logic - broker_address: String, - // Stored for consumer group management - group_id: String, -} - -impl KafkaBroker { - pub fn new(broker_address: &str, group_id: &str) -> Self { - let producer: FutureProducer = ClientConfig::new() - .set("bootstrap.servers", broker_address) - .set("message.timeout.ms", "5000") - .create() - .expect("Producer creation failed"); - - Self { - producer, - broker_address: broker_address.to_string(), - group_id: group_id.to_string(), - } - } - - pub async fn publish( - &self, - topic: &str, - key: &str, - message: &T, - ) -> Result<(), Error> { - let payload = serde_json::to_string(message) - .map_err(|e| Error::internal(format!("Serialization failed: {}", e)))?; - - self.producer - .send( - FutureRecord::to(topic) - .key(key) - .payload(&payload), - Duration::from_secs(5), - ) - .await - .map_err(|(e, _)| Error::internal(format!("Failed to publish message: {}", e)))?; - - Ok(()) - } - -} \ No newline at end of file diff --git a/gb-messaging/src/kafka.rs b/gb-messaging/src/kafka.rs deleted file mode 100644 index 0edee0f..0000000 --- a/gb-messaging/src/kafka.rs +++ /dev/null @@ -1,112 +0,0 @@ -use gb_core::{Result, Error}; -use rdkafka::producer::{FutureProducer, FutureRecord}; -use rdkafka::consumer::{StreamConsumer, Consumer}; -use rdkafka::ClientConfig; -use std::time::Duration; -use serde::Serialize; - -#[allow(dead_code)] -pub struct Kafka { - broker_address: String, - group_id: String, - - producer: FutureProducer, - consumer: StreamConsumer, -} - -impl Kafka { - pub async fn new(broker_address: &str, group_id: &str) -> Result { - let producer = ClientConfig::new() - .set("bootstrap.servers", broker_address) - .create() - .map_err(|e| Error::kafka(format!("Failed to create producer: {}", e)))?; - - - let consumer = ClientConfig::new() - .set("bootstrap.servers", broker_address) - .set("group.id", group_id) - .create() - .map_err(|e| Error::kafka(format!("Failed to create consumer: {}", e)))?; - - Ok(Self { - broker_address: broker_address.to_string(), - group_id: group_id.to_string(), - producer, - consumer, - }) - } - - pub async fn publish(&self, topic: &str, message: &T) -> Result<()> { - let payload = serde_json::to_string(message) - .map_err(|e| Error::internal(format!("Serialization error: {}", e)))?; - - self.producer - .send( - FutureRecord::to(topic) - .payload(payload.as_bytes()) - .key(""), - Duration::from_secs(0), - ) - .await - .map_err(|(e, _)| Error::kafka(format!("Failed to send message: {}", e)))?; - - Ok(()) - } - - pub async fn subscribe(&self, topic: &str) -> Result<()> { - self.consumer - .subscribe(&[topic]) - .map_err(|e| Error::kafka(format!("Failed to subscribe: {}", e)))?; - - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use rstest::*; - use tokio; - use serde::{Deserialize, Serialize}; - use uuid::Uuid; - - #[derive(Debug, Serialize, Deserialize, PartialEq)] - struct TestMessage { - id: Uuid, - content: String, - } - - #[fixture] - fn test_message() -> TestMessage { - TestMessage { - id: Uuid::new_v4(), - content: "test message".to_string(), - } - } - - #[fixture] - async fn kafka() -> Kafka { - Kafka::new( - "localhost:9092", - "test-group", - ).await.unwrap() - } - - #[rstest] - #[tokio::test] - async fn test_publish_subscribe( - #[future] kafka: Kafka, - test_message: TestMessage - ) { - let topic = "test-topic"; - let kafka = kafka.await; - kafka.publish(topic, &test_message) - .await - .unwrap(); - - kafka.subscribe(topic) - .await - .unwrap(); - tokio::time::sleep(Duration::from_secs(1)).await; - } -} diff --git a/gb-messaging/src/lib.rs b/gb-messaging/src/lib.rs deleted file mode 100644 index 1d7b57c..0000000 --- a/gb-messaging/src/lib.rs +++ /dev/null @@ -1,88 +0,0 @@ -mod kafka; -mod redis_pubsub; -mod websocket; -mod processor; -pub mod models; - -pub use kafka::Kafka; -pub use redis_pubsub::RedisPubSub; -pub use websocket::WebSocketClient; -pub use processor::MessageProcessor; -pub use models::MessageEnvelope; -mod broker; -pub use broker::KafkaBroker; - -#[cfg(test)] -mod tests { - use super::*; - use gb_core::models::Message; - use serde::{Deserialize, Serialize}; - use uuid::Uuid; - use std::sync::Arc; - use redis::Client; - - #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] - struct TestMessage { - id: Uuid, - content: String, - } - - #[tokio::test] - async fn test_messaging_integration() { - let kafka = KafkaBroker::new( - "localhost:9092", - "test-group", - ); - let redis_client = Client::open("redis://localhost") - .expect("Failed to create Redis client"); - let redis = RedisPubSub::new(Arc::new(redis_client)); - let mut websocket = WebSocketClient::connect("ws://localhost:8080") - .await - .unwrap(); - - let test_message = TestMessage { - id: Uuid::new_v4(), - content: "integration test".to_string(), - }; - - kafka.publish("test-topic", &test_message.id.to_string(), &test_message) - .await - .unwrap(); - - redis.publish("test-channel", &test_message) - .await - .unwrap(); - - websocket.send_message(&serde_json::to_string(&test_message).unwrap()) - .await - .unwrap(); - - let mut processor = MessageProcessor::new(); - - processor.register_handler("test", |envelope| { - println!("Processed message: {}", envelope.message.content); - Ok(()) - }); - - let message = Message { - id: Uuid::new_v4(), - customer_id: Uuid::new_v4(), - instance_id: Uuid::new_v4(), - conversation_id: Uuid::new_v4(), - sender_id: Uuid::new_v4(), - kind: "test".to_string(), - content: "test content".to_string(), - metadata: serde_json::Value::Object(serde_json::Map::new()), - created_at: Some(chrono::Utc::now()), - shard_key: Some(0), - }; - - let envelope = MessageEnvelope { - id: Uuid::new_v4(), - message, - metadata: std::collections::HashMap::new(), - }; - - processor.sender().send(envelope).unwrap(); - } -} diff --git a/gb-messaging/src/models.rs b/gb-messaging/src/models.rs deleted file mode 100644 index de4e7bf..0000000 --- a/gb-messaging/src/models.rs +++ /dev/null @@ -1,11 +0,0 @@ -use gb_core::models::Message; -use serde::{Deserialize, Serialize}; -use std::collections::HashMap; -use uuid::Uuid; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct MessageEnvelope { - pub id: Uuid, - pub message: Message, - pub metadata: HashMap, -} diff --git a/gb-messaging/src/processor.rs b/gb-messaging/src/processor.rs deleted file mode 100644 index 2e887cb..0000000 --- a/gb-messaging/src/processor.rs +++ /dev/null @@ -1,150 +0,0 @@ -use gb_core::{Result, models::*}; // This will import both Message and MessageId - -use gb_core::Error; -use uuid::Uuid; -use std::collections::HashMap; -use tracing::instrument; -use crate::MessageEnvelope; -use tokio::sync::broadcast; // Add this import -use std::sync::Arc; -use tracing::{error}; // Add error and info macros here - - -pub struct MessageProcessor { - tx: broadcast::Sender, - rx: broadcast::Receiver, - handlers: Arc Result<()> + Send + Sync>>>, -} - -impl Clone for MessageProcessor { - fn clone(&self) -> Self { - MessageProcessor { - tx: self.tx.clone(), - rx: self.tx.subscribe(), - handlers: Arc::clone(&self.handlers), - } - } -} - -impl MessageProcessor { - pub fn new() -> Self { - Self::new_with_buffer_size(100) - } - - pub fn new_with_buffer_size(buffer_size: usize) -> Self { - let (tx, rx) = broadcast::channel(buffer_size); - Self { - tx, - rx, - handlers: Arc::new(HashMap::new()), - } - } - - pub fn sender(&self) -> broadcast::Sender { - self.tx.clone() - } - - #[instrument(skip(self, handler))] - pub fn register_handler(&mut self, kind: &str, handler: F) - where - F: Fn(MessageEnvelope) -> Result<()> + Send + Sync + 'static, - { - Arc::get_mut(&mut self.handlers) - .expect("Cannot modify handlers") - .insert(kind.to_string(), Box::new(handler)); - } - - #[instrument(skip(self))] - pub async fn add_message(&mut self, message: Message) -> Result { - let envelope = MessageEnvelope { - id: Uuid::new_v4(), - message, - metadata: HashMap::new(), - }; - - self.tx.send(envelope.clone()) - .map_err(|e| Error::internal(format!("Failed to queue message: {}", e)))?; - - // Start processing immediately - if let Some(handler) = self.handlers.get(&envelope.message.kind) { - handler(envelope.clone()) - .map_err(|e| Error::internal(format!("Handler error: {}", e)))?; - } - - Ok(MessageId(envelope.id)) - } - #[instrument(skip(self))] - pub async fn process_messages(&mut self) -> Result<()> { - while let Ok(envelope) = self.rx.recv().await { - if let Some(handler) = self.handlers.get(&envelope.message.kind) { - if let Err(e) = handler(envelope.clone()) { - error!("Handler error for message {}: {}", envelope.id, e); - } - tracing::info!("Processing message: {:?}", &envelope.message.id); - } else { - error!("No handler registered for message kind: {}", envelope.message.kind); - } - } - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use gb_core::models::Message; - use rstest::*; - use uuid::Uuid; - use std::{sync::Arc, time::Duration}; - use tokio::sync::Mutex; - - #[fixture] - fn test_message() -> Message { - Message { - id: Uuid::new_v4(), - customer_id: Uuid::new_v4(), - instance_id: Uuid::new_v4(), - conversation_id: Uuid::new_v4(), - sender_id: Uuid::new_v4(), - kind: "test".to_string(), - content: "test content".to_string(), - metadata: serde_json::Value::Object(serde_json::Map::new()), - created_at: Some(chrono::Utc::now()), - shard_key: Some(0), - } - } - - #[rstest] - #[tokio::test] - async fn test_message_processor(test_message: Message) { - let mut processor = MessageProcessor::new(); - let processed = Arc::new(Mutex::new(false)); - let processed_clone = processed.clone(); - - processor.register_handler("test", move |envelope| { - assert_eq!(envelope.message.content, "test content"); - let mut processed = processed_clone.blocking_lock(); - *processed = true; - Ok(()) - }); - - let mut processor_clone = processor.clone(); - let handle = tokio::spawn(async move { - processor_clone.process_messages().await.unwrap(); - }); - - let envelope = MessageEnvelope { - id: Uuid::new_v4(), - message: test_message, - metadata: HashMap::new(), - }; - - processor.sender().send(envelope).unwrap(); - - tokio::time::sleep(Duration::from_secs(1)).await; - - assert!(*processed.lock().await); - - handle.abort(); - } -} diff --git a/gb-messaging/src/redis_pubsub.rs b/gb-messaging/src/redis_pubsub.rs deleted file mode 100644 index 444d689..0000000 --- a/gb-messaging/src/redis_pubsub.rs +++ /dev/null @@ -1,123 +0,0 @@ -use gb_core::{Result, Error}; -use redis::{Client, AsyncCommands}; -use serde::Serialize; -use std::sync::Arc; -use tracing::instrument; -use futures_util::StreamExt; - -#[derive(Clone)] -pub struct RedisPubSub { - client: Arc, -} - -impl RedisPubSub { - pub fn new(client: Arc) -> Self { - Self { client } - } - - #[instrument(skip(self, payload), err)] - pub async fn publish(&self, channel: &str, payload: &T) -> Result<()> { - let mut conn = self.client - .get_async_connection() - .await - .map_err(|e| Error::internal(e.to_string()))?; - - let serialized = serde_json::to_string(payload) - .map_err(|e| Error::internal(e.to_string()))?; - - conn.publish::<_, _, i32>(channel, serialized) - .await - .map_err(|e| Error::internal(e.to_string()))?; - - Ok(()) - } - - #[instrument(skip(self, handler), err)] - pub async fn subscribe(&self, channels: &[&str], mut handler: F) -> Result<()> - where - F: FnMut(String, String) + Send + 'static, - { - let mut pubsub = self.client - .get_async_connection() - .await - .map_err(|e| Error::internal(e.to_string()))? - .into_pubsub(); - - for channel in channels { - pubsub.subscribe(*channel) - .await - .map_err(|e| Error::internal(e.to_string()))?; - } - - let mut stream = pubsub.on_message(); - - while let Some(msg) = stream.next().await { - let channel = msg.get_channel_name().to_string(); - let payload: String = msg.get_payload() - .map_err(|e| Error::internal(e.to_string()))?; - - handler(channel, payload); - } - - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use redis::Client; - use serde::{Deserialize, Serialize}; - use uuid::Uuid; - use tokio::sync::mpsc; - use std::time::Duration; - - #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] - struct TestMessage { - id: Uuid, - content: String, - } - - async fn setup() -> (RedisPubSub, TestMessage) { - let client = Arc::new(Client::open("redis://127.0.0.1/").unwrap()); - let redis_pubsub = RedisPubSub::new(client); - - let test_message = TestMessage { - id: Uuid::new_v4(), - content: "test message".to_string(), - }; - - (redis_pubsub, test_message) - } - - #[tokio::test] - async fn test_publish_subscribe() { - let (redis_pubsub, test_message) = setup().await; - let channel = "test_channel"; - let (tx, mut rx) = mpsc::channel(1); - - let pubsub_clone = redis_pubsub.clone(); - - - tokio::spawn(async move { - let handler = move |_channel: String, payload: String| { - let received: TestMessage = serde_json::from_str(&payload).unwrap(); - tx.try_send(received).unwrap(); - }; - - pubsub_clone.subscribe(&[channel], handler).await.unwrap(); - }); - - // Give the subscriber time to connect - tokio::time::sleep(Duration::from_millis(100)).await; - - redis_pubsub.publish(channel, &test_message).await.unwrap(); - - let received = tokio::time::timeout(Duration::from_secs(1), rx.recv()) - .await - .unwrap() - .unwrap(); - - assert_eq!(received, test_message); - } -} diff --git a/gb-messaging/src/websocket.rs b/gb-messaging/src/websocket.rs deleted file mode 100644 index a2fabfb..0000000 --- a/gb-messaging/src/websocket.rs +++ /dev/null @@ -1,88 +0,0 @@ -use futures_util::SinkExt; -use tokio_tungstenite::{connect_async, tungstenite::Message}; -use gb_core::{Result, Error}; - -pub struct WebSocketClient { - stream: tokio_tungstenite::WebSocketStream< - tokio_tungstenite::MaybeTlsStream - >, -} - -impl WebSocketClient { - fn to_gb_error(error: tokio_tungstenite::tungstenite::Error) -> Error { - Error::new( - gb_core::ErrorKind::WebSocket(error.to_string()), - error.to_string() - ) - } - - pub async fn connect(url: &str) -> Result { - let (ws_stream, _) = connect_async(url).await.map_err(Self::to_gb_error)?; - Ok(Self { - stream: ws_stream, - }) - } - - pub async fn send_message(&mut self, payload: &str) -> Result<()> { - self.stream - .send(Message::Text(payload.to_string())) - .await - .map_err(Self::to_gb_error)?; - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use futures::StreamExt; - use rstest::*; - use serde::{Deserialize, Serialize}; - - use std::time::Duration; - use tokio::net::TcpListener; - use uuid::Uuid; - - #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] - struct TestMessage { - id: Uuid, - content: String, - } - - async fn create_test_server() -> String { - let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); - let addr = listener.local_addr().unwrap(); - - tokio::spawn(async move { - while let Ok((stream, _)) = listener.accept().await { - let ws_stream = tokio_tungstenite::accept_async(stream).await.unwrap(); - let (mut write, mut read) = ws_stream.split(); - - while let Some(Ok(msg)) = read.next().await { - if let Message::Text(_) = msg { - write.send(msg).await.unwrap(); - } - } - } - }); - - format!("ws://{}", addr) - } - - #[fixture] - fn test_message() -> TestMessage { - TestMessage { - id: Uuid::new_v4(), - content: "test message".to_string(), - } - } - - #[rstest] - #[tokio::test] - async fn test_websocket(test_message: TestMessage) { - let server_url = create_test_server().await; - let mut client = WebSocketClient::connect(&server_url).await.unwrap(); - tokio::time::sleep(Duration::from_millis(100)).await; - client.send_message(&serde_json::to_string(&test_message).unwrap()).await.unwrap(); - } -} diff --git a/gb-migrations/20231220000000_update_user_schema.sql b/gb-migrations/20231220000000_update_user_schema.sql deleted file mode 100644 index 58d1956..0000000 --- a/gb-migrations/20231220000000_update_user_schema.sql +++ /dev/null @@ -1,37 +0,0 @@ --- Create users table -CREATE TABLE IF NOT EXISTS users ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - email VARCHAR(255) NOT NULL UNIQUE, - name VARCHAR(255), - password_hash VARCHAR(255) NOT NULL, - role VARCHAR(50) NOT NULL DEFAULT 'user', - status VARCHAR(50) NOT NULL DEFAULT 'active', - created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP -); - --- Create sessions table -CREATE TABLE IF NOT EXISTS sessions ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, - refresh_token VARCHAR(255) NOT NULL UNIQUE, - expires_at TIMESTAMP WITH TIME ZONE NOT NULL, - created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP -); - --- Create indexes -CREATE INDEX IF NOT EXISTS idx_users_email ON users(email); -CREATE INDEX IF NOT EXISTS idx_sessions_user_id ON sessions(user_id); -CREATE INDEX IF NOT EXISTS idx_sessions_refresh_token ON sessions(refresh_token); - - --- Add password_hash column to users table -ALTER TABLE users -ADD COLUMN IF NOT EXISTS password_hash VARCHAR(255) NOT NULL DEFAULT ''; - --- Update column names if needed -ALTER TABLE users RENAME COLUMN password TO password_hash; - --- Add metadata column to instances table -ALTER TABLE instances -ADD COLUMN IF NOT EXISTS metadata JSONB NOT NULL DEFAULT '{}'; \ No newline at end of file diff --git a/gb-migrations/Cargo.toml b/gb-migrations/Cargo.toml deleted file mode 100644 index dc6aaea..0000000 --- a/gb-migrations/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "gb-migrations" -version = { workspace = true } -edition = { workspace = true } -authors = { workspace = true } -license = { workspace = true } - -[[bin]] -name = "migrations" -path = "src/bin/migrations.rs" - -[dependencies] -tokio= { workspace = true } -sqlx= { workspace = true } -tracing= { workspace = true } -uuid= { workspace = true } -chrono= { workspace = true } -serde_json= { workspace = true } -gb-core = { path = "../gb-core" } - -[dev-dependencies] -rstest= { workspace = true } \ No newline at end of file diff --git a/gb-migrations/src/bin/migrations.rs b/gb-migrations/src/bin/migrations.rs deleted file mode 100644 index 237bf81..0000000 --- a/gb-migrations/src/bin/migrations.rs +++ /dev/null @@ -1,19 +0,0 @@ -use sqlx::PgPool; -use gb_migrations::run_migrations; - -#[tokio::main] -async fn main() -> Result<(), sqlx::Error> { - let database_url = std::env::var("DATABASE_URL") - .expect("DATABASE_URL must be set"); - - println!("Creating database connection pool..."); - let pool = PgPool::connect(&database_url) - .await - .expect("Failed to create pool"); - - println!("Running migrations..."); - run_migrations(&pool).await?; - - println!("Migrations completed successfully!"); - Ok(()) -} \ No newline at end of file diff --git a/gb-migrations/src/lib.rs b/gb-migrations/src/lib.rs deleted file mode 100644 index 59a8faa..0000000 --- a/gb-migrations/src/lib.rs +++ /dev/null @@ -1,144 +0,0 @@ -use sqlx::PgPool; -use tracing::info; - -pub async fn run_migrations(pool: &PgPool) -> Result<(), sqlx::Error> { - info!("Running database migrations"); - - // Create tables - let table_queries = [ - // Customers table - r#"CREATE TABLE IF NOT EXISTS customers ( - id UUID PRIMARY KEY, - name VARCHAR(255) NOT NULL, - subscription_tier VARCHAR(50) NOT NULL, - status VARCHAR(50) NOT NULL, - max_instances INTEGER NOT NULL, - metadata JSONB NOT NULL DEFAULT '{}', - created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP - )"#, - - // Instances table - r#"CREATE TABLE IF NOT EXISTS instances ( - id UUID PRIMARY KEY, - customer_id UUID NOT NULL REFERENCES customers(id), - name VARCHAR(255) NOT NULL, - status VARCHAR(50) NOT NULL, - shard_id INTEGER NOT NULL, - region VARCHAR(50) NOT NULL, - config JSONB NOT NULL DEFAULT '{}', - created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP - )"#, - - // Rooms table - r#"CREATE TABLE IF NOT EXISTS rooms ( - id UUID PRIMARY KEY, - customer_id UUID NOT NULL REFERENCES customers(id), - instance_id UUID NOT NULL REFERENCES instances(id), - name VARCHAR(255) NOT NULL, - kind VARCHAR(50) NOT NULL, - status VARCHAR(50) NOT NULL, - config JSONB NOT NULL DEFAULT '{}', - created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP - )"#, - - // Messages table - r#"CREATE TABLE IF NOT EXISTS messages ( - id UUID PRIMARY KEY, - customer_id UUID NOT NULL REFERENCES customers(id), - instance_id UUID NOT NULL REFERENCES instances(id), - conversation_id UUID NOT NULL, - sender_id UUID NOT NULL, - kind VARCHAR(50) NOT NULL, - content TEXT NOT NULL, - metadata JSONB NOT NULL DEFAULT '{}', - created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, - shard_key INTEGER NOT NULL - )"#, - - // Users table - r#"CREATE TABLE IF NOT EXISTS users ( - id UUID PRIMARY KEY, - customer_id UUID NOT NULL REFERENCES customers(id), - instance_id UUID NOT NULL REFERENCES instances(id), - name VARCHAR(255) NOT NULL, - email VARCHAR(255) NOT NULL UNIQUE, - status VARCHAR(50) NOT NULL, - metadata JSONB NOT NULL DEFAULT '{}', - created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP - )"#, - - // Tracks table - r#"CREATE TABLE IF NOT EXISTS tracks ( - id UUID PRIMARY KEY, - room_id UUID NOT NULL REFERENCES rooms(id), - user_id UUID NOT NULL REFERENCES users(id), - kind VARCHAR(50) NOT NULL, - status VARCHAR(50) NOT NULL, - metadata JSONB NOT NULL DEFAULT '{}', - created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP - )"#, - - // Subscriptions table - r#"CREATE TABLE IF NOT EXISTS subscriptions ( - id UUID PRIMARY KEY, - track_id UUID NOT NULL REFERENCES tracks(id), - user_id UUID NOT NULL REFERENCES users(id), - status VARCHAR(50) NOT NULL, - metadata JSONB NOT NULL DEFAULT '{}', - created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP - )"#, - ]; - - // Create indexes - let index_queries = [ - "CREATE INDEX IF NOT EXISTS idx_instances_customer_id ON instances(customer_id)", - "CREATE INDEX IF NOT EXISTS idx_rooms_instance_id ON rooms(instance_id)", - "CREATE INDEX IF NOT EXISTS idx_messages_conversation_id ON messages(conversation_id)", - "CREATE INDEX IF NOT EXISTS idx_messages_shard_key ON messages(shard_key)", - "CREATE INDEX IF NOT EXISTS idx_tracks_room_id ON tracks(room_id)", - "CREATE INDEX IF NOT EXISTS idx_subscriptions_track_id ON subscriptions(track_id)", - "CREATE INDEX IF NOT EXISTS idx_users_email ON users(email)", - ]; - - // Execute table creation queries - for query in table_queries { - sqlx::query(query) - .execute(pool) - .await?; - } - - // Execute index creation queries - for query in index_queries { - sqlx::query(query) - .execute(pool) - .await?; - } - - info!("Migrations completed successfully"); - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - use sqlx::postgres::{PgPoolOptions, PgPool}; - use rstest::*; - - async fn create_test_pool() -> PgPool { - let database_url = std::env::var("DATABASE_URL") - .unwrap_or_else(|_| "postgres://postgres:postgres@localhost/gb_test".to_string()); - - PgPoolOptions::new() - .max_connections(5) - .connect(&database_url) - .await - .expect("Failed to create test pool") - } - - #[rstest] - #[tokio::test] - async fn test_migrations() { - let pool = create_test_pool().await; - assert!(run_migrations(&pool).await.is_ok()); - } -} diff --git a/gb-monitoring/Cargo.toml b/gb-monitoring/Cargo.toml deleted file mode 100644 index 3af78a0..0000000 --- a/gb-monitoring/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "gb-monitoring" -version= { workspace = true } -edition= { workspace = true } - -[dependencies] -opentelemetry = { version = "0.19", features = ["rt-tokio"] } -opentelemetry-otlp = { version = "0.12", features = ["tonic"] } -tracing= { workspace = true } -tracing-subscriber= { workspace = true } -thiserror= { workspace = true } -prometheus= { workspace = true } -gb-core = { path = "../gb-core" } -lazy_static = "1.4" -tokio= { workspace = true } -serde= { workspace = true } -serde_json= { workspace = true } - -[dev-dependencies] -rstest= { workspace = true } -tokio-test = "0.4" \ No newline at end of file diff --git a/gb-monitoring/src/lib.rs b/gb-monitoring/src/lib.rs deleted file mode 100644 index a4742f6..0000000 --- a/gb-monitoring/src/lib.rs +++ /dev/null @@ -1,40 +0,0 @@ -mod logging; -mod metrics; -mod telemetry; - -pub use logging::init_logging; -pub use metrics::Metrics; -pub use telemetry::Telemetry; - - -#[cfg(test)] -mod tests { - use super::*; - use tracing::info; - - #[tokio::test] - async fn test_monitoring_integration() { - // Initialize logging - init_logging("gb").unwrap(); - - // Initialize metrics - let metrics = Metrics::new(); - - // Initialize telemetry - Telemetry::new("test-service").await.unwrap(); - - // Test logging with metrics - info!( - active_connections = metrics.active_connections.get() as i64, - "System initialized" - ); - - // Simulate some activity - metrics.set_active_connections(1); - metrics.increment_message_count(); - metrics.observe_processing_time(0.1); - - // Verify metrics - assert_eq!(metrics.active_connections.get(), 1); - } -} diff --git a/gb-monitoring/src/logging.rs b/gb-monitoring/src/logging.rs deleted file mode 100644 index ec89147..0000000 --- a/gb-monitoring/src/logging.rs +++ /dev/null @@ -1,40 +0,0 @@ -use tracing::subscriber::set_global_default; -use tracing_subscriber::{ - fmt::{format::FmtSpan, time}, - EnvFilter, - layer::SubscriberExt, - Registry, -}; - -pub fn init_logging(_service_name: &str) -> Result<(), Box> { - let env_filter = EnvFilter::try_from_default_env() - .unwrap_or_else(|_| EnvFilter::new("info")); - - let formatting_layer = tracing_subscriber::fmt::layer() - .with_timer(time::time()) - .with_target(true) - .with_thread_ids(true) - .with_span_events(FmtSpan::CLOSE) - .with_file(true) - .with_line_number(true); - - let subscriber = Registry::default() - .with(env_filter) - .with(formatting_layer); - - set_global_default(subscriber)?; // Use ? instead of expect - Ok(()) -} - -#[cfg(test)] -mod tests { - - use tracing::info; - - #[test] - fn test_logging_initialization() { - // TODO: init_logging("gb").Result; // Just call the function - info!("Test log message"); - // Add assertions to verify the log was actually written if needed - } -} diff --git a/gb-monitoring/src/metrics.rs b/gb-monitoring/src/metrics.rs deleted file mode 100644 index 466ca74..0000000 --- a/gb-monitoring/src/metrics.rs +++ /dev/null @@ -1,82 +0,0 @@ -use prometheus::{IntCounter, IntGauge, Histogram, Registry}; - -pub struct Metrics { - registry: Registry, - message_counter: IntCounter, - pub active_connections: IntGauge, - message_processing_time: Histogram, -} - -impl Metrics { - pub fn new() -> Self { - let registry = Registry::new(); - - let message_counter = IntCounter::new( - "message_total", - "Total number of messages processed" - ).unwrap(); - - let active_connections = IntGauge::new( - "active_connections", - "Number of active connections" - ).unwrap(); - - let message_processing_time = Histogram::with_opts( - prometheus::HistogramOpts::new( - "message_processing_seconds", - "Time spent processing messages" - ).buckets(vec![0.01, 0.05, 0.1, 0.5, 1.0, 2.0, 5.0]) - ).unwrap(); - - registry.register(Box::new(message_counter.clone())).unwrap(); - registry.register(Box::new(active_connections.clone())).unwrap(); - registry.register(Box::new(message_processing_time.clone())).unwrap(); - - Self { - registry, - message_counter, - active_connections, - message_processing_time, - } - } - - pub fn increment_message_count(&self) { - self.message_counter.inc(); - } - - pub fn observe_processing_time(&self, duration_seconds: f64) { - self.message_processing_time.observe(duration_seconds); - } - - pub fn set_active_connections(&self, count: i64) { - self.active_connections.set(count); - } - - pub fn registry(&self) -> &Registry { - &self.registry - } -} - -#[cfg(test)] -mod tests { - use prometheus::Encoder as _; - - use super::*; - - #[test] - fn test_metrics() { - let metrics = Metrics::new(); - - metrics.increment_message_count(); - assert_eq!(metrics.message_counter.get(), 1); - - metrics.set_active_connections(10); - assert_eq!(metrics.active_connections.get(), 10); - - metrics.observe_processing_time(0.5); - let mut buffer = Vec::new(); - let encoder = prometheus::TextEncoder::new(); - encoder.encode(&metrics.registry().gather(), &mut buffer).unwrap(); - assert!(!buffer.is_empty()); - } -} diff --git a/gb-monitoring/src/telemetry.rs b/gb-monitoring/src/telemetry.rs deleted file mode 100644 index 1fd50af..0000000 --- a/gb-monitoring/src/telemetry.rs +++ /dev/null @@ -1,65 +0,0 @@ -use opentelemetry::{ - sdk::{trace, Resource}, - runtime::Tokio, - KeyValue, -}; -use opentelemetry_otlp::{Protocol, WithExportConfig}; -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum TelemetryError { - #[error("Failed to initialize tracer: {0}")] - Init(String), -} - -#[allow(dead_code)] -pub struct Telemetry { - tracer: trace::Tracer -} - -impl Telemetry { - pub async fn new(service_name: &str) -> Result { - let tracer = Self::init_tracer(service_name) - .await - .map_err(|e| TelemetryError::Init(e.to_string()))?; - Ok(Self { tracer }) - } - - async fn init_tracer(service_name: &str) -> Result { - let exporter = opentelemetry_otlp::new_exporter() - .tonic() - .with_protocol(Protocol::Grpc); - - let resource = Resource::new(vec![ - KeyValue::new("service.name", service_name.to_string()), - ]); - - let config = trace::config().with_resource(resource); - - let tracer = opentelemetry_otlp::new_pipeline() - .tracing() - .with_exporter(exporter) - .with_trace_config(config) - .install_batch(Tokio) - .map_err(|e| TelemetryError::Init(e.to_string()))?; - - Ok(tracer) - } -} - -impl Drop for Telemetry { - fn drop(&mut self) { - opentelemetry::global::shutdown_tracer_provider(); - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[tokio::test] - async fn test_telemetry_creation() { - let telemetry = Telemetry::new("test-service").await; - assert!(telemetry.is_ok()); - } -} \ No newline at end of file diff --git a/gb-server/Cargo.toml b/gb-server/Cargo.toml deleted file mode 100644 index 997afcb..0000000 --- a/gb-server/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -name = "gb-server" -version = { workspace = true } -edition = { workspace = true } -authors = { workspace = true } -license = { workspace = true } - -[dependencies] -gb-core = { path = "../gb-core" } -gb-messaging = { path = "../gb-messaging" } -gb-monitoring = { path = "../gb-monitoring" } -gb-file = { path = "../gb-file" } -tokio = { workspace = true, features = ["full", "macros", "rt-multi-thread"] } -axum = { workspace = true, features = ["ws", "multipart", "macros"] } -serde = { workspace = true } -serde_json = { workspace = true } -uuid = { workspace = true } -tracing = { workspace = true } -tracing-subscriber = { workspace = true, features = ["env-filter"] } -async-trait = { workspace = true } -futures-util = { workspace = true, features = ["sink"] } # Now valid, as futures-util is in workspace.dependencies -chrono = { workspace = true, features = ["serde"] } -tokio-stream = { workspace = true } -sqlx = { workspace = true, features = ["runtime-tokio-rustls", "postgres", "chrono", "uuid"] } -redis = { workspace = true, features = ["tokio-comp"] } -hyper = { workspace = true, features = ["server"] } -hyper-util = { workspace = true } -tower = { workspace = true } -tower-http = { workspace = true, features = ["cors", "trace"] } -actix-web = { workspace = true } -dotenv = { workspace = true } -log = { workspace = true } -vector = "0.4.1" - -[dev-dependencies] -rstest = { workspace = true } -tokio-test = { workspace = true } diff --git a/gb-server/src/lib.rs b/gb-server/src/lib.rs deleted file mode 100644 index e69de29..0000000 diff --git a/gb-server/src/main.rs b/gb-server/src/main.rs deleted file mode 100644 index 06d3871..0000000 --- a/gb-server/src/main.rs +++ /dev/null @@ -1,72 +0,0 @@ -use log::{info, LevelFilter}; - - -use tokio::net::TcpStream; - -use actix_web::{middleware, web, App, HttpServer}; -use gb_core::models; -use tracing_subscriber::fmt::format::FmtSpan; -use dotenv::dotenv; -use gb_core::config::AppConfig; -use gb_core::db::{init_minio, init_postgres}; -use gb_file::handlers::upload_file; - -#[actix_web::main] -async fn main() -> std::io::Result<()> { - dotenv().ok(); - - // Initialize tracing - tracing_subscriber::fmt() - .with_span_events(FmtSpan::CLOSE) - .init(); - - // Configure the logger - // log::set_logger(&VectorLogger { stream: TcpStream::connect("127.0.0.1:9000").await? }) - // .map_err(|_| "Couldn't set logger")?; - // log::set_max_level(LevelFilter::Info); - - // Get the Vector agent's address and port - let vector_host = "127.0.0.1"; - let vector_port = 9000; - - // // Start a Vector logger - // let mut vector_logger = VectorLogger::new(vector_host, vector_port).await?; - - // // Set the logger - // log::set_logger(&vector_logger).map_err(|_| "Couldn't set logger")?; - // log::set_max_level(LevelFilter::Info); - - // Log some messages - info!("Hello from Rust!"); - - - // Load configuration - let config = AppConfig::from_env(); - - - // TODO: /gbo/bin/storage$ ./minio server ../../data/storage/ - - - - // Initialize databases and services - let db_pool = init_postgres(&config).await.expect("Failed to connect to PostgreSQL"); - let minio_client = init_minio(&config).await.expect("Failed to initialize Minio"); - - let app_state = web::Data::new(models::AppState { - config: Some(config.clone()), - db_pool: Some(db_pool), - minio_client: Some(minio_client), - }); - - // Start HTTP server - HttpServer::new(move || { - App::new() - .wrap(middleware::Logger::default()) - .wrap(middleware::Compress::default()) - .app_data(app_state.clone()) - .service(upload_file) - }) - .bind((config.server.host.clone(), config.server.port))? - .run() - .await -} diff --git a/gb-storage/Cargo.toml b/gb-storage/Cargo.toml deleted file mode 100644 index 75b4b69..0000000 --- a/gb-storage/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "gb-storage" -version = { workspace = true } -edition = { workspace = true } -authors = { workspace = true } -license = { workspace = true } - -[dependencies] -gb-core = { path = "../gb-core" } -tokio= { workspace = true } -sqlx= { workspace = true } -redis= { workspace = true } -tracing= { workspace = true } -async-trait= { workspace = true } -serde= { workspace = true } -serde_json= { workspace = true } -uuid= { workspace = true } -chrono= { workspace = true } -tikv-client = "0.1" - -[dev-dependencies] -rstest= { workspace = true } -mockall= { workspace = true } -tokio-test = "0.4" diff --git a/gb-storage/src/lib.rs b/gb-storage/src/lib.rs deleted file mode 100644 index 5f8e4c6..0000000 --- a/gb-storage/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod postgres; -mod redis; -mod tikv; - -pub use postgres::PostgresCustomerRepository; -pub use redis::RedisStorage; -pub use tikv::TiKVStorage; \ No newline at end of file diff --git a/gb-storage/src/models.rs b/gb-storage/src/models.rs deleted file mode 100644 index 80f09dd..0000000 --- a/gb-storage/src/models.rs +++ /dev/null @@ -1,21 +0,0 @@ -// or wherever SubscriptionTier is defined - -impl From for String { - fn from(tier: SubscriptionTier) -> Self { - match tier { - SubscriptionTier::Free => "free".to_string(), - SubscriptionTier::Pro => "pro".to_string(), - SubscriptionTier::Enterprise => "enterprise".to_string(), - } - } -} - -impl From for String { - fn from(status: CustomerStatus) -> Self { - match status { - CustomerStatus::Active => "active".to_string(), - CustomerStatus::Inactive => "inactive".to_string(), - CustomerStatus::Suspended => "suspended".to_string(), - } - } -} diff --git a/gb-storage/src/postgres.rs b/gb-storage/src/postgres.rs deleted file mode 100644 index 0fc8fcf..0000000 --- a/gb-storage/src/postgres.rs +++ /dev/null @@ -1,229 +0,0 @@ -use gb_core::{ - Result, Error, - models::{Customer, CustomerStatus, SubscriptionTier}, -}; -use sqlx::{PgPool, Row, postgres::PgRow}; -use std::sync::Arc; -use chrono::Utc; - -#[allow(dead_code)] -#[async_trait::async_trait] -pub trait CustomerRepository: Send + Sync { - async fn create(&self, customer: Customer) -> Result; - async fn get_customer_by_id(&self, id: &str) -> Result>; - async fn update(&self, customer: Customer) -> Result; - async fn delete(&self, id: &str) -> Result<()>; -} - -trait ToDbString { - fn to_db_string(&self) -> String; -} - -trait FromDbString: Sized { - fn from_db_string(s: &str) -> Result; -} - -impl ToDbString for SubscriptionTier { - fn to_db_string(&self) -> String { - match self { - SubscriptionTier::Free => "free".to_string(), - SubscriptionTier::Pro => "pro".to_string(), - SubscriptionTier::Enterprise => "enterprise".to_string(), - } - } -} - -impl ToDbString for CustomerStatus { - fn to_db_string(&self) -> String { - match self { - CustomerStatus::Active => "active".to_string(), - CustomerStatus::Inactive => "inactive".to_string(), - CustomerStatus::Suspended => "suspended".to_string(), - } - } -} - -impl FromDbString for SubscriptionTier { - fn from_db_string(s: &str) -> Result { - match s { - "free" => Ok(SubscriptionTier::Free), - "pro" => Ok(SubscriptionTier::Pro), - "enterprise" => Ok(SubscriptionTier::Enterprise), - _ => Err(Error::internal(format!("Invalid subscription tier: {}", s))), - } - } -} - -impl FromDbString for CustomerStatus { - fn from_db_string(s: &str) -> Result { - match s { - "active" => Ok(CustomerStatus::Active), - "inactive" => Ok(CustomerStatus::Inactive), - "suspended" => Ok(CustomerStatus::Suspended), - _ => Err(Error::internal(format!("Invalid customer status: {}", s))), - } - } -} - -pub struct PostgresCustomerRepository { - pool: Arc, -} - -#[async_trait::async_trait] -impl CustomerRepository for PostgresCustomerRepository { - async fn create(&self, customer: Customer) -> Result { - let subscription_tier = customer.subscription_tier.to_db_string(); - let status = customer.status.to_db_string(); - - let row = sqlx::query( - r#" - INSERT INTO customers ( - id, name, email, - subscription_tier, status, - created_at, updated_at, - max_instances - ) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8) - RETURNING * - "# - ) - .bind(&customer.id) - .bind(&customer.name) - .bind(&customer.email) - .bind(&subscription_tier) - .bind(&status) - .bind(&customer.created_at) - .bind(&customer.updated_at) - .bind(customer.max_instances as i32) - .fetch_one(&*self.pool) - .await - .map_err(|e| Error::internal(format!("Database error: {}", e)))?; - - Self::row_to_customer(&row).await - } - - async fn get_customer_by_id(&self, id: &str) -> Result> { - let maybe_row = sqlx::query( - "SELECT * FROM customers WHERE id = $1" - ) - .bind(id) - .fetch_optional(&*self.pool) - .await - .map_err(|e| Error::internal(format!("Database error: {}", e)))?; - - if let Some(row) = maybe_row { - Ok(Some(Self::row_to_customer(&row).await?)) - } else { - Ok(None) - } - } - - async fn update(&self, customer: Customer) -> Result { - let subscription_tier = customer.subscription_tier.to_db_string(); - let status = customer.status.to_db_string(); - - let row = sqlx::query( - r#" - UPDATE customers - SET name = $2, - email = $3, - subscription_tier = $4, - status = $5, - updated_at = $6, - max_instances = $7 - WHERE id = $1 - RETURNING * - "# - ) - .bind(&customer.id) - .bind(&customer.name) - .bind(&customer.email) - .bind(&subscription_tier) - .bind(&status) - .bind(Utc::now()) - .bind(customer.max_instances as i32) - .fetch_one(&*self.pool) - .await - .map_err(|e| Error::internal(format!("Database error: {}", e)))?; - - Self::row_to_customer(&row).await - } - - async fn delete(&self, id: &str) -> Result<()> { - sqlx::query("DELETE FROM customers WHERE id = $1") - .bind(id) - .execute(&*self.pool) - .await - .map_err(|e| Error::internal(format!("Database error: {}", e)))?; - - Ok(()) - } -} - -impl PostgresCustomerRepository { - pub fn new(pool: Arc) -> Self { - Self { pool } - } - - async fn row_to_customer(row: &PgRow) -> Result { - Ok(Customer { - id: row.try_get("id").map_err(|e| Error::internal(e.to_string()))?, - name: row.try_get("name").map_err(|e| Error::internal(e.to_string()))?, - email: row.try_get("email").map_err(|e| Error::internal(e.to_string()))?, - subscription_tier: SubscriptionTier::from_db_string( - row.try_get("subscription_tier").map_err(|e| Error::internal(e.to_string()))? - )?, - status: CustomerStatus::from_db_string( - row.try_get("status").map_err(|e| Error::internal(e.to_string()))? - )?, - created_at: row.try_get("created_at").map_err(|e| Error::internal(e.to_string()))?, - updated_at: row.try_get("updated_at").map_err(|e| Error::internal(e.to_string()))?, - max_instances: { - let value: i32 = row.try_get("max_instances") - .map_err(|e| Error::internal(e.to_string()))?; - if value < 0 { - return Err(Error::internal("max_instances cannot be negative")); - } - value as u32 - }, - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use chrono::Utc; - use uuid::Uuid; - - #[allow(dead_code)] - fn create_test_customer() -> Customer { - Customer { - id: Uuid::new_v4(), - name: "Test Customer".to_string(), - email: "test@example.com".to_string(), - subscription_tier: SubscriptionTier::Free, - status: CustomerStatus::Active, - created_at: Utc::now(), - updated_at: Utc::now(), - max_instances: 1, - } - } - - // Add your tests here - // Example: - /* - #[sqlx::test] - async fn test_create_customer() { - let pool = setup_test_db().await; - let repo = PostgresCustomerRepository::new(Arc::new(pool)); - - let customer = create_test_customer(); - let created = repo.create(customer.clone()).await.unwrap(); - - assert_eq!(created.id, customer.id); - assert_eq!(created.name, customer.name); - // ... more assertions - } - */ -} \ No newline at end of file diff --git a/gb-storage/src/redis.rs b/gb-storage/src/redis.rs deleted file mode 100644 index 6de0fdf..0000000 --- a/gb-storage/src/redis.rs +++ /dev/null @@ -1,79 +0,0 @@ -use gb_core::{Result, Error}; -use redis::{Client, Commands}; -use serde::{de::DeserializeOwned, Serialize}; -use std::time::Duration; -use tracing::instrument; - -pub struct RedisStorage { - client: Client, -} - -impl RedisStorage { - pub fn new(url: &str) -> Result { - let client = Client::open(url) - .map_err(|e| Error::internal(format!("Redis error: {}", e)))?; - - Ok(Self { client }) - } - - - #[allow(dependency_on_unit_never_type_fallback)] - #[instrument(skip(self))] - pub async fn set(&self, key: &str, value: &T) -> Result<()> { - let mut conn = self.client.get_connection() - .map_err(|e| Error::internal(format!("Redis error: {}", e)))?; - - let serialized = serde_json::to_string(value) - .map_err(|e| Error::internal(format!("Serialization error: {}", e)))?; - - conn.set(key, serialized) - .map_err(|e| Error::internal(format!("Redis error: {}", e)))?; - - Ok(()) - } - - #[instrument(skip(self))] - pub async fn get(&self, key: &str) -> Result> { - let mut conn = self.client.get_connection() - .map_err(|e| Error::internal(format!("Redis error: {}", e)))?; - - let value: Option = conn.get(key) - .map_err(|e| Error::internal(format!("Redis error: {}", e)))?; - - match value { - Some(v) => { - let deserialized = serde_json::from_str(&v) - .map_err(|e| Error::internal(format!("Deserialization error: {}", e)))?; - Ok(Some(deserialized)) - } - None => Ok(None) - } - } - - #[instrument(skip(self))] - pub async fn delete(&self, key: &str) -> Result { - let mut conn = self.client.get_connection() - .map_err(|e| Error::internal(format!("Redis error: {}", e)))?; - - conn.del(key) - .map_err(|e| Error::internal(format!("Redis error: {}", e))) - } - - #[allow(dependency_on_unit_never_type_fallback)] - #[instrument(skip(self))] - pub async fn set_with_ttl(&self, key: &str, value: &T, ttl: Duration) -> Result<()> { - let mut conn = self.client.get_connection() - .map_err(|e| Error::internal(format!("Redis error: {}", e)))?; - - let serialized = serde_json::to_string(value) - .map_err(|e| Error::internal(format!("Serialization error: {}", e)))?; - - redis::pipe() - .set(key, serialized) - .expire(key, ttl.as_secs() as i64) - .query(&mut conn) - .map_err(|e| Error::internal(format!("Redis error: {}", e)))?; - - Ok(()) - } -} \ No newline at end of file diff --git a/gb-storage/src/tikv.rs b/gb-storage/src/tikv.rs deleted file mode 100644 index 74817ec..0000000 --- a/gb-storage/src/tikv.rs +++ /dev/null @@ -1,73 +0,0 @@ -use gb_core::{Result, Error}; -use tikv_client::{RawClient, Config, KvPair}; -use tracing::{error, instrument}; - -pub struct TiKVStorage { - client: RawClient, -} - -impl TiKVStorage { - pub async fn new(pd_endpoints: Vec) -> Result { - let _config = Config::default(); - let client = RawClient::new(pd_endpoints) - .await - .map_err(|e| Error::internal(format!("TiKV error: {}", e)))?; - - Ok(Self { client }) - } - - #[instrument(skip(self))] - pub async fn get(&self, key: &[u8]) -> Result>> { - self.client - .get(key.to_vec()) - .await - .map_err(|e| { - error!("TiKV get error: {}", e); - Error::internal(format!("TiKV error: {}", e)) - }) - } - - #[instrument(skip(self))] - pub async fn put(&self, key: &[u8], value: &[u8]) -> Result<()> { - self.client - .put(key.to_vec(), value.to_vec()) - .await - .map_err(|e| { - error!("TiKV put error: {}", e); - Error::internal(format!("TiKV error: {}", e)) - }) - } - - #[instrument(skip(self))] - pub async fn delete(&self, key: &[u8]) -> Result<()> { - self.client - .delete(key.to_vec()) - .await - .map_err(|e| { - error!("TiKV delete error: {}", e); - Error::internal(format!("TiKV error: {}", e)) - }) - } - - #[instrument(skip(self))] - pub async fn batch_get(&self, keys: Vec>) -> Result> { - self.client - .batch_get(keys) - .await - .map_err(|e| { - error!("TiKV batch get error: {}", e); - Error::internal(format!("TiKV error: {}", e)) - }) - } - - #[instrument(skip(self))] - pub async fn scan(&self, start: &[u8], end: &[u8], limit: u32) -> Result> { - self.client - .scan(start.to_vec()..end.to_vec(), limit) - .await - .map_err(|e| { - error!("TiKV scan error: {}", e); - Error::internal(format!("TiKV error: {}", e)) - }) - } -} \ No newline at end of file diff --git a/gb-testing/Cargo.toml b/gb-testing/Cargo.toml deleted file mode 100644 index 74b0045..0000000 --- a/gb-testing/Cargo.toml +++ /dev/null @@ -1,76 +0,0 @@ -[package] -name = "gb-testing" -version = { workspace = true } -edition = { workspace = true } -authors = { workspace = true } -license = { workspace = true } - -# Define features -[features] -default = ["integration"] # No default features -integration = [] # Feature for integration tests -load = [] # Feature for load tests -stress = [] # Feature for stress tests -chaos = [] # Feature for chaos tests - - -[dependencies] -gb-core = { path = "../gb-core" } -gb-auth = { path = "../gb-auth" } -gb-server = { path = "../gb-server" } -gb-file = { path = "../gb-file" } - -anyhow = { workspace = true } -# Testing frameworks -goose = "0.17" # Load testing -criterion = { workspace = true, features = ["async_futures"] } - -# Async Runtime -tokio = { workspace = true } -tokio-stream= { workspace = true } -async-trait = { workspace = true } - -# HTTP Client -reqwest = { workspace = true, features = ["json", "stream"] } -hyper = { workspace = true, features = ["full"] } - -# WebSocket Testing -tokio-tungstenite = { workspace = true } -tungstenite = { workspace = true } - -# Database -sqlx = { workspace = true } -redis = { workspace = true } - -# Metrics & Monitoring -prometheus = { workspace = true, features = ["process"] } -tracing = { workspace = true } -opentelemetry = { workspace = true } - -# Serialization -serde = { workspace = true } -serde_json = { workspace = true } - -# Utils -futures = { workspace = true } -rand = { workspace = true } -fake = { workspace = true, features = ["derive"] } -chrono = { workspace = true, features = ["serde"] } -uuid = { workspace = true, features = ["v4"] } - - -minio = { workspace = true } -actix-web ={ workspace = true } -actix-multipart ={ workspace = true } -sanitize-filename = { workspace = true } -tempfile = { workspace = true } -bytes = { workspace = true } - -[dev-dependencies] -rstest = { workspace = true } -wiremock = "0.5" -assert_cmd = "2.0" -predicates = "3.0" - - -jmap-client = "0.1" # Check for the latest version on crates.io diff --git a/gb-testing/README.md b/gb-testing/README.md deleted file mode 100644 index 110c37a..0000000 --- a/gb-testing/README.md +++ /dev/null @@ -1 +0,0 @@ -cargo test --package gb-testing --test integration_email_list -- test_successful_email_lilst --exact --show-output \ No newline at end of file diff --git a/gb-testing/config/test_config.yaml b/gb-testing/config/test_config.yaml deleted file mode 100644 index 2efa813..0000000 --- a/gb-testing/config/test_config.yaml +++ /dev/null @@ -1,57 +0,0 @@ -load_test: - users: 100 - duration: 300 # seconds - ramp_up: 60 # seconds - scenarios: - - auth - - api - - webrtc - -performance_test: - iterations: 1000 - -performance_test: - iterations: 1000 - warmup_iterations: 100 - sample_size: 100 - threads: 8 - scenarios: - - api_latency - - database_queries - - media_processing - -stress_test: - duration: 1800 # 30 minutes - concurrent_users: 1000 - scenarios: - - continuous_requests - - websocket_connections - - file_uploads - -chaos_test: - duration: 3600 # 1 hour - interval: 300 # 5 minutes between actions - actions: - - kill_random_pod - - network_partition - - resource_exhaustion - - disk_pressure - -metrics: - prometheus: - enabled: true - port: 9090 - grafana: - enabled: true - port: 3000 - jaeger: - enabled: true - port: 16686 - -reports: - formats: - - json - - html - - pdf - output_dir: "./test-reports" - retain_days: 30 diff --git a/gb-testing/run_tests.sh b/gb-testing/run_tests.sh deleted file mode 100755 index 5625d61..0000000 --- a/gb-testing/run_tests.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -set -e - -echo "Running gb-testing test suite..." - -# Run integration tests -echo "Running integration tests..." -cargo test --test '*' --features integration - -# Run load tests -echo "Running load tests..." -cargo test --test '*' --features load - -# Run performance benchmarks -#echo "Running performance benchmarks..." -#cargo bench - -# Run stress tests -#echo "Running stress tests..." -#cargo test --test '*' --features stress - -# Run chaos tests -#echo "Running chaos tests..." -#cargo test --test '*' --features chaos - -echo "All tests completed!" diff --git a/gb-testing/src/chaos/mod.rs b/gb-testing/src/chaos/mod.rs deleted file mode 100644 index a234d76..0000000 --- a/gb-testing/src/chaos/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ - -pub struct ChaosTest { -} - -impl ChaosTest { - pub async fn new() -> anyhow::Result { - // Initialize the ChaosTest struct - Ok(ChaosTest { }) - } - - pub async fn network_partition(&self) -> anyhow::Result<()> { - // Network partition test implementation - Ok(()) - } - - pub async fn resource_exhaustion(&self) -> anyhow::Result<()> { - // Resource exhaustion test implementation - Ok(()) - } -} diff --git a/gb-testing/src/integration/mod.rs b/gb-testing/src/integration/mod.rs deleted file mode 100644 index 33fc44e..0000000 --- a/gb-testing/src/integration/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ -use async_trait::async_trait; -use sqlx::PgPool; - -pub struct IntegrationTest { - pub db_pool: PgPool, -} - -#[async_trait] -pub trait IntegrationTestCase { - async fn setup(&mut self) -> anyhow::Result<()>; - async fn execute(&self) -> anyhow::Result<()>; - async fn teardown(&mut self) -> anyhow::Result<()>; -} \ No newline at end of file diff --git a/gb-testing/src/lib.rs b/gb-testing/src/lib.rs deleted file mode 100644 index 74457d5..0000000 --- a/gb-testing/src/lib.rs +++ /dev/null @@ -1,13 +0,0 @@ -pub mod integration; -pub mod load; -pub mod performance; -pub mod stress; -pub mod chaos; -pub mod scenarios; -pub mod utils; -pub mod metrics; -pub mod reports; - -pub use scenarios::TestScenario; -pub use metrics::TestMetrics; -pub use reports::TestReport; diff --git a/gb-testing/src/load/mod.rs b/gb-testing/src/load/mod.rs deleted file mode 100644 index 720fa1a..0000000 --- a/gb-testing/src/load/mod.rs +++ /dev/null @@ -1,140 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Serialize, Deserialize)] -pub struct LoadTestConfig { - pub users: usize, - pub duration: std::time::Duration, - pub ramp_up: std::time::Duration, - pub scenarios: Vec, -} - -pub struct LoadTest { - pub config: LoadTestConfig, - pub metrics: crate::metrics::TestMetrics, -} - -// impl LoadTest { -// pub fn new(config: LoadTestConfig) -> Self { -// Self { -// config, -// metrics: crate::metrics::TestMetrics::new(), -// } -// } - -// pub async fn run(&self) -> anyhow::Result { -// let mut goose = GooseAttack::initialize()?; - -// goose -// .set_default_host("http://localhost:8080")? -// .set_users(self.config.users)? -// .set_startup_time(self.config.ramp_up)? -// .set_run_time(self.config.duration)?; - -// for scenario in &self.config.scenarios { -// match scenario.as_str() { -// "auth" => goose.register_scenario(auth_scenario()), -// "api" => goose.register_scenario(api_scenario()), -// "webrtc" => goose.register_scenario(webrtc_scenario()), -// _ => continue, -// }?; -// } - -// let metrics = goose.execute().await?; -// Ok(crate::reports::TestReport::from(metrics)) -// } -// } - -// fn auth_scenario() -> Scenario { -// scenario!("Authentication") -// .register_transaction(transaction!(login)) -// .register_transaction(transaction!(logout)) -// } - -// async fn login(user: &mut GooseUser) -> TransactionResult { -// let payload = serde_json::json!({ -// "email": "test@example.com", -// "password": "password123" -// }); - -// let _response = user -// .post_json("/auth/login", &payload) -// .await? -// .response?; - -// Ok(()) -// } - -// async fn logout(user: &mut GooseUser) -> TransactionResult { -// let _response = user -// .post("/auth/logout") -// .await? -// .response?; - -// Ok(()) -// } - -// fn api_scenario() -> Scenario { -// scenario!("API") -// .register_transaction(transaction!(create_instance)) -// .register_transaction(transaction!(list_instances)) -// } - -// async fn create_instance(user: &mut GooseUser) -> TransactionResult { -// let payload = serde_json::json!({ -// "name": "test-instance", -// "config": { -// "memory": "512Mi", -// "cpu": "0.5" -// } -// }); - -// let _response = user -// .post_json("/api/instances", &payload) -// .await? -// .response?; - -// Ok(()) -// } - -// async fn list_instances(user: &mut GooseUser) -> TransactionResult { -// let _response = user -// .get("/api/instances") -// .await? -// .response?; - -// Ok(()) -// } - -// fn webrtc_scenario() -> Scenario { -// scenario!("WebRTC") -// .register_transaction(transaction!(join_room)) -// .register_transaction(transaction!(send_message)) -// } - -// async fn join_room(user: &mut GooseUser) -> TransactionResult { -// let payload = serde_json::json!({ -// "room_id": "test-room", -// "user_id": "test-user" -// }); - -// let _response = user -// .post_json("/webrtc/rooms/join", &payload) -// .await? -// .response?; - -// Ok(()) -// } - -// async fn send_message(user: &mut GooseUser) -> TransactionResult { -// let payload = serde_json::json!({ -// "room_id": "test-room", -// "message": "test message" -// }); - -// let _response = user -// .post_json("/webrtc/messages", &payload) -// .await? -// .response?; - -// Ok(()) -// } diff --git a/gb-testing/src/metrics/mod.rs b/gb-testing/src/metrics/mod.rs deleted file mode 100644 index ce71d2c..0000000 --- a/gb-testing/src/metrics/mod.rs +++ /dev/null @@ -1,52 +0,0 @@ -use prometheus::{Registry, Counter, Gauge, Histogram, HistogramOpts}; - -#[allow(dead_code)] -pub struct TestMetrics { - registry: Registry, - request_count: Counter, - error_count: Counter, - response_time: Histogram, - active_users: Gauge, -} - -impl TestMetrics { - pub fn new() -> Self { - let registry = Registry::new(); - - let request_count = Counter::new("test_requests_total", "Total number of requests").unwrap(); - let error_count = Counter::new("test_errors_total", "Total number of errors").unwrap(); - let response_time = Histogram::with_opts( - HistogramOpts::new("test_response_time", "Response time in seconds") - ).unwrap(); - let active_users = Gauge::new("test_active_users", "Number of active users").unwrap(); - - registry.register(Box::new(request_count.clone())).unwrap(); - registry.register(Box::new(error_count.clone())).unwrap(); - registry.register(Box::new(response_time.clone())).unwrap(); - registry.register(Box::new(active_users.clone())).unwrap(); - - Self { - registry, - request_count, - error_count, - response_time, - active_users, - } - } - - pub fn increment_requests(&self) { - self.request_count.inc(); - } - - pub fn increment_errors(&self) { - self.error_count.inc(); - } - - pub fn observe_response_time(&self, duration: f64) { - self.response_time.observe(duration); - } - - pub fn set_active_users(&self, count: i64) { - self.active_users.set(count as f64); - } -} diff --git a/gb-testing/src/performance/mod.rs b/gb-testing/src/performance/mod.rs deleted file mode 100644 index 552528d..0000000 --- a/gb-testing/src/performance/mod.rs +++ /dev/null @@ -1,29 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; -use tokio::runtime::Runtime; - -pub fn benchmark_api(c: &mut Criterion) { - let rt = Runtime::new().unwrap(); - - c.bench_function("api_latency", |b| { - b.iter(|| { - rt.block_on(async { - // API latency test implementation - }) - }) - }); -} - -pub fn benchmark_database(c: &mut Criterion) { - let rt = Runtime::new().unwrap(); - - c.bench_function("db_query_performance", |b| { - b.iter(|| { - rt.block_on(async { - // Database query performance test implementation - }) - }) - }); -} - -criterion_group!(benches, benchmark_api, benchmark_database); -criterion_main!(benches); diff --git a/gb-testing/src/reports/mod.rs b/gb-testing/src/reports/mod.rs deleted file mode 100644 index e38843d..0000000 --- a/gb-testing/src/reports/mod.rs +++ /dev/null @@ -1,64 +0,0 @@ -use anyhow; -use serde::Serialize; -use std::time::{Duration, SystemTime}; - -#[derive(Debug, Serialize)] -pub struct TestReport { - pub timestamp: SystemTime, - pub duration: Duration, - pub total_requests: u64, - pub successful_requests: u64, - pub failed_requests: u64, - pub avg_response_time: f64, - pub percentiles: Percentiles, - pub errors: Vec, -} - -#[derive(Debug, Serialize)] -pub struct Percentiles { - pub p50: f64, - pub p90: f64, - pub p95: f64, - pub p99: f64, -} - -#[derive(Debug, Serialize)] -pub struct TestError { - pub error_type: String, - pub message: String, - pub count: u64, -} - -impl TestReport { - pub fn new( - duration: Duration, - total_requests: u64, - successful_requests: u64, - failed_requests: u64, - avg_response_time: f64, - percentiles: Percentiles, - errors: Vec, - ) -> Self { - Self { - timestamp: SystemTime::now(), - duration, - total_requests, - successful_requests, - failed_requests, - avg_response_time, - percentiles, - errors, - } - } - - pub fn save_json(&self, path: &str) -> anyhow::Result<()> { - let json = serde_json::to_string_pretty(self)?; - std::fs::write(path, json)?; - Ok(()) - } - - pub fn save_html(&self, _path: &str) -> anyhow::Result<()> { - // HTML report generation implementation - Ok(()) - } -} diff --git a/gb-testing/src/scenarios/mod.rs b/gb-testing/src/scenarios/mod.rs deleted file mode 100644 index 81e3603..0000000 --- a/gb-testing/src/scenarios/mod.rs +++ /dev/null @@ -1,31 +0,0 @@ -use async_trait::async_trait; -use serde::{Deserialize, Serialize}; -use std::time::Duration; - -#[async_trait] -pub trait TestScenario { - async fn setup(&mut self) -> anyhow::Result<()>; - async fn execute(&self) -> anyhow::Result<()>; - async fn teardown(&mut self) -> anyhow::Result<()>; - fn name(&self) -> &'static str; - fn description(&self) -> &'static str; -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct ScenarioResult { - pub name: String, - pub success: bool, - pub duration: Duration, - pub error: Option, - pub metrics: ScenarioMetrics, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct ScenarioMetrics { - pub requests: u64, - pub failures: u64, - pub avg_response_time: f64, - pub max_response_time: f64, - pub min_response_time: f64, - pub throughput: f64, -} diff --git a/gb-testing/src/stress/mod.rs b/gb-testing/src/stress/mod.rs deleted file mode 100644 index d2dc837..0000000 --- a/gb-testing/src/stress/mod.rs +++ /dev/null @@ -1,38 +0,0 @@ -use std::time::Duration; -use tokio::time; - -pub struct StressTest { - duration: Duration, - concurrent_users: usize, -} - -impl StressTest { - pub fn new(duration: Duration, concurrent_users: usize) -> Self { - Self { - duration, - concurrent_users, - } - } - - pub async fn run(&self) -> anyhow::Result<()> { - let start = std::time::Instant::now(); - - while start.elapsed() < self.duration { - let mut handles = Vec::new(); - - for _ in 0..self.concurrent_users { - handles.push(tokio::spawn(async { - // Stress test implementation - })); - } - - for handle in handles { - handle.await?; - } - - time::sleep(Duration::from_secs(1)).await; - } - - Ok(()) - } -} diff --git a/gb-testing/src/utils/mod.rs b/gb-testing/src/utils/mod.rs deleted file mode 100644 index 663f6d1..0000000 --- a/gb-testing/src/utils/mod.rs +++ /dev/null @@ -1,49 +0,0 @@ -use rand::{distributions::Alphanumeric, Rng}; -use std::time::Duration; - -pub fn generate_random_string(length: usize) -> String { - rand::thread_rng() - .sample_iter(&Alphanumeric) - .take(length) - .map(char::from) - .collect() -} - -pub fn generate_test_data(size: usize) -> Vec { - (0..size).map(|_| rand::random::()).collect() -} - -pub async fn exponential_backoff( - mut operation: F, - max_retries: u32, - initial_delay: Duration, -) -> anyhow::Result -where - F: FnMut() -> Fut, - Fut: std::future::Future>, -{ - let mut retries = 0; - let mut delay = initial_delay; - - loop { - match operation().await { - Ok(value) => return Ok(value), - Err(error) => { - if retries >= max_retries { - return Err(error); - } - tokio::time::sleep(delay).await; - delay *= 2; - retries += 1; - } - } - } -} - -pub fn format_duration(duration: Duration) -> String { - let total_seconds = duration.as_secs(); - let hours = total_seconds / 3600; - let minutes = (total_seconds % 3600) / 60; - let seconds = total_seconds % 60; - format!("{:02}:{:02}:{:02}", hours, minutes, seconds) -} diff --git a/gb-testing/tests/chaos_kubernetes_test.rs b/gb-testing/tests/chaos_kubernetes_test.rs deleted file mode 100644 index 48f7136..0000000 --- a/gb-testing/tests/chaos_kubernetes_test.rs +++ /dev/null @@ -1,12 +0,0 @@ -use gb_testing::chaos::ChaosTest; - -#[tokio::test] -async fn test_kubernetes_chaos() -> anyhow::Result<()> { - let chaos_test = ChaosTest::new().await?; - - - chaos_test.network_partition().await?; - chaos_test.resource_exhaustion().await?; - - Ok(()) -} diff --git a/gb-testing/tests/load_auth_test.rs b/gb-testing/tests/load_auth_test.rs deleted file mode 100644 index 0ce4615..0000000 --- a/gb-testing/tests/load_auth_test.rs +++ /dev/null @@ -1,20 +0,0 @@ -use gb_testing::load::LoadTestConfig; -use std::time::Duration; - -#[tokio::test] -async fn test_auth_load() -> anyhow::Result<()> { - let _config = LoadTestConfig { - users: 100, - duration: Duration::from_secs(300), - ramp_up: Duration::from_secs(60), - scenarios: vec!["auth".to_string()], - }; - - // let load_test = LoadTest::new(config); - // let report = load_test.run().await?; - - // report.save_json("test-reports/auth-load-test.json")?; - // report.save_html("test-reports/auth-load-test.html")?; - - Ok(()) -} diff --git a/gb-testing/tests/performance_api_bench.rs b/gb-testing/tests/performance_api_bench.rs deleted file mode 100644 index 2012b21..0000000 --- a/gb-testing/tests/performance_api_bench.rs +++ /dev/null @@ -1,17 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; - - -pub fn api_benchmark(c: &mut Criterion) { - let mut group = c.benchmark_group("API"); - - group.bench_function("create_instance", |b| { - b.iter(|| { - // Benchmark implementation - }) - }); - - group.finish(); -} - -criterion_group!(benches, api_benchmark); -criterion_main!(benches); diff --git a/gb-utils/Cargo.toml b/gb-utils/Cargo.toml deleted file mode 100644 index 021b591..0000000 --- a/gb-utils/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "gb-utils" -version = { workspace = true } -edition = { workspace = true } -authors = { workspace = true } -license = { workspace = true } - -[dependencies] -gb-core = { path = "../gb-core" } -gb-document = { path = "../gb-document" } -gb-image = { path = "../gb-image" } -async-trait= { workspace = true } -tokio= { workspace = true } -serde= { workspace = true } -serde_json= { workspace = true } -thiserror= { workspace = true } -tracing= { workspace = true } -mime = "0.3" -mime_guess = "2.0" -uuid = { version = "1.6", features = ["v4"] } - -[dev-dependencies] -rstest= { workspace = true } -tokio-test = "0.4" diff --git a/gb-utils/src/detector.rs b/gb-utils/src/detector.rs deleted file mode 100644 index 6849424..0000000 --- a/gb-utils/src/detector.rs +++ /dev/null @@ -1,66 +0,0 @@ -use gb_core::{Result, Error}; -use tracing::instrument; - -pub struct FileTypeDetector; - -impl FileTypeDetector { - - #[instrument(skip(data))] - pub fn detect_from_bytes(data: &[u8]) -> Result { - if data.starts_with(b"%PDF") { - Ok(FileType::Pdf) - } else if data.starts_with(&[0x50, 0x4B, 0x03, 0x04]) { - // ZIP header, could be DOCX/XLSX - if Self::is_office_document(data) { - Ok(FileType::Word) - } else { - Ok(FileType::Excel) - } - } else if data.starts_with(&[0x89, 0x50, 0x4E, 0x47]) { - Ok(FileType::Png) - } else if data.starts_with(&[0xFF, 0xD8, 0xFF]) { - Ok(FileType::Jpeg) - } else if data.starts_with(b"RIFF") && data[8..12] == *b"WEBP" { - Ok(FileType::WebP) - } else { - Err(Error::internal("Unknown file type".to_string())) - } - } - - fn is_office_document(data: &[u8]) -> bool { - // Check for Office Open XML signatures - // This is a simplified check - std::str::from_utf8(data) - .map(|s| s.contains("word/")) - .unwrap_or(false) - } -} - -#[derive(Debug, Clone, PartialEq)] -pub enum FileType { - Pdf, - Word, - Excel, - Png, - Jpeg, - WebP, -} - -#[cfg(test)] -mod tests { - use super::*; - use rstest::*; - - - - #[rstest] - fn test_detect_from_bytes() -> Result<()> { - let pdf_data = b"%PDF-1.4\n"; - assert_eq!(FileTypeDetector::detect_from_bytes(pdf_data)?, FileType::Pdf); - - let png_data = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]; - assert_eq!(FileTypeDetector::detect_from_bytes(&png_data)?, FileType::Png); - - Ok(()) - } -} diff --git a/gb-utils/src/lib.rs b/gb-utils/src/lib.rs deleted file mode 100644 index 7d57583..0000000 --- a/gb-utils/src/lib.rs +++ /dev/null @@ -1,45 +0,0 @@ -use tracing::log::{info, Level, LevelFilter, Metadata, Record}; -use std::io::Write; -use tokio::io::{AsyncWriteExt}; -use tokio::net::TcpStream; - -// // A simple logger implementation that sends logs to Vector -// struct VectorLogger { -// stream: TcpStream, -// } - -// impl VectorLogger { -// async fn new(host: &str, port: u16) -> Result { -// let stream = TcpStream::connect(format!("{}:{}", host, port)).await?; -// Ok(VectorLogger { stream }) -// } -// } - -// impl log::Log for VectorLogger { -// fn enabled(&self, _metadata: &Metadata) -> bool { -// true -// } - -// fn log(&self, record: &Record) { -// let _ = self.log_async(record).await; -// } - -// fn flush(&self) {} -// } - -// impl VectorLogger { -// async fn log_async(&self, record: &Record) -> Result<(), std::io::Error> { -// let log_event = format!( -// "{{\"level\":\"{}\", \"message\":\"{}\", \"module\":\"{}\", \"file\":\"{}\", \"line\":{}}}\n", -// record.level(), -// record.args(), -// record.location().module_path(), -// record.location().file(), -// record.location().line() -// ); - -// self.stream.write_all(log_event.as_bytes()).await?; -// Ok(()) -// } -// } - diff --git a/gb-utils/src/processor.rs b/gb-utils/src/processor.rs deleted file mode 100644 index e69de29..0000000 diff --git a/gb-vm/Cargo.toml b/gb-vm/Cargo.toml deleted file mode 100644 index d41db73..0000000 --- a/gb-vm/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "gb-vm" -version = { workspace = true } -edition = { workspace = true } -authors = { workspace = true } -license = { workspace = true } - -[dependencies] -gb-core = { path = "../gb-core" } -async-trait = { workspace = true } -tokio = { workspace = true } -serde = { workspace = true } -serde_json = { workspace = true } -thiserror = { workspace = true } -tracing = { workspace = true } - -[dev-dependencies] -rstest = { workspace = true } -tokio-test = { workspace = true } -tempfile = { workspace = true } diff --git a/gb-vm/src/db.rs b/gb-vm/src/db.rs deleted file mode 100644 index 04376f5..0000000 --- a/gb-vm/src/db.rs +++ /dev/null @@ -1,65 +0,0 @@ -use anyhow::Result; -use minio_rs::client::{Client as MinioClient, ClientBuilder as MinioClientBuilder}; -use rdkafka::ClientConfig; -use rdkafka::producer::FutureProducer; -use redis::aio::ConnectionManager as RedisConnectionManager; -use sqlx::postgres::{PgPoolOptions, PgPool}; -use zitadel::api::v1::auth::AuthServiceClient; - -use crate::config::AppConfig; - -pub async fn init_postgres(config: &AppConfig) -> Result { - let pool = PgPoolOptions::new() - .max_connections(config.database.max_connections) - .connect(&config.database.url) - .await?; - - // Run migrations - sqlx::migrate!("./migrations") - .run(&pool) - .await?; - - Ok(pool) -} - -pub async fn init_redis(config: &AppConfig) -> Result { - let client = redis::Client::open(config.redis.url.as_str())?; - let connection_manager = RedisConnectionManager::new(client).await?; - - Ok(connection_manager) -} - -pub async fn init_kafka(config: &AppConfig) -> Result { - let producer: FutureProducer = ClientConfig::new() - .set("bootstrap.servers", &config.kafka.brokers) - .set("message.timeout.ms", "5000") - .create()?; - - Ok(producer) -} - -pub async fn init_zitadel(config: &AppConfig) -> Result> { - let channel = tonic::transport::Channel::from_shared(format!("https://{}", config.zitadel.domain))? - .connect() - .await?; - - let client = AuthServiceClient::new(channel); - - Ok(client) -} - -pub async fn init_minio(config: &AppConfig) -> Result { - let client = MinioClientBuilder::new() - .endpoint(&config.minio.endpoint) - .access_key(&config.minio.access_key) - .secret_key(&config.minio.secret_key) - .ssl(config.minio.use_ssl) - .build()?; - - // Ensure bucket exists - if !client.bucket_exists(&config.minio.bucket).await? { - client.make_bucket(&config.minio.bucket, None).await?; - } - - Ok(client) -} diff --git a/gb-vm/src/handlers.rs b/gb-vm/src/handlers.rs deleted file mode 100644 index e69de29..0000000 diff --git a/gb-vm/src/lib.rs b/gb-vm/src/lib.rs deleted file mode 100644 index e69de29..0000000 diff --git a/gb-vm/src/router.rs b/gb-vm/src/router.rs deleted file mode 100644 index 9cf1b17..0000000 --- a/gb-vm/src/router.rs +++ /dev/null @@ -1,4 +0,0 @@ -use actix_web::web; - -use crate::router; - diff --git a/infra.sh b/infra.sh deleted file mode 100644 index 6f18229..0000000 --- a/infra.sh +++ /dev/null @@ -1,276 +0,0 @@ -#!/bin/bash - -# Base directory -INSTALL_DIR="$HOME/server_binaries" -PID_DIR="$INSTALL_DIR/pids" -LOG_DIR="$INSTALL_DIR/logs" - -# Create directories if they don't exist -mkdir -p "$PID_DIR" -mkdir -p "$LOG_DIR" - -# Function to start all services -start_all() { - echo "Starting all services..." - - # Start PostgreSQL - if [ ! -f "$PID_DIR/postgres.pid" ]; then - echo "Starting PostgreSQL..." - if [ ! -d "$INSTALL_DIR/data/postgresql/base" ]; then - echo "Initializing PostgreSQL database..." - "$INSTALL_DIR/postgresql/bin/initdb" -D "$INSTALL_DIR/data/postgresql" - fi - - "$INSTALL_DIR/postgresql/bin/pg_ctl" -D "$INSTALL_DIR/data/postgresql" -l "$LOG_DIR/postgresql.log" start - echo $! > "$PID_DIR/postgres.pid" - - # Create database and user after a short delay - sleep 5 - "$INSTALL_DIR/postgresql/bin/createdb" -h localhost generalbots || echo "Database might already exist" - "$INSTALL_DIR/postgresql/bin/createuser" -h localhost gbuser || echo "User might already exist" - "$INSTALL_DIR/postgresql/bin/psql" -h localhost -c "ALTER USER gbuser WITH PASSWORD 'gbpassword';" || echo "Password might already be set" - "$INSTALL_DIR/postgresql/bin/psql" -h localhost -c "GRANT ALL PRIVILEGES ON DATABASE generalbots TO gbuser;" || echo "Privileges might already be granted" - - # Create database for Zitadel - "$INSTALL_DIR/postgresql/bin/createdb" -h localhost zitadel || echo "Zitadel database might already exist" - else - echo "PostgreSQL already running" - fi - - # Start Redis - if [ ! -f "$PID_DIR/redis.pid" ]; then - echo "Starting Redis..." - "$INSTALL_DIR/redis/src/redis-server" --daemonize yes --dir "$INSTALL_DIR/data/redis" --logfile "$LOG_DIR/redis.log" - echo $(pgrep -f "redis-server") > "$PID_DIR/redis.pid" - else - echo "Redis already running" - fi - - # Start Zitadel - if [ ! -f "$PID_DIR/zitadel.pid" ]; then - echo "Starting Zitadel..." - "$INSTALL_DIR/zitadel/zitadel" start --config "$INSTALL_DIR/config/zitadel.yaml" > "$LOG_DIR/zitadel.log" 2>&1 & - echo $! > "$PID_DIR/zitadel.pid" - else - echo "Zitadel already running" - fi - - # Start Stalwart Mail - if [ ! -f "$PID_DIR/stalwart.pid" ]; then - echo "Starting Stalwart Mail Server..." - "$INSTALL_DIR/stalwart/stalwart-mail" --config "$INSTALL_DIR/config/stalwart/config.toml" > "$LOG_DIR/stalwart.log" 2>&1 & - echo $! > "$PID_DIR/stalwart.pid" - else - echo "Stalwart Mail already running" - fi - - # Start MinIO - if [ ! -f "$PID_DIR/minio.pid" ]; then - echo "Starting MinIO..." - MINIO_ROOT_USER=minioadmin MINIO_ROOT_PASSWORD=minioadmin "$INSTALL_DIR/minio/minio" server "$INSTALL_DIR/data/minio" --console-address :9001 > "$LOG_DIR/minio.log" 2>&1 & - echo $! > "$PID_DIR/minio.pid" - else - echo "MinIO already running" - fi - - # Start Redpanda - if [ ! -f "$PID_DIR/redpanda.pid" ]; then - echo "Starting Redpanda..." - "$INSTALL_DIR/redpanda/bin/redpanda" --config "$INSTALL_DIR/config/redpanda.yaml" start > "$LOG_DIR/redpanda.log" 2>&1 & - echo $! > "$PID_DIR/redpanda.pid" - else - echo "Redpanda already running" - fi - - # Start Vector - if [ ! -f "$PID_DIR/vector.pid" ]; then - echo "Starting Vector..." - "$INSTALL_DIR/vector/bin/vector" --config "$INSTALL_DIR/config/vector.toml" > "$LOG_DIR/vector.log" 2>&1 & - echo $! > "$PID_DIR/vector.pid" - else - echo "Vector already running" - fi - - echo "All services started" - echo "To check status: ./$(basename $0) status" -} - -# Function to stop all services -stop_all() { - echo "Stopping all services..." - - # Stop Vector - if [ -f "$PID_DIR/vector.pid" ]; then - echo "Stopping Vector..." - kill -TERM $(cat "$PID_DIR/vector.pid") 2>/dev/null || echo "Vector was not running" - rm "$PID_DIR/vector.pid" 2>/dev/null - fi - - # Stop Redpanda - if [ -f "$PID_DIR/redpanda.pid" ]; then - echo "Stopping Redpanda..." - kill -TERM $(cat "$PID_DIR/redpanda.pid") 2>/dev/null || echo "Redpanda was not running" - rm "$PID_DIR/redpanda.pid" 2>/dev/null - fi - - # Stop MinIO - if [ -f "$PID_DIR/minio.pid" ]; then - echo "Stopping MinIO..." - kill -TERM $(cat "$PID_DIR/minio.pid") 2>/dev/null || echo "MinIO was not running" - rm "$PID_DIR/minio.pid" 2>/dev/null - fi - - # Stop Stalwart Mail - if [ -f "$PID_DIR/stalwart.pid" ]; then - echo "Stopping Stalwart Mail Server..." - kill -TERM $(cat "$PID_DIR/stalwart.pid") 2>/dev/null || echo "Stalwart Mail was not running" - rm "$PID_DIR/stalwart.pid" 2>/dev/null - fi - - # Stop Zitadel - if [ -f "$PID_DIR/zitadel.pid" ]; then - echo "Stopping Zitadel..." - kill -TERM $(cat "$PID_DIR/zitadel.pid") 2>/dev/null || echo "Zitadel was not running" - rm "$PID_DIR/zitadel.pid" 2>/dev/null - fi - - # Stop Redis - if [ -f "$PID_DIR/redis.pid" ]; then - echo "Stopping Redis..." - "$INSTALL_DIR/redis/src/redis-cli" shutdown 2>/dev/null || echo "Redis CLI not available" - kill -TERM $(cat "$PID_DIR/redis.pid") 2>/dev/null || echo "Redis was not running" - rm "$PID_DIR/redis.pid" 2>/dev/null - fi - - # Stop PostgreSQL - if [ -f "$PID_DIR/postgres.pid" ]; then - echo "Stopping PostgreSQL..." - "$INSTALL_DIR/postgresql/bin/pg_ctl" -D "$INSTALL_DIR/data/postgresql" stop 2>/dev/null || echo "PostgreSQL was not running" - rm "$PID_DIR/postgres.pid" 2>/dev/null - fi - - echo "All services stopped" -} - -# Function to check status of all services -check_status() { - echo "Checking status of all services..." - - # Check PostgreSQL - if [ -f "$PID_DIR/postgres.pid" ] && ps -p $(cat "$PID_DIR/postgres.pid") > /dev/null 2>&1; then - echo "PostgreSQL: Running (PID: $(cat "$PID_DIR/postgres.pid"))" - else - if pgrep -f "postgres" > /dev/null; then - echo "PostgreSQL: Running (PID: $(pgrep -f "postgres" | head -1))" - else - echo "PostgreSQL: Not running" - fi - fi - - # Check Redis - if [ -f "$PID_DIR/redis.pid" ] && ps -p $(cat "$PID_DIR/redis.pid") > /dev/null 2>&1; then - echo "Redis: Running (PID: $(cat "$PID_DIR/redis.pid"))" - else - if pgrep -f "redis-server" > /dev/null; then - echo "Redis: Running (PID: $(pgrep -f "redis-server" | head -1))" - else - echo "Redis: Not running" - fi - fi - - # Check Zitadel - if [ -f "$PID_DIR/zitadel.pid" ] && ps -p $(cat "$PID_DIR/zitadel.pid") > /dev/null 2>&1; then - echo "Zitadel: Running (PID: $(cat "$PID_DIR/zitadel.pid"))" - else - if pgrep -f "zitadel" > /dev/null; then - echo "Zitadel: Running (PID: $(pgrep -f "zitadel" | head -1))" - else - echo "Zitadel: Not running" - fi - fi - - # Check Stalwart Mail - if [ -f "$PID_DIR/stalwart.pid" ] && ps -p $(cat "$PID_DIR/stalwart.pid") > /dev/null 2>&1; then - echo "Stalwart Mail: Running (PID: $(cat "$PID_DIR/stalwart.pid"))" - else - if pgrep -f "stalwart-mail" > /dev/null; then - echo "Stalwart Mail: Running (PID: $(pgrep -f "stalwart-mail" | head -1))" - else - echo "Stalwart Mail: Not running" - fi - fi - - # Check MinIO - if [ -f "$PID_DIR/minio.pid" ] && ps -p $(cat "$PID_DIR/minio.pid") > /dev/null 2>&1; then - echo "MinIO: Running (PID: $(cat "$PID_DIR/minio.pid"))" - else - if pgrep -f "minio" > /dev/null; then - echo "MinIO: Running (PID: $(pgrep -f "minio" | head -1))" - else - echo "MinIO: Not running" - fi - fi - - # Check Redpanda - if [ -f "$PID_DIR/redpanda.pid" ] && ps -p $(cat "$PID_DIR/redpanda.pid") > /dev/null 2>&1; then - echo "Redpanda: Running (PID: $(cat "$PID_DIR/redpanda.pid"))" - else - if pgrep -f "redpanda" > /dev/null; then - echo "Redpanda: Running (PID: $(pgrep -f "redpanda" | head -1))" - else - echo "Redpanda: Not running" - fi - fi - - # Check Vector - if [ -f "$PID_DIR/vector.pid" ] && ps -p $(cat "$PID_DIR/vector.pid") > /dev/null 2>&1; then - echo "Vector: Running (PID: $(cat "$PID_DIR/vector.pid"))" - else - if pgrep -f "vector" > /dev/null; then - echo "Vector: Running (PID: $(pgrep -f "vector" | head -1))" - else - echo "Vector: Not running" - fi - fi -} - -# Function to restart all services -restart_all() { - echo "Restarting all services..." - stop_all - sleep 3 - start_all -} - -# Function to show logs -show_logs() { - echo "Available logs:" - ls -la "$LOG_DIR" - echo "" - echo "Use 'tail -f $LOG_DIR/[logfile]' to view a specific log" -} - -# Check command-line arguments -case "$1" in - start) - start_all - ;; - stop) - stop_all - ;; - restart) - restart_all - ;; - status) - check_status - ;; - logs) - show_logs - ;; - *) - echo "Usage: $0 {start|stop|restart|status|logs}" - exit 1 - ;; -esac - -exit 0 \ No newline at end of file diff --git a/install.sh b/install.sh deleted file mode 100755 index a9a355b..0000000 --- a/install.sh +++ /dev/null @@ -1,187 +0,0 @@ -#!/bin/bash -set -e - -# Create directories -echo "Creating directories..." -INSTALL_DIR="/opt/gbo" - - -mkdir -p "$INSTALL_DIR" -sudo chmod -R 777 "$INSTALL_DIR" - -mkdir -p "$INSTALL_DIR/bin" -mkdir -p "$INSTALL_DIR/bin/bot" -mkdir -p "$INSTALL_DIR/bin/mail" -mkdir -p "$INSTALL_DIR/bin/tabular" -mkdir -p "$INSTALL_DIR/bin/object" -mkdir -p "$INSTALL_DIR/bin/directory" -mkdir -p "$INSTALL_DIR/bin/alm" -mkdir -p "$INSTALL_DIR/bin/webserver" -mkdir -p "$INSTALL_DIR/bin/meeting" - -mkdir -p "$INSTALL_DIR/config" -mkdir -p "$INSTALL_DIR/data" -mkdir -p "$INSTALL_DIR/data/tabular" -mkdir -p "$INSTALL_DIR/data/object" -mkdir -p "$INSTALL_DIR/data/mail" -mkdir -p "$INSTALL_DIR/data/directory" -mkdir -p "$INSTALL_DIR/data/alm" -mkdir -p "$INSTALL_DIR/data/webserver" -mkdir -p "$INSTALL_DIR/data/meeting" - -mkdir -p "$INSTALL_DIR/logs" -mkdir -p "$INSTALL_DIR/certs" -mkdir -p "$INSTALL_DIR/config" -mkdir -p "$INSTALL_DIR/data" - -# Install system dependencies -echo "Installing system dependencies..." -sudo apt-get install -y \ - apt-transport-https \ - ca-certificates \ - curl \ - software-properties-common \ - gnupg \ - wget \ - unzip \ - tar \ - postgresql-client \ - redis-tools - -echo "System dependencies installed" - -# Download PostgreSQL binary (using the official package) -echo "Downloading PostgreSQL..." -if [ ! -d "$INSTALL_DIR/postgresql" ]; then - mkdir -p "$INSTALL_DIR/postgresql" - wget -O "$INSTALL_DIR/postgresql/postgresql.tar.gz" "https://get.enterprisedb.com/postgresql/postgresql-14.10-1-linux-x64-binaries.tar.gz" - tar -xzf "$INSTALL_DIR/postgresql/postgresql.tar.gz" -C "$INSTALL_DIR/postgresql" --strip-components=1 - rm "$INSTALL_DIR/postgresql/postgresql.tar.gz" - mkdir -p "$INSTALL_DIR/data/postgresql" -fi - - -# Download Zitadel binary -echo "Downloading Zitadel..." -if [ ! -d "$INSTALL_DIR/zitadel" ]; then - mkdir -p "$INSTALL_DIR/zitadel" - # Get latest release URL - ZITADEL_LATEST=$(curl -s https://api.github.com/repos/zitadel/zitadel/releases/latest | grep "browser_download_url.*linux_amd64.tar.gz" | cut -d '"' -f 4) - wget -O "$INSTALL_DIR/zitadel/zitadel.tar.gz" "$ZITADEL_LATEST" - tar -xzf "$INSTALL_DIR/zitadel/zitadel.tar.gz" -C "$INSTALL_DIR/zitadel" - rm "$INSTALL_DIR/zitadel/zitadel.tar.gz" - mkdir -p "$INSTALL_DIR/data/zitadel" - - # Create default Zitadel config - cat > "$INSTALL_DIR/config/zitadel.yaml" < "$INSTALL_DIR/config/redpanda.yaml" < "$INSTALL_DIR/config/vector.toml" < Self { + let minio = MinioConfig { + endpoint: env::var("MINIO_ENDPOINT").expect("MINIO_ENDPOINT not set"), + access_key: env::var("MINIO_ACCESS_KEY").expect("MINIO_ACCESS_KEY not set"), + secret_key: env::var("MINIO_SECRET_KEY").expect("MINIO_SECRET_KEY not set"), + use_ssl: env::var("MINIO_USE_SSL") + .unwrap_or_else(|_| "false".to_string()) + .parse() + .unwrap_or(false), + bucket: env::var("MINIO_BUCKET").expect("MINIO_BUCKET not set"), + }; + AppConfig { + minio, + server: ServerConfig { + host: env::var("SERVER_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()), + port: env::var("SERVER_PORT").ok() + .and_then(|p| p.parse().ok()) + .unwrap_or(8080), + }, + } + } +} +#[derive(Clone)] +pub struct MinioConfig { + pub endpoint: String, + pub access_key: String, + pub secret_key: String, + pub use_ssl: bool, + pub bucket: String, +} + + +// App state shared across all handlers +pub struct AppState { + pub minio_client: Option, + pub config: Option, + +} + +pub async fn init_minio(config: &AppConfig) -> Result { + let scheme = if config.minio.use_ssl { "https" } else { "http" }; + let base_url = format!("{}://{}", scheme, config.minio.endpoint); + let base_url = BaseUrl::from_str(&base_url)?; + let credentials = StaticProvider::new( + &config.minio.access_key, + &config.minio.secret_key, + None, + ); + + let minio_client = MinioClientBuilder::new(base_url) + .provider(Some(credentials)) + .build()?; + + Ok(minio_client) +} + #[post("/files/upload/{folder_path}")] pub async fn upload_file( folder_path: web::Path, @@ -78,19 +152,6 @@ pub async fn upload_file( ))) } -#[actix_web::post("/files/delete")] -pub async fn delete_file( - req: HttpRequest, - _state: web::Data, - _file_path: web::Json, -) -> Result { - let _user_id = extract_user_id(&req)?; - - Ok(create_response( - true, - Some("File deleted successfully".to_string()), - )) -} #[post("/files/list/{folder_path}")] diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..af73773 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,38 @@ + +use actix_web::{middleware, web, App, HttpServer}; +use gbserver::{init_minio, upload_file, AppConfig, AppState}; +use tracing_subscriber::fmt::format::FmtSpan; +use dotenv::dotenv; + + +#[actix_web::main] +async fn main() -> std::io::Result<()> { + dotenv().ok(); + + // Initialize tracing + tracing_subscriber::fmt() + .with_span_events(FmtSpan::CLOSE) + .init(); + + // log::set_max_level(LevelFilter::Info); + + let config = AppConfig::from_env(); + let minio_client = init_minio(&config).await.expect("Failed to initialize Minio"); + + let app_state = web::Data::new(AppState { + config: Some(config.clone()), + minio_client: Some(minio_client), + }); + + // Start HTTP server + HttpServer::new(move || { + App::new() + .wrap(middleware::Logger::default()) + .wrap(middleware::Compress::default()) + .app_data(app_state.clone()) + .service(upload_file) // Uncomment and import or define upload_file below + }) + .bind((config.server.host.clone(), config.server.port))? + .run() + .await +} diff --git a/gb-auth/src/handlers/auth_handler.rs b/src/models.rs similarity index 100% rename from gb-auth/src/handlers/auth_handler.rs rename to src/models.rs diff --git a/gb-llm/.gbdialog/ai/analyze-customer-sentiment.bas b/src/prompts/ai/analyze-customer-sentiment.bas similarity index 100% rename from gb-llm/.gbdialog/ai/analyze-customer-sentiment.bas rename to src/prompts/ai/analyze-customer-sentiment.bas diff --git a/gb-llm/.gbdialog/analytics/sales-performance.bas b/src/prompts/analytics/sales-performance.bas similarity index 100% rename from gb-llm/.gbdialog/analytics/sales-performance.bas rename to src/prompts/analytics/sales-performance.bas diff --git a/gb-llm/.gbdialog/business/send-proposal.bas b/src/prompts/business/send-proposal.bas similarity index 100% rename from gb-llm/.gbdialog/business/send-proposal.bas rename to src/prompts/business/send-proposal.bas diff --git a/gb-llm/.gbdialog/calendar/schedule-meeting.bas b/src/prompts/calendar/schedule-meeting.bas similarity index 100% rename from gb-llm/.gbdialog/calendar/schedule-meeting.bas rename to src/prompts/calendar/schedule-meeting.bas diff --git a/gb-llm/.gbdialog/communication/keyword-sendmail.bas b/src/prompts/communication/keyword-sendmail.bas similarity index 100% rename from gb-llm/.gbdialog/communication/keyword-sendmail.bas rename to src/prompts/communication/keyword-sendmail.bas diff --git a/gb-llm/.gbdialog/conversations/meeting-assistant.bas b/src/prompts/conversations/meeting-assistant.bas similarity index 100% rename from gb-llm/.gbdialog/conversations/meeting-assistant.bas rename to src/prompts/conversations/meeting-assistant.bas diff --git a/gb-llm/.gbdialog/core/system-prompt.bas b/src/prompts/core/system-prompt.bas similarity index 100% rename from gb-llm/.gbdialog/core/system-prompt.bas rename to src/prompts/core/system-prompt.bas diff --git a/gb-llm/.gbdialog/crm/update-opportunity.bas b/src/prompts/crm/update-opportunity.bas similarity index 100% rename from gb-llm/.gbdialog/crm/update-opportunity.bas rename to src/prompts/crm/update-opportunity.bas diff --git a/gb-llm/.gbdialog/files/search-documents.bas b/src/prompts/files/search-documents.bas similarity index 100% rename from gb-llm/.gbdialog/files/search-documents.bas rename to src/prompts/files/search-documents.bas diff --git a/gb-llm/.gbdialog/geral.bas b/src/prompts/geral.bas similarity index 100% rename from gb-llm/.gbdialog/geral.bas rename to src/prompts/geral.bas diff --git a/gb-llm/.gbdialog/groups/create-workspace.bas b/src/prompts/groups/create-workspace.bas similarity index 100% rename from gb-llm/.gbdialog/groups/create-workspace.bas rename to src/prompts/groups/create-workspace.bas diff --git a/gb-llm/.gbdialog/health/system-check.bas b/src/prompts/health/system-check.bas similarity index 100% rename from gb-llm/.gbdialog/health/system-check.bas rename to src/prompts/health/system-check.bas diff --git a/gb-llm/.gbdialog/scheduled/basic-check.bas b/src/prompts/scheduled/basic-check.bas similarity index 100% rename from gb-llm/.gbdialog/scheduled/basic-check.bas rename to src/prompts/scheduled/basic-check.bas diff --git a/gb-llm/.gbdialog/security/access-review.bas b/src/prompts/security/access-review.bas similarity index 100% rename from gb-llm/.gbdialog/security/access-review.bas rename to src/prompts/security/access-review.bas diff --git a/gb-llm/.gbdialog/tools/on-receive-email.bas b/src/prompts/tools/on-receive-email.bas similarity index 100% rename from gb-llm/.gbdialog/tools/on-receive-email.bas rename to src/prompts/tools/on-receive-email.bas diff --git a/src/scripts/check-space.sh b/src/scripts/check-space.sh new file mode 100644 index 0000000..c19f9ab --- /dev/null +++ b/src/scripts/check-space.sh @@ -0,0 +1,29 @@ +df -h +printf "%-20s %-10s %-10s %-10s %-6s %s\n" "CONTAINER" "USED" "AVAIL" "TOTAL" "USE%" "MOUNT" +for container in $(lxc list -c n --format csv); do + disk_info=$(lxc exec $container -- df -h / --output=used,avail,size,pcent | tail -n 1) + printf "%-20s %s\n" "$container" "$disk_info" +done + +#!/bin/bash + +# Directory to analyze +TARGET_DIR="/opt/gbo/tenants/pragmatismo" + +echo "Calculating sizes for directories in $TARGET_DIR..." +echo "" + +# Check if directory exists +if [ ! -d "$TARGET_DIR" ]; then + echo "Error: Directory $TARGET_DIR does not exist" + exit 1 +fi + +# Get the size of each subdirectory +echo "Directory Size Report:" +echo "----------------------" +du -h --max-depth=1 "$TARGET_DIR" | sort -hr | awk -F'\t' '{printf "%-50s %s\n", $2, $1}' + +echo "" +echo "Total size:" +du -sh "$TARGET_DIR" \ No newline at end of file diff --git a/src/scripts/cleaner.sh b/src/scripts/cleaner.sh new file mode 100644 index 0000000..4ce4871 --- /dev/null +++ b/src/scripts/cleaner.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +# Cleanup script for Ubuntu Server and LXC containers +# Run with sudo privileges + +echo "Starting system cleanup..." + +### Host System Cleanup ### +echo -e "\n[ HOST SYSTEM CLEANUP ]" + +# Package manager cache +echo "Cleaning package cache..." +apt clean +apt autoclean +apt autoremove -y + +# Journal logs +echo "Cleaning journal logs..." +journalctl --vacuum-time=2d 2>/dev/null + +# Temporary files +echo "Cleaning temporary files..." +rm -rf /tmp/* /var/tmp/* + +# Thumbnail cache +echo "Cleaning thumbnail cache..." +rm -rf ~/.cache/thumbnails/* /root/.cache/thumbnails/* + +# DNS cache +echo "Flushing DNS cache..." +systemd-resolve --flush-caches 2>/dev/null || true + +# Old kernels (keep 2 latest) +echo "Removing old kernels..." +apt purge -y $(dpkg -l | awk '/^ii linux-image-*/{print $2}' | grep -v $(uname -r) | head -n -2) 2>/dev/null + +# Crash reports +echo "Clearing crash reports..." +rm -f /var/crash/* + +### LXC Containers Cleanup ### +echo -e "\n[ LXC CONTAINERS CLEANUP ]" + +# Check if LXC is installed +if command -v lxc >/dev/null 2>&1; then + for container in $(lxc list -c n --format csv | grep -v "^$"); do + echo -e "\nCleaning container: $container" + + # Execute cleanup commands in container + lxc exec "$container" -- bash -c " + echo 'Cleaning package cache...' + apt clean && apt autoclean && apt autoremove -y + + echo 'Cleaning temporary files...' + rm -rf /tmp/* /var/tmp/* + + echo 'Cleaning logs...' + journalctl --vacuum-time=1d 2>/dev/null || true + + echo 'Cleaning thumbnail cache...' + rm -rf /home/*/.cache/thumbnails/* /root/.cache/thumbnails/* + " 2>/dev/null + done +else + echo "LXC not installed, skipping container cleanup." +fi + +echo -e "\nCleanup completed!" \ No newline at end of file diff --git a/gb-infra/src/templates/opt/gbo/tenants/default/shared/scripts/limits.sh b/src/scripts/set-limits.sh similarity index 97% rename from gb-infra/src/templates/opt/gbo/tenants/default/shared/scripts/limits.sh rename to src/scripts/set-limits.sh index cac722a..e0002cc 100644 --- a/gb-infra/src/templates/opt/gbo/tenants/default/shared/scripts/limits.sh +++ b/src/scripts/set-limits.sh @@ -12,7 +12,7 @@ declare -A container_limits=( ["*bot*"]="2048MB:50ms/100ms" ["*meeting*"]="1024MB:20ms/100ms" ["*alm*"]="512MB:20ms/100ms" - ["*alm-ci*"]="1024MB:20ms/100ms" + ["*alm-ci*"]="4096MB:80ms/100ms" ) # Default values (for containers that don't match any pattern) diff --git a/gb-infra/src/templates/opt/gbo/tenants/default/shared/scripts/set-size-5GB.sh b/src/scripts/set-size-5GB.sh similarity index 100% rename from gb-infra/src/templates/opt/gbo/tenants/default/shared/scripts/set-size-5GB.sh rename to src/scripts/set-size-5GB.sh diff --git a/gb-infra/src/templates/opt/gbo/tenants/default/shared/scripts/startup.sh b/src/scripts/startup.sh similarity index 100% rename from gb-infra/src/templates/opt/gbo/tenants/default/shared/scripts/startup.sh rename to src/scripts/startup.sh diff --git a/gb-infra/src/templates/opt/gbo/tenants/default/alm-ci/alm-ci.sh b/src/templates/opt/gbo/tenants/default/alm-ci/alm-ci.sh similarity index 97% rename from gb-infra/src/templates/opt/gbo/tenants/default/alm-ci/alm-ci.sh rename to src/templates/opt/gbo/tenants/default/alm-ci/alm-ci.sh index e80a72c..7799e88 100644 --- a/gb-infra/src/templates/opt/gbo/tenants/default/alm-ci/alm-ci.sh +++ b/src/templates/opt/gbo/tenants/default/alm-ci/alm-ci.sh @@ -73,20 +73,25 @@ export OPENCV4NODEJS_DISABLE_AUTOBUILD=1 export OPENCV_LIB_DIR=/usr/lib/x86_64-linux-gnu sudo apt install -y curl gnupg ca-certificates git -sudo apt-get install -y \ - apt-transport-https \ - software-properties-common \ - gnupg \ - wget \ - unzip \ - tar - # Install Node.js 22.x curl -fsSL https://deb.nodesource.com/setup_22.x | sudo bash - sudo apt install -y nodejs # Install rust 1.85 +apt-get install -y libssl-dev pkg-config +sudo apt-get install -y \ + apt-transport-https \ + software-properties-common \ + gnupg \ + cmake \ + build-essential \ + clang \ + libclang-dev \ + libz-dev \ + libssl-dev \ + pkg-config + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain 1.85.1 -y source ~/.cargo/env rustc --version diff --git a/gb-infra/src/templates/opt/gbo/tenants/default/alm/alm.sh b/src/templates/opt/gbo/tenants/default/alm/alm.sh similarity index 100% rename from gb-infra/src/templates/opt/gbo/tenants/default/alm/alm.sh rename to src/templates/opt/gbo/tenants/default/alm/alm.sh diff --git a/gb-infra/src/templates/opt/gbo/tenants/default/bot/bot.sh b/src/templates/opt/gbo/tenants/default/bot/bot.sh similarity index 100% rename from gb-infra/src/templates/opt/gbo/tenants/default/bot/bot.sh rename to src/templates/opt/gbo/tenants/default/bot/bot.sh diff --git a/gb-infra/src/templates/opt/gbo/tenants/default/desktop/desktop.sh b/src/templates/opt/gbo/tenants/default/desktop/desktop.sh similarity index 100% rename from gb-infra/src/templates/opt/gbo/tenants/default/desktop/desktop.sh rename to src/templates/opt/gbo/tenants/default/desktop/desktop.sh diff --git a/gb-infra/src/templates/opt/gbo/tenants/default/directory/directory.sh b/src/templates/opt/gbo/tenants/default/directory/directory.sh similarity index 100% rename from gb-infra/src/templates/opt/gbo/tenants/default/directory/directory.sh rename to src/templates/opt/gbo/tenants/default/directory/directory.sh diff --git a/gb-infra/src/templates/opt/gbo/tenants/default/drive/drive.sh b/src/templates/opt/gbo/tenants/default/drive/drive.sh similarity index 100% rename from gb-infra/src/templates/opt/gbo/tenants/default/drive/drive.sh rename to src/templates/opt/gbo/tenants/default/drive/drive.sh diff --git a/gb-infra/src/templates/opt/gbo/tenants/default/email/email.sh b/src/templates/opt/gbo/tenants/default/email/email.sh similarity index 100% rename from gb-infra/src/templates/opt/gbo/tenants/default/email/email.sh rename to src/templates/opt/gbo/tenants/default/email/email.sh diff --git a/gb-infra/src/templates/opt/gbo/tenants/default/meeting/meeting.sh b/src/templates/opt/gbo/tenants/default/meeting/meeting.sh similarity index 100% rename from gb-infra/src/templates/opt/gbo/tenants/default/meeting/meeting.sh rename to src/templates/opt/gbo/tenants/default/meeting/meeting.sh diff --git a/gb-infra/src/templates/opt/gbo/tenants/default/prompt.txt b/src/templates/opt/gbo/tenants/default/prompt.txt similarity index 100% rename from gb-infra/src/templates/opt/gbo/tenants/default/prompt.txt rename to src/templates/opt/gbo/tenants/default/prompt.txt diff --git a/gb-infra/src/templates/opt/gbo/tenants/default/proxy/proxy.sh b/src/templates/opt/gbo/tenants/default/proxy/proxy.sh similarity index 100% rename from gb-infra/src/templates/opt/gbo/tenants/default/proxy/proxy.sh rename to src/templates/opt/gbo/tenants/default/proxy/proxy.sh diff --git a/gb-infra/src/templates/opt/gbo/tenants/default/social/.sh b/src/templates/opt/gbo/tenants/default/social/.sh similarity index 100% rename from gb-infra/src/templates/opt/gbo/tenants/default/social/.sh rename to src/templates/opt/gbo/tenants/default/social/.sh diff --git a/gb-infra/src/templates/opt/gbo/tenants/default/system/system.sh b/src/templates/opt/gbo/tenants/default/system/system.sh similarity index 100% rename from gb-infra/src/templates/opt/gbo/tenants/default/system/system.sh rename to src/templates/opt/gbo/tenants/default/system/system.sh diff --git a/gb-infra/src/templates/opt/gbo/tenants/default/table-editor/table-editor.sh b/src/templates/opt/gbo/tenants/default/table-editor/table-editor.sh similarity index 100% rename from gb-infra/src/templates/opt/gbo/tenants/default/table-editor/table-editor.sh rename to src/templates/opt/gbo/tenants/default/table-editor/table-editor.sh diff --git a/gb-infra/src/templates/opt/gbo/tenants/default/tables/tables.sh b/src/templates/opt/gbo/tenants/default/tables/tables.sh similarity index 100% rename from gb-infra/src/templates/opt/gbo/tenants/default/tables/tables.sh rename to src/templates/opt/gbo/tenants/default/tables/tables.sh diff --git a/gb-infra/src/templates/opt/gbo/tenants/default/webmail/webmail.sh b/src/templates/opt/gbo/tenants/default/webmail/webmail.sh similarity index 100% rename from gb-infra/src/templates/opt/gbo/tenants/default/webmail/webmail.sh rename to src/templates/opt/gbo/tenants/default/webmail/webmail.sh diff --git a/gb-testing/tests/integration_email_list.rs b/src/tests/integration_email_list.rs similarity index 100% rename from gb-testing/tests/integration_email_list.rs rename to src/tests/integration_email_list.rs diff --git a/gb-testing/tests/integration_file_list_test.rs b/src/tests/integration_file_list_test.rs similarity index 100% rename from gb-testing/tests/integration_file_list_test.rs rename to src/tests/integration_file_list_test.rs diff --git a/gb-testing/tests/integration_file_upload_test.rs b/src/tests/integration_file_upload_test.rs similarity index 100% rename from gb-testing/tests/integration_file_upload_test.rs rename to src/tests/integration_file_upload_test.rs