From 4d01ecddd77fc3bc31571111ecf9cfa5bfe0dd65 Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Tue, 26 May 2026 12:39:06 +0100 Subject: [PATCH 01/28] chore: ignore local workspace files Remove the VS Code workspace file from repository tracking while leaving local workspace files ignored. --- .gitignore | 1 + memory-map.code-workspace | 18 ------------------ 2 files changed, 1 insertion(+), 18 deletions(-) delete mode 100644 memory-map.code-workspace diff --git a/.gitignore b/.gitignore index 5a3e99a..4859914 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ data/ .codex/worktrees/ .pre-commit-config.yaml .playwright-mcp/ +*.code-workspace diff --git a/memory-map.code-workspace b/memory-map.code-workspace deleted file mode 100644 index 26369f3..0000000 --- a/memory-map.code-workspace +++ /dev/null @@ -1,18 +0,0 @@ -{ - "folders": [ - { - "path": "." - } - ], - "settings": { - "rust-analyzer.procMacro.ignored": { - "leptos_macro": [ - // optional: - // "component", - "server" - ] - }, - "rust-analyzer.cargo.features": "all", - "rust-analyzer.rustfmt.overrideCommand": ["leptosfmt", "--stdin", "--rustfmt"] - } -} From 454fbcc030e1840cc418edb6869616a9805e0286 Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Tue, 26 May 2026 13:32:20 +0100 Subject: [PATCH 02/28] chore: remove test output caching Simplify the just test recipe to run cargo test directly. Remove the obsolete test-output cache ignore entry and update contributor docs. --- .gitignore | 1 - CONTRIBUTING.md | 10 +--------- README.md | 2 +- justfile | 44 +++++--------------------------------------- 4 files changed, 7 insertions(+), 50 deletions(-) diff --git a/.gitignore b/.gitignore index 4859914..3662722 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ target/ data/ .env .direnv/ -.cache/test-output/ .claude/worktrees/ .codex/worktrees/ .pre-commit-config.yaml diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 75ccc74..3da8f33 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,19 +28,11 @@ just check # Run cargo check just clippy # Run Clippy with warnings as errors just deny # Check dependency licenses and advisories just doc # Build docs and run ASCII/link checks -just test # Run tests with cached output +just test # Run tests just frontend-build # Build the Trunk frontend just verify # Run the full verification suite ``` -## Tests - -`just test` caches command output under `.cache/test-output/`. The cache key is -based on tracked file contents and the test arguments. - -After creating a new source or test file, run `git add ` once so the cache -can see it. Use `just clean` to clear build artifacts and cached test output. - ## Documentation And Text Source and Markdown documentation are kept ASCII-only. Use plain ASCII diff --git a/README.md b/README.md index d8a8c0c..46f3f00 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ The project uses [Just](https://github.com/casey/just) as a task runner. - `just clippy`: Run Clippy with warnings treated as errors. - `just deny`: Check Rust dependencies with `cargo-deny`. - `just doc`: Build documentation with warnings treated as errors and run ASCII/link checks. -- `just test`: Run the workspace test suite with cached output. +- `just test`: Run the workspace test suite. - `just frontend-build`: Build the frontend with Trunk. - `just verify`: Run the full verification suite before submitting a PR. - `just regenerate-schema`: Introspect the backend and update the frontend GraphQL schema. diff --git a/justfile b/justfile index 0855da7..152a191 100644 --- a/justfile +++ b/justfile @@ -117,53 +117,19 @@ cargo *args: fi {{ direnv_prefix }} cargo "$@" -# Run tests with output caching. Re-runs only when tracked source files change. +# Run tests. [positional-arguments] test *args: #!/usr/bin/env bash set -euo pipefail - mkdir -p .cache/test-output - ARGS=$(printf '%q ' "$@") - CONTENT_HASH=$(git ls-files -z | xargs -0 md5sum 2>/dev/null | md5sum | cut -c1-32 || true) - CACHE_KEY=$(echo "${ARGS}:${CONTENT_HASH}" | md5sum | cut -c1-12) - OUTPUT_FILE=".cache/test-output/test-output-${CACHE_KEY}.txt" - STATUS_FILE=".cache/test-output/test-output-${CACHE_KEY}.status" - if [ -s "$OUTPUT_FILE" ] && [ -s "$STATUS_FILE" ]; then - echo "No source changes, proceeding to print cached test outputs:" - (trap '' PIPE; cat "$OUTPUT_FILE") - echo "Finished printing cached test outputs." - exit "$(cat "$STATUS_FILE")" - else - echo "No cached outputs currently present, proceeding to run tests:" - TEMP_FILE="${OUTPUT_FILE}.tmp" - TEMP_STATUS_FILE="${STATUS_FILE}.tmp" - rm -f "$TEMP_FILE" - rm -f "$TEMP_STATUS_FILE" - trap 'rm -f "$TEMP_FILE" "$TEMP_STATUS_FILE"' INT TERM HUP - RC=0 - if [ "$#" -eq 0 ]; then - set -- --workspace --all-features - fi - {{ direnv_prefix }} cargo test "$@" > "$TEMP_FILE" 2>&1 || RC=$? - if [ ! -s "$TEMP_FILE" ]; then - rm -f "$TEMP_FILE" - rm -f "$TEMP_STATUS_FILE" - exit "${RC:-1}" - fi - printf '%s\n' "$RC" > "$TEMP_STATUS_FILE" - mv "$TEMP_FILE" "$OUTPUT_FILE" - mv "$TEMP_STATUS_FILE" "$STATUS_FILE" - (trap '' PIPE; cat "$OUTPUT_FILE") - echo "Test outputs and exit status saved to cache files:" - echo " output: $OUTPUT_FILE" - echo " status: $STATUS_FILE" - exit "$RC" + if [ "$#" -eq 0 ]; then + set -- --workspace --all-features fi + {{ direnv_prefix }} cargo test "$@" -# Remove build artifacts and test cache. +# Remove build artifacts. clean: {{ direnv_prefix }} cargo clean - rm -rf .cache/test-output/ # Check licenses and advisories with cargo-deny. deny: From 8c7d965feb9b410bd718846624db815f6502b0f6 Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Tue, 26 May 2026 20:07:08 +0100 Subject: [PATCH 03/28] Add RustFS package to devenv --- devenv/flake.lock | 39 ++++++++++++++++++++++++++++ devenv/flake.nix | 22 +++++++++++++++- devenv/packages/rustfs.nix | 53 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 devenv/packages/rustfs.nix diff --git a/devenv/flake.lock b/devenv/flake.lock index b8c3ffa..60fa3bd 100644 --- a/devenv/flake.lock +++ b/devenv/flake.lock @@ -206,6 +206,8 @@ "nixpkgs-minio": "nixpkgs-minio", "nixpkgs-unstable": "nixpkgs-unstable", "process-compose-flake": "process-compose-flake", + "rust-overlay": "rust-overlay", + "rustfs-src": "rustfs-src", "services-flake": "services-flake", "systems": "systems", "treefmt-nix": "treefmt-nix" @@ -245,6 +247,43 @@ "type": "github" } }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1779765539, + "narHash": "sha256-2QxuD5gJcfCFsnqv54LGEHQKvd+K+DW/ecERwAvuA7w=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "09889992e640378f7008c3302b9d4892579df610", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "rustfs-src": { + "flake": false, + "locked": { + "lastModified": 1779289387, + "narHash": "sha256-1GBOq6PUk/FmvgL8otFHBMS+gT5obiGDXnEVYhVbQuw=", + "owner": "rustfs", + "repo": "rustfs", + "rev": "dcbffb084f9a85b7362f2c146e16f749d2c81179", + "type": "github" + }, + "original": { + "owner": "rustfs", + "ref": "1.0.0-beta.4", + "repo": "rustfs", + "type": "github" + } + }, "services-flake": { "locked": { "lastModified": 1765168239, diff --git a/devenv/flake.nix b/devenv/flake.nix index e5e4ecc..9faf4bd 100644 --- a/devenv/flake.nix +++ b/devenv/flake.nix @@ -8,6 +8,14 @@ # @todo Look into https://github.com/OpenMaxIO/openmaxio-object-browser or https://github.com/rustfs/rustfs nixpkgs-minio.url = "github:NixOS/nixpkgs/e6f23dc08d3624daab7094b701aa3954923c6bbb"; nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable"; + rustfs-src = { + url = "github:rustfs/rustfs/1.0.0-beta.4"; + flake = false; + }; + rust-overlay = { + url = "github:oxalica/rust-overlay"; + inputs.nixpkgs.follows = "nixpkgs"; + }; fenix = { url = "github:nix-community/fenix"; inputs.nixpkgs.follows = "nixpkgs"; @@ -73,6 +81,14 @@ # For Leptos targets.wasm32-unknown-unknown.stable.rust-std ]; + rustfsPkgs = pkgs.extend (import inputs.rust-overlay); + rustfsToolchain = rustfsPkgs.rust-bin.stable.latest.default.override { + extensions = [ "rust-src" ]; + }; + rustfsRustPlatform = pkgs.makeRustPlatform { + cargo = rustfsToolchain; + rustc = rustfsToolchain; + }; treefmtEval = inputs.treefmt-nix.lib.evalModule pkgs { # Cargo.toml lives at the repo root (one level above devenv/). @@ -165,10 +181,14 @@ }; overlayAttrs = { - inherit (config.packages) rustToolchain; + inherit (config.packages) rustToolchain rustfs; }; packages.rustToolchain = rustToolchain; + packages.rustfs = pkgs.callPackage ./packages/rustfs.nix { + rustPlatform = rustfsRustPlatform; + rustfsSrc = inputs.rustfs-src; + }; # `process-compose.foo` will add a flake package output called "foo". # Therefore, this will add a default package that you can build using diff --git a/devenv/packages/rustfs.nix b/devenv/packages/rustfs.nix new file mode 100644 index 0000000..9420e77 --- /dev/null +++ b/devenv/packages/rustfs.nix @@ -0,0 +1,53 @@ +{ + lib, + rustPlatform, + rustfsSrc, + openssl, + pkg-config, + protobuf, +}: + +rustPlatform.buildRustPackage rec { + pname = "rustfs"; + version = "1.0.0-beta.4"; + + src = rustfsSrc; + + cargoLock = { + lockFile = "${src}/Cargo.lock"; + outputHashes = { + "mysql_async-0.36.1" = "sha256-DFE+VEK4D6Dl8/PcPJ53UaZ0AbVHD6Kc3dKJcA1ZZrs="; + "pageant-0.2.0" = "sha256-laML4qIZBA4irXXWXPx7NyTGpEDCHoSalkKwcPSZOJY="; + "russh-0.60.3" = "sha256-laML4qIZBA4irXXWXPx7NyTGpEDCHoSalkKwcPSZOJY="; + "russh-cryptovec-0.60.3" = "sha256-laML4qIZBA4irXXWXPx7NyTGpEDCHoSalkKwcPSZOJY="; + "russh-util-0.52.0" = "sha256-laML4qIZBA4irXXWXPx7NyTGpEDCHoSalkKwcPSZOJY="; + "s3s-0.14.0-dev" = "sha256-J4EOD90XsvR0B8wJ+5j2v6pQXSVi5fs36j+Ge21Ky+c="; + }; + }; + + nativeBuildInputs = [ + pkg-config + protobuf + ]; + + buildInputs = [ + openssl + ]; + + cargoBuildFlags = [ + "--package" + "rustfs" + ]; + + PROTOC = "${protobuf}/bin/protoc"; + RUSTFLAGS = "--cfg tokio_unstable"; + + doCheck = false; + + meta = { + description = "High-performance S3-compatible object storage"; + homepage = "https://rustfs.com"; + license = lib.licenses.asl20; + mainProgram = "rustfs"; + }; +} From d57b8d1be8707b352fd93282965d08597198ec62 Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Tue, 26 May 2026 20:07:45 +0100 Subject: [PATCH 04/28] Ignore Nix build result symlinks --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 3662722..6ede1cb 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ target/ data/ .env .direnv/ +/result +/result-* .claude/worktrees/ .codex/worktrees/ .pre-commit-config.yaml From c44c4650cbc0fd7e7e41c0348a827c5cf25b9c30 Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Tue, 26 May 2026 21:44:34 +0100 Subject: [PATCH 05/28] Replace services-flake services with RustFS --- .env.example | 6 +- .gitignore | 5 +- README.md | 11 +- devenv/flake.lock | 33 ----- devenv/flake.nix | 317 +++++++++++++++++++++++++++++++++++----------- justfile | 6 +- 6 files changed, 258 insertions(+), 120 deletions(-) diff --git a/.env.example b/.env.example index ca10aa7..8c75165 100644 --- a/.env.example +++ b/.env.example @@ -10,9 +10,9 @@ SMTP_PASS=password SMTP_FROM=noreply@example.com COOKIE_SECRET=supersecretkeymustbeatleast64byteslongforsecurityreasons1234567890 FRONTEND_URL=http://localhost:3000 -MINIO_ACCESS_KEY=minioadmin -MINIO_SECRET_KEY=minioadmin -MINIO_URL=http://localhost:9000/ +MINIO_ACCESS_KEY=memorymapdev +MINIO_SECRET_KEY=memorymapdevsecret +MINIO_URL=http://127.0.0.1:9000/ S3_BUCKET_NAME=memory-map SERVER_HOST=127.0.0.1 SERVER_PORT=8000 diff --git a/.gitignore b/.gitignore index 6ede1cb..89dd2b7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ target/ -data/ +data/minio1/ +data/pg1/ +data/postgres/ +data/rustfs/ .env .direnv/ /result diff --git a/README.md b/README.md index 46f3f00..94650a7 100644 --- a/README.md +++ b/README.md @@ -70,10 +70,10 @@ You can optionally configure the build mode and other settings by editing `.env` just servers ``` -MinIO object storage becomes available at: [http://localhost:9001/login](http://localhost:9001/login) +RustFS S3-compatible storage becomes available at: [http://localhost:9001/login](http://localhost:9001/login) -- **Username:** `minioadmin` -- **Password:** `minioadmin` +- **Username:** `memorymapdev` +- **Password:** `memorymapdevsecret` ### 5. Start backend @@ -99,7 +99,8 @@ Frontend app: [http://localhost:3000/](http://localhost:3000/) The project uses [Just](https://github.com/casey/just) as a task runner. -- `just servers`: Start PostgreSQL and MinIO via Nix. +- `just servers`: Start PostgreSQL and RustFS via Nix. +- `just clean-service-state`: Remove local PostgreSQL and storage service state. - `just backend`: Start the Axum backend with hot-reloading (via Bacon). - `just frontend`: Start the Leptos frontend (via Trunk). - `just fmt`: Format Rust, Nix, Markdown, YAML, and TOML files. @@ -121,7 +122,7 @@ The project uses [Just](https://github.com/casey/just) as a task runner. | | [UnoCSS](https://unocss.dev/) | | Backend | [Axum](https://github.com/tokio-rs/axum) | | | [GraphQL](https://graphql.org) | -| Storage | [MinIO](https://min.io) | +| Storage | [RustFS](https://rustfs.com/) | | Database | [PostgreSQL](https://www.postgresql.org) | | Development Environment | [Nix package manager](https://nixos.org) | | | [nix-direnv](https://github.com/nix-community/nix-direnv) | diff --git a/devenv/flake.lock b/devenv/flake.lock index 60fa3bd..1356f97 100644 --- a/devenv/flake.lock +++ b/devenv/flake.lock @@ -149,22 +149,6 @@ "type": "github" } }, - "nixpkgs-minio": { - "locked": { - "lastModified": 1750111231, - "narHash": "sha256-3a7Tha/RwYlzH/v3PJrG7+HjOj4c6YOv2K8sqdGsHVQ=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "e6f23dc08d3624daab7094b701aa3954923c6bbb", - "type": "github" - }, - "original": { - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "e6f23dc08d3624daab7094b701aa3954923c6bbb", - "type": "github" - } - }, "nixpkgs-unstable": { "locked": { "lastModified": 1767379071, @@ -203,12 +187,10 @@ "flake-parts": "flake-parts", "git-hooks": "git-hooks", "nixpkgs": "nixpkgs", - "nixpkgs-minio": "nixpkgs-minio", "nixpkgs-unstable": "nixpkgs-unstable", "process-compose-flake": "process-compose-flake", "rust-overlay": "rust-overlay", "rustfs-src": "rustfs-src", - "services-flake": "services-flake", "systems": "systems", "treefmt-nix": "treefmt-nix" } @@ -284,21 +266,6 @@ "type": "github" } }, - "services-flake": { - "locked": { - "lastModified": 1765168239, - "narHash": "sha256-NZ7H4lbbytPNwe4ZyvovycuS1BMBFwJrptgX7NiF+F0=", - "owner": "juspay", - "repo": "services-flake", - "rev": "8b6244f2b310f229568d5cadf7dfcb5ebe6f8bda", - "type": "github" - }, - "original": { - "owner": "juspay", - "repo": "services-flake", - "type": "github" - } - }, "systems": { "locked": { "lastModified": 1681028828, diff --git a/devenv/flake.nix b/devenv/flake.nix index 9faf4bd..3d3a8b1 100644 --- a/devenv/flake.nix +++ b/devenv/flake.nix @@ -3,10 +3,6 @@ inputs = { nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1"; - # We're using this version as newer versions removed useful features - # https://www.reddit.com/r/selfhosted/comments/1kva3pw/avoid_minio_developers_introduce_trojan_horse/ - # @todo Look into https://github.com/OpenMaxIO/openmaxio-object-browser or https://github.com/rustfs/rustfs - nixpkgs-minio.url = "github:NixOS/nixpkgs/e6f23dc08d3624daab7094b701aa3954923c6bbb"; nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable"; rustfs-src = { url = "github:rustfs/rustfs/1.0.0-beta.4"; @@ -27,7 +23,6 @@ flake-parts.url = "github:hercules-ci/flake-parts"; systems.url = "github:nix-systems/default"; process-compose-flake.url = "github:Platonic-Systems/process-compose-flake"; - services-flake.url = "github:juspay/services-flake"; treefmt-nix = { url = "github:numtide/treefmt-nix"; inputs.nixpkgs.follows = "nixpkgs"; @@ -89,6 +84,181 @@ cargo = rustfsToolchain; rustc = rustfsToolchain; }; + rustfsPackage = pkgs.callPackage ./packages/rustfs.nix { + rustPlatform = rustfsRustPlatform; + rustfsSrc = inputs.rustfs-src; + }; + + dbName = "db"; + postgresPort = 5432; + postgresDataDir = "data/postgres"; + postgresPackage = pkgs.postgresql.withPackages (postgresExtensions: [ + postgresExtensions.postgis + ]); + postgresHbaConf = pkgs.writeText "pg_hba.conf" '' + # Generated by Nix + local all all trust + host all all 127.0.0.1/32 trust + host all all ::1/128 trust + local replication all trust + host replication all 127.0.0.1/32 trust + host replication all ::1/128 trust + ''; + postgresInit = pkgs.writeShellApplication { + name = "memory-map-postgres-init"; + runtimeInputs = [ + postgresPackage + pkgs.coreutils + ]; + text = '' + set -euo pipefail + + PGDATA="$(readlink -m "${postgresDataDir}")" + export PGDATA + mkdir -p "$PGDATA" + + if [ -s "$PGDATA/PG_VERSION" ]; then + echo "PostgreSQL data directory already initialized: $PGDATA" + exit 0 + fi + + initdb --locale=C --encoding=UTF8 -D "$PGDATA" + ''; + }; + postgresStart = pkgs.writeShellApplication { + name = "memory-map-postgres-start"; + runtimeInputs = [ + postgresPackage + pkgs.coreutils + ]; + text = '' + set -euo pipefail + + PGDATA="$(readlink -m "${postgresDataDir}")" + export PGDATA + + exec postgres \ + -D "$PGDATA" \ + -c listen_addresses=127.0.0.1 \ + -c port=${toString postgresPort} \ + -c hba_file=${postgresHbaConf} \ + -c unix_socket_directories= + ''; + }; + postgresBootstrap = pkgs.writeShellApplication { + name = "memory-map-postgres-bootstrap"; + runtimeInputs = [ + postgresPackage + pkgs.gnugrep + ]; + text = '' + set -euo pipefail + + export PGHOST=127.0.0.1 + export PGPORT=${toString postgresPort} + export PGDATABASE=postgres + export PGCONNECT_TIMEOUT=5 + + if ! psql -v ON_ERROR_STOP=1 -tAc "SELECT 1 FROM pg_database WHERE datname = '${dbName}'" | grep -qx 1; then + createdb "${dbName}" + fi + + psql -v ON_ERROR_STOP=1 -tAc "SELECT name FROM pg_available_extensions WHERE name = 'postgis'" | grep -qx postgis + ''; + }; + postgresTest = pkgs.writeShellApplication { + name = "memory-map-postgres-test"; + runtimeInputs = [ + postgresPackage + pkgs.gnugrep + ]; + text = '' + set -euo pipefail + + psql -h 127.0.0.1 -p ${toString postgresPort} -d ${dbName} -v ON_ERROR_STOP=1 -c 'SELECT version();' + psql -h 127.0.0.1 -p ${toString postgresPort} -d ${dbName} -v ON_ERROR_STOP=1 -tAc "SELECT name FROM pg_available_extensions WHERE name = 'postgis'" | grep -qx postgis + ''; + }; + + rustfsDataDir = "data/rustfs"; + rustfsApiAddress = "127.0.0.1:9000"; + rustfsConsoleAddress = "127.0.0.1:9001"; + s3EndpointUrl = "http://${rustfsApiAddress}"; + s3Region = "us-east-1"; + s3BucketName = "memory-map"; + s3AccessKey = "memorymapdev"; + s3SecretKey = "memorymapdevsecret"; + rustfsStart = pkgs.writeShellApplication { + name = "memory-map-rustfs-start"; + runtimeInputs = [ + rustfsPackage + pkgs.coreutils + ]; + text = '' + set -euo pipefail + + data_dir="$(readlink -m "${rustfsDataDir}")" + mkdir -p "$data_dir" + exec rustfs server "$data_dir" + ''; + }; + rustfsBootstrap = pkgs.writeShellApplication { + name = "memory-map-rustfs-bootstrap"; + runtimeInputs = [ + pkgs.coreutils + pkgs.curl + ]; + text = '' + set -euo pipefail + + curl --fail --silent --show-error --max-time 5 "${s3EndpointUrl}/health/ready" >/dev/null + + auth_args=( + --aws-sigv4 "aws:amz:${s3Region}:s3" + --user "${s3AccessKey}:${s3SecretKey}" + --silent + --show-error + --max-time 5 + ) + + curl --fail "''${auth_args[@]}" "${s3EndpointUrl}/" >/dev/null + + response_body="$(mktemp)" + trap 'rm -f "$response_body"' EXIT + + bucket_status="$(curl "''${auth_args[@]}" --head --output "$response_body" --write-out "%{http_code}" "${s3EndpointUrl}/${s3BucketName}" || true)" + case "$bucket_status" in + 200) + exit 0 + ;; + 404) + ;; + *) + cat "$response_body" >&2 + echo "Failed to check bucket ${s3BucketName}; HTTP $bucket_status" >&2 + exit 1 + ;; + esac + + http_code="$(curl "''${auth_args[@]}" --request PUT --output "$response_body" --write-out "%{http_code}" "${s3EndpointUrl}/${s3BucketName}" || true)" + case "$http_code" in + 200|409) + ;; + *) + cat "$response_body" >&2 + echo "Failed to create bucket ${s3BucketName}; HTTP $http_code" >&2 + exit 1 + ;; + esac + + bucket_status="$(curl "''${auth_args[@]}" --head --output "$response_body" --write-out "%{http_code}" "${s3EndpointUrl}/${s3BucketName}" || true)" + if [ "$bucket_status" != 200 ]; then + cat "$response_body" >&2 + echo "Failed to verify bucket ${s3BucketName}; HTTP $bucket_status" >&2 + exit 1 + fi + ''; + }; treefmtEval = inputs.treefmt-nix.lib.evalModule pkgs { # Cargo.toml lives at the repo root (one level above devenv/). @@ -164,13 +334,6 @@ inherit system; config.allowUnfree = true; overlays = [ - # https://github.com/hercules-ci/flake-parts/discussions/217#discussioncomment-10475578 - (final: _prev: { - minio = import inputs.nixpkgs-minio { - inherit (final) system; - config.allowUnfree = true; - }; - }) (final: _prev: { unstable = import inputs.nixpkgs-unstable { inherit (final) system; @@ -185,89 +348,89 @@ }; packages.rustToolchain = rustToolchain; - packages.rustfs = pkgs.callPackage ./packages/rustfs.nix { - rustPlatform = rustfsRustPlatform; - rustfsSrc = inputs.rustfs-src; - }; + packages.rustfs = rustfsPackage; # `process-compose.foo` will add a flake package output called "foo". # Therefore, this will add a default package that you can build using # `nix build` and run using `nix run`. - process-compose."default" = - { config, ... }: - let - dbName = "db"; - in - { - imports = [ - inputs.services-flake.processComposeModules.default - ]; - - services = { - minio."minio1" = { - enable = true; - package = pkgs.minio.minio; - }; - postgres = { - "pg1" = { - enable = true; - extensions = extensions: [ - extensions.postgis - ]; - initialDatabases = [ - { - name = dbName; - } - ]; + process-compose."default" = { + settings = { + ordered_shutdown = true; + processes = { + pg1-init.command = postgresInit; + pg1 = { + command = postgresStart; + depends_on."pg1-init".condition = "process_completed_successfully"; + shutdown = { + signal = 2; + timeout_seconds = 10; + }; + readiness_probe = { + exec.command = "${postgresPackage}/bin/pg_isready -h 127.0.0.1 -p ${toString postgresPort} -d postgres"; + initial_delay_seconds = 1; + period_seconds = 2; + timeout_seconds = 5; + success_threshold = 1; + failure_threshold = 10; + }; + availability = { + restart = "on_failure"; + max_restarts = 5; }; }; - }; - - settings = { - processes = { - minio1-test = { - command = pkgs.writeShellApplication { - runtimeInputs = [ pkgs.curl ]; - text = '' - curl http://127.0.0.1:9000/minio/health/live - ''; - name = "minio1-test"; - }; - depends_on."minio1".condition = "process_healthy"; + pg1-bootstrap = { + command = postgresBootstrap; + depends_on."pg1".condition = "process_healthy"; + }; + pgweb = { + environment.PGWEB_DATABASE_URL = "postgres://127.0.0.1:${toString postgresPort}/${dbName}"; + command = pkgs.pgweb; + depends_on."pg1-bootstrap".condition = "process_completed_successfully"; + }; + pg1-test = { + command = postgresTest; + depends_on."pg1-bootstrap".condition = "process_completed_successfully"; + }; + rustfs = { + command = rustfsStart; + environment = { + RUSTFS_ACCESS_KEY = s3AccessKey; + RUSTFS_SECRET_KEY = s3SecretKey; + RUSTFS_ADDRESS = rustfsApiAddress; + RUSTFS_CONSOLE_ENABLE = "true"; + RUSTFS_CONSOLE_ADDRESS = rustfsConsoleAddress; + RUSTFS_REGION = s3Region; + RUSTFS_HEALTH_ENDPOINT_ENABLE = "true"; + }; + shutdown = { + signal = 15; + timeout_seconds = 5; + }; + readiness_probe = { + exec.command = lib.getExe rustfsBootstrap; + initial_delay_seconds = 2; + period_seconds = 5; + timeout_seconds = 8; + success_threshold = 1; + failure_threshold = 6; }; - pgweb = - let - pgcfg = config.services.postgres.pg1; - in - { - environment.PGWEB_DATABASE_URL = pgcfg.connectionURI { inherit dbName; }; - command = pkgs.pgweb; - depends_on."pg1".condition = "process_healthy"; - }; - pg1-test = { - command = pkgs.writeShellApplication { - name = "pg1-test"; - runtimeInputs = [ config.services.postgres.pg1.package ]; - text = '' - echo 'SELECT version();' | psql -h 127.0.0.1 ${dbName} - ''; - }; - depends_on."pg1".condition = "process_healthy"; + availability = { + restart = "on_failure"; + max_restarts = 3; }; }; }; }; + }; devShells.default = pkgs.mkShell { - inputsFrom = [ - config.process-compose."default".services.outputs.devShell - ]; - # Alias for `nativeBuildInputs` # https://discourse.nixos.org/t/difference-between-buildinputs-and-packages-in-mkshell/60598/10 packages = [ pkgs.bashInteractive config.packages.rustToolchain + config.process-compose."default".outputs.package + postgresPackage pkgs.openssl pkgs.pkg-config pkgs.cargo-deny diff --git a/justfile b/justfile index 152a191..d64e152 100644 --- a/justfile +++ b/justfile @@ -19,10 +19,14 @@ default: allow-env: direnv allow -# Start PostgreSQL and Minio servers. +# Start PostgreSQL and RustFS servers. servers: {{ direnv_prefix }} nix run ./devenv +# Remove local service state created by current and legacy service recipes. +clean-service-state: + rm -rf data/postgres data/rustfs data/pg1 data/minio1 + # Start backend server. backend: {{ direnv_prefix }} bash -c 'cd backend; {{ log_prefix }} bacon run -- {{ release_flag }}' From ed6a872a6be87631636f16adf2649171c83a0e55 Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Tue, 26 May 2026 21:56:11 +0100 Subject: [PATCH 06/28] Verify RustFS identity during bootstrap --- devenv/flake.nix | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/devenv/flake.nix b/devenv/flake.nix index 3d3a8b1..055f0f5 100644 --- a/devenv/flake.nix +++ b/devenv/flake.nix @@ -207,11 +207,21 @@ runtimeInputs = [ pkgs.coreutils pkgs.curl + pkgs.gnugrep ]; text = '' set -euo pipefail - curl --fail --silent --show-error --max-time 5 "${s3EndpointUrl}/health/ready" >/dev/null + health_body="$(mktemp)" + response_body="$(mktemp)" + trap 'rm -f "$health_body" "$response_body"' EXIT + + curl --fail --silent --show-error --max-time 5 --output "$health_body" "${s3EndpointUrl}/health/ready" + if ! grep -Eq '"service"[[:space:]]*:[[:space:]]*"rustfs-endpoint"' "$health_body"; then + cat "$health_body" >&2 + echo "RustFS readiness probe did not identify a RustFS service at ${s3EndpointUrl}" >&2 + exit 1 + fi auth_args=( --aws-sigv4 "aws:amz:${s3Region}:s3" @@ -223,9 +233,6 @@ curl --fail "''${auth_args[@]}" "${s3EndpointUrl}/" >/dev/null - response_body="$(mktemp)" - trap 'rm -f "$response_body"' EXIT - bucket_status="$(curl "''${auth_args[@]}" --head --output "$response_body" --write-out "%{http_code}" "${s3EndpointUrl}/${s3BucketName}" || true)" case "$bucket_status" in 200) From b9028baf751a354293965890e6acf3b70554d914 Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Tue, 26 May 2026 22:05:10 +0100 Subject: [PATCH 07/28] Rename storage configuration to S3 --- .env.example | 8 +++++--- README.md | 5 +++++ backend/src/constants.rs | 2 +- backend/src/controllers/api/locations.rs | 6 +++--- backend/src/graphql/objects/s3_object.rs | 4 ++-- backend/src/graphql/queries/mutation.rs | 12 ++++++------ backend/src/lib.rs | 20 +++++++++++++------- backend/src/main.rs | 24 +++++++++++++++++------- 8 files changed, 52 insertions(+), 29 deletions(-) diff --git a/.env.example b/.env.example index 8c75165..7c7ee7e 100644 --- a/.env.example +++ b/.env.example @@ -10,10 +10,12 @@ SMTP_PASS=password SMTP_FROM=noreply@example.com COOKIE_SECRET=supersecretkeymustbeatleast64byteslongforsecurityreasons1234567890 FRONTEND_URL=http://localhost:3000 -MINIO_ACCESS_KEY=memorymapdev -MINIO_SECRET_KEY=memorymapdevsecret -MINIO_URL=http://127.0.0.1:9000/ +S3_ENDPOINT_URL=http://127.0.0.1:9000/ +S3_ACCESS_KEY=memorymapdev +S3_SECRET_KEY=memorymapdevsecret S3_BUCKET_NAME=memory-map +S3_REGION=us-east-1 +S3_FORCE_PATH_STYLE=true SERVER_HOST=127.0.0.1 SERVER_PORT=8000 CORS_ALLOWED_ORIGINS=http://127.0.0.1:3000 diff --git a/README.md b/README.md index 94650a7..ee13da4 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,11 @@ You can optionally configure the build mode and other settings by editing `.env` - `BUILD_MODE="debug"` (default): Faster compilation, includes debug info. - `BUILD_MODE="release"`: Optimised build, smaller binaries, slower compilation. - Database, SMTP, and S3 storage configurations. +- Local storage uses `S3_ENDPOINT_URL`, `S3_ACCESS_KEY`, `S3_SECRET_KEY`, + `S3_BUCKET_NAME`, `S3_REGION`, and `S3_FORCE_PATH_STYLE`. +- The default local S3 API endpoint is `http://127.0.0.1:9000/`, with region + `us-east-1`, bucket `memory-map`, and path-style addressing enabled for + RustFS. ### 4. Start database & storage diff --git a/backend/src/constants.rs b/backend/src/constants.rs index 070422a..b7473f9 100644 --- a/backend/src/constants.rs +++ b/backend/src/constants.rs @@ -19,7 +19,7 @@ pub const ERR_MULTIPART_MISSING_FILENAME: &str = "Multipart field missing filena pub const ERR_MULTIPART_MISSING_CONTENT_TYPE: &str = "Multipart field missing content type"; pub const ERR_UNSUPPORTED_FILE_TYPE: &str = "Unsupported file type: "; pub const ERR_FAILED_READ_BYTES: &str = "Failed to read bytes: "; -pub const ERR_UPLOAD_MINIO: &str = "Failed to upload file to MinIO"; +pub const ERR_UPLOAD_STORAGE: &str = "Failed to upload file to S3 storage"; pub const ERR_DB_CLIENT: &str = "Failed to get database client from pool"; pub const ERR_HASHING: &str = "Hashing error: "; pub const ERR_EMAIL: &str = "Email error: "; diff --git a/backend/src/controllers/api/locations.rs b/backend/src/controllers/api/locations.rs index 6438064..1b9a5a1 100644 --- a/backend/src/controllers/api/locations.rs +++ b/backend/src/controllers/api/locations.rs @@ -8,7 +8,7 @@ use { ERR_MULTIPART_MISSING_FILENAME, ERR_MULTIPART_MISSING_NAME, ERR_UNSUPPORTED_FILE_TYPE, - ERR_UPLOAD_MINIO, + ERR_UPLOAD_STORAGE, }, errors::AppError, graphql::{ @@ -143,12 +143,12 @@ pub async fn post( state .inner - .minio_client + .s3_client .put_object_content(&state.inner.bucket_name, &file.filename, file.bytes) .content_type(file.content_type) .send() .await - .context(ERR_UPLOAD_MINIO)?; + .context(ERR_UPLOAD_STORAGE)?; let client = state.inner.pool.get().await.context(ERR_DB_CLIENT)?; let location = if let (Some(latitude), Some(longitude)) = (latitude, longitude) { diff --git a/backend/src/graphql/objects/s3_object.rs b/backend/src/graphql/objects/s3_object.rs index de29370..90d9ed5 100644 --- a/backend/src/graphql/objects/s3_object.rs +++ b/backend/src/graphql/objects/s3_object.rs @@ -254,7 +254,7 @@ impl S3Object { ) -> Result { let data = ctx.data::>>()?; Ok(data - .minio_client + .s3_client .get_presigned_object_url(&data.bucket_name, &self.name, Method::GET) .send() .await? @@ -266,7 +266,7 @@ impl S3Object { ctx: &Context<'_>, ) -> Result { let data = ctx.data::>>()?; - data.minio_client + data.s3_client .get_object(&data.bucket_name, &self.name) .send() .await? diff --git a/backend/src/graphql/queries/mutation.rs b/backend/src/graphql/queries/mutation.rs index f2619f0..a804791 100644 --- a/backend/src/graphql/queries/mutation.rs +++ b/backend/src/graphql/queries/mutation.rs @@ -67,7 +67,7 @@ use { futures::future::join_all, jiff::Timestamp, minio::s3::{ - Client as MinioClient, + Client as S3Client, builders::ObjectToDelete, types::S3Api, }, @@ -117,7 +117,7 @@ pub struct Mutation; impl Mutation { pub async fn delete_s3_objects_worker( db_client: &Client, - minio_client: &MinioClient, + s3_client: &S3Client, bucket_name: &str, ids: &[i64], ) -> Result, AppError> { @@ -144,11 +144,11 @@ impl Mutation { tracing::debug!("Objects to delete: {:?}", objects_to_delete); if !objects_to_delete.is_empty() { - minio_client + s3_client .delete_objects::<_, ObjectToDelete>(bucket_name, objects_to_delete) .send() .await - .context("Failed to delete objects from MinIO")?; + .context("Failed to delete objects from S3 storage")?; } Ok(objects) @@ -313,7 +313,7 @@ impl Mutation { let user_id = ctx.data_opt::().ok_or_else(|| GraphQLError::new("Unauthorized"))?.0; let wrapper = ContextWrapper(ctx); let bucket_name = wrapper.get_bucket_name()?; - let minio_client = wrapper.get_minio_client()?; + let s3_client = wrapper.get_s3_client()?; let client = wrapper.get_db_client().await?; let ids: Vec = ids .into_iter() @@ -345,7 +345,7 @@ impl Mutation { .ok_or_else(|| GraphQLError::new("Forbidden"))?; } - let result = Self::delete_s3_objects_worker(&client, minio_client, bucket_name, &ids) + let result = Self::delete_s3_objects_worker(&client, s3_client, bucket_name, &ids) .await .map_err(GraphQLError::from)?; diff --git a/backend/src/lib.rs b/backend/src/lib.rs index 0755d90..0471107 100644 --- a/backend/src/lib.rs +++ b/backend/src/lib.rs @@ -54,10 +54,12 @@ pub struct Config { pub smtp_from: String, pub cookie_secret: String, pub frontend_url: String, - pub minio_access_key: String, - pub minio_secret_key: String, - pub minio_url: String, + pub s3_endpoint_url: String, + pub s3_access_key: String, + pub s3_secret_key: String, pub s3_bucket_name: String, + pub s3_region: String, + pub s3_force_path_style: bool, pub server_host: String, pub server_port: u16, pub cors_allowed_origins: String, @@ -66,6 +68,10 @@ pub struct Config { impl Config { pub fn from_env() -> Result { let cfg = config::Config::builder() + .set_default("s3_region", "us-east-1") + .map_err(errors::AppError::from)? + .set_default("s3_force_path_style", true) + .map_err(errors::AppError::from)? .add_source(config::Environment::default().separator("__")) .build() .map_err(errors::AppError::from)?; @@ -79,7 +85,7 @@ pub struct UserId(pub i64); pub struct SharedState>> { pub pool: Pool, - pub minio_client: s3::Client, + pub s3_client: s3::Client, pub bucket_name: String, pub last_modified: AtomicU64, pub response_cache: Cache, @@ -139,7 +145,7 @@ impl>> fmt::Debug for SharedState { ) -> fmt::Result { f.debug_struct("SharedState") .field("pool", &"Pool") - .field("minio_client", &self.minio_client) + .field("s3_client", &self.s3_client) .field("bucket_name", &self.bucket_name) .field("last_modified", &self.last_modified) .field("response_cache", &"Cache") @@ -157,11 +163,11 @@ impl<'a> ContextWrapper<'a> { Ok(pool.get().await?) } - pub fn get_minio_client(&self) -> Result<&s3::Client, GraphQLError> { + pub fn get_s3_client(&self) -> Result<&s3::Client, GraphQLError> { Ok(&self .0 .data::>>()? - .minio_client) + .s3_client) } pub fn get_bucket_name(&self) -> Result<&str, GraphQLError> { diff --git a/backend/src/main.rs b/backend/src/main.rs index 115da50..820dcbf 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -259,16 +259,26 @@ async fn main() -> anyhow::Result<()> { .context("Failed to run database migrations")?; } - // Initialise minio client - let base_url = cfg.minio_url.parse::().context("Failed to parse MinIO URL")?; - tracing::info!("Trying to connect to MinIO at: `{:?}`", base_url); + // Initialise S3 client + let mut base_url = + cfg.s3_endpoint_url.parse::().context("Failed to parse S3 endpoint URL")?; + base_url.region.clone_from(&cfg.s3_region); + if cfg.s3_force_path_style { + base_url.virtual_style = false; + } + tracing::info!( + "S3 endpoint configured: `{:?}` (region: {}, force path-style: {})", + base_url, + cfg.s3_region, + cfg.s3_force_path_style + ); - let static_provider = StaticProvider::new(&cfg.minio_access_key, &cfg.minio_secret_key, None); + let static_provider = StaticProvider::new(&cfg.s3_access_key, &cfg.s3_secret_key, None); - let minio_client = ClientBuilder::new(base_url) + let s3_client = ClientBuilder::new(base_url) .provider(Some(Box::new(static_provider))) .build() - .context("Failed to build MinIO client")?; + .context("Failed to build S3 client")?; let bucket_name = cfg.s3_bucket_name.clone(); @@ -292,7 +302,7 @@ async fn main() -> anyhow::Result<()> { let key = Key::from(cfg.cookie_secret.as_bytes()); let shared_state = Arc::new(SharedState { pool, - minio_client, + s3_client, bucket_name, last_modified, response_cache, From 513432f359b603175b4f7469881c62cbf45960f6 Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Tue, 26 May 2026 22:55:28 +0100 Subject: [PATCH 08/28] Migrate backend storage to AWS SDK --- .env.example | 1 + Cargo.lock | 1243 +++++++++++++++------- README.md | 5 +- backend/Cargo.toml | 8 +- backend/src/controllers/api/locations.rs | 23 +- backend/src/errors.rs | 6 - backend/src/graphql/objects/s3_object.rs | 19 +- backend/src/graphql/queries/mutation.rs | 24 +- backend/src/lib.rs | 33 +- backend/src/main.rs | 31 +- backend/src/storage.rs | 222 ++++ devenv/flake.nix | 2 - 12 files changed, 1129 insertions(+), 488 deletions(-) create mode 100644 backend/src/storage.rs diff --git a/.env.example b/.env.example index 7c7ee7e..67aa1b1 100644 --- a/.env.example +++ b/.env.example @@ -16,6 +16,7 @@ S3_SECRET_KEY=memorymapdevsecret S3_BUCKET_NAME=memory-map S3_REGION=us-east-1 S3_FORCE_PATH_STYLE=true +S3_PRESIGNED_URL_TTL_SECONDS=604800 SERVER_HOST=127.0.0.1 SERVER_PORT=8000 CORS_ALLOWED_ORIGINS=http://127.0.0.1:3000 diff --git a/Cargo.lock b/Cargo.lock index 70fb8b1..2bed172 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,7 +14,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "generic-array", ] @@ -26,7 +26,7 @@ checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -66,6 +66,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -75,56 +81,6 @@ dependencies = [ "libc", ] -[[package]] -name = "anstream" -version = "0.6.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" - -[[package]] -name = "anstyle-parse" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" -dependencies = [ - "anstyle", - "once_cell_polyfill", - "windows-sys 0.61.2", -] - [[package]] name = "any_spawner" version = "0.3.0" @@ -159,7 +115,7 @@ checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" dependencies = [ "base64ct", "blake2", - "cpufeatures", + "cpufeatures 0.2.17", "password-hash", ] @@ -205,7 +161,7 @@ dependencies = [ "futures-timer", "futures-util", "handlebars", - "http", + "http 1.4.0", "indexmap", "mime", "multer", @@ -250,7 +206,7 @@ dependencies = [ "proc-macro2", "quote", "strum", - "syn 2.0.111", + "syn", "thiserror 2.0.17", ] @@ -295,17 +251,6 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4288f83726785267c6f2ef073a3d83dc3f9b81464e9f99898240cced85fce35a" -[[package]] -name = "async-recursion" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.111", -] - [[package]] name = "async-trait" version = "0.1.89" @@ -314,7 +259,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -344,7 +289,7 @@ dependencies = [ "manyhow", "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -360,7 +305,7 @@ dependencies = [ "proc-macro2", "quote", "quote-use", - "syn 2.0.111", + "syn", ] [[package]] @@ -369,6 +314,18 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "aws-credential-types" +version = "1.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f20799b373a1be121fe3005fba0c2090af9411573878f224df44b42727fcaf7" +dependencies = [ + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "zeroize", +] + [[package]] name = "aws-lc-rs" version = "1.17.0" @@ -391,6 +348,321 @@ dependencies = [ "fs_extra", ] +[[package]] +name = "aws-runtime" +version = "1.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ed8e8c52d2dc2390ad9f15647fe663f71e9780b4262c190fbb823a32721566" +dependencies = [ + "aws-credential-types", + "aws-sigv4", + "aws-smithy-async", + "aws-smithy-eventstream", + "aws-smithy-http", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "bytes-utils", + "fastrand", + "http 0.2.12", + "http 1.4.0", + "http-body 0.4.6", + "http-body 1.0.1", + "percent-encoding", + "pin-project-lite", + "tracing", + "uuid", +] + +[[package]] +name = "aws-sdk-s3" +version = "1.133.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "237aba2985e3c0a83e199cc7aa9a64a16c599875bc98170f00932f6199f19922" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-sigv4", + "aws-smithy-async", + "aws-smithy-checksums", + "aws-smithy-eventstream", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-observability", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-smithy-xml", + "aws-types", + "bytes", + "fastrand", + "hex", + "hmac 0.13.0", + "http 0.2.12", + "http 1.4.0", + "http-body 1.0.1", + "lru", + "percent-encoding", + "regex-lite", + "sha2 0.11.0", + "tracing", + "url", +] + +[[package]] +name = "aws-sigv4" +version = "1.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7083fb918b38474ac65ffbf8a69fc8792d36879f4ac5f1667b43aec61efe9a5" +dependencies = [ + "aws-credential-types", + "aws-smithy-eventstream", + "aws-smithy-http", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "crypto-bigint", + "form_urlencoded", + "hex", + "hmac 0.13.0", + "http 0.2.12", + "http 1.4.0", + "p256", + "percent-encoding", + "sha2 0.11.0", + "subtle", + "time", + "tracing", + "zeroize", +] + +[[package]] +name = "aws-smithy-async" +version = "1.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffcaf626bdda484571968400c326a244598634dc75fd451325a54ad1a59acfc" +dependencies = [ + "futures-util", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "aws-smithy-checksums" +version = "0.64.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9e8e65f4f81fcccdeb6c3eca2af17ac21d421a1786a26a394aecf421d616d3a" +dependencies = [ + "aws-smithy-http", + "aws-smithy-types", + "bytes", + "crc-fast", + "hex", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "md-5 0.11.0", + "pin-project-lite", + "sha1 0.11.0", + "sha2 0.11.0", + "tracing", +] + +[[package]] +name = "aws-smithy-eventstream" +version = "0.60.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf09d74e5e32f76b8762da505a3cd59303e367a664ca67295387baa8c1d7548" +dependencies = [ + "aws-smithy-types", + "bytes", + "crc32fast", +] + +[[package]] +name = "aws-smithy-http" +version = "0.63.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba1ab2dc1c2c3749ead27180d333c42f11be8b0e934058fb4b2258ee8dbe5231" +dependencies = [ + "aws-smithy-eventstream", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "bytes-utils", + "futures-core", + "futures-util", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "percent-encoding", + "pin-project-lite", + "pin-utils", + "tracing", +] + +[[package]] +name = "aws-smithy-http-client" +version = "1.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a2f165a7feee6f263028b899d0a181987f4fa7179a6411a32a439fba7c5f769" +dependencies = [ + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "h2", + "http 1.4.0", + "hyper", + "hyper-rustls", + "hyper-util", + "pin-project-lite", + "rustls", + "rustls-native-certs", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower", + "tracing", +] + +[[package]] +name = "aws-smithy-json" +version = "0.62.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "517089205f18ab4adc5a3e02888cb139bbbbb2e168eac9f396216925d1fbeaf5" +dependencies = [ + "aws-smithy-runtime-api", + "aws-smithy-schema", + "aws-smithy-types", +] + +[[package]] +name = "aws-smithy-observability" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06c2315d173edbf1920da8ba3a7189695827002e4c0fc961973ab1c54abca9c" +dependencies = [ + "aws-smithy-runtime-api", +] + +[[package]] +name = "aws-smithy-runtime" +version = "1.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e6f5caf6fea86f8c2206541ab5857cfcda9013426cdbe8fa0098b9e2d32182" +dependencies = [ + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-http-client", + "aws-smithy-observability", + "aws-smithy-runtime-api", + "aws-smithy-schema", + "aws-smithy-types", + "bytes", + "fastrand", + "http 0.2.12", + "http 1.4.0", + "http-body 0.4.6", + "http-body 1.0.1", + "http-body-util", + "pin-project-lite", + "pin-utils", + "tokio", + "tracing", +] + +[[package]] +name = "aws-smithy-runtime-api" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc117c179ecf39a62a0a3f49f600e9ac26a7ad7dd172177999f83933af776c32" +dependencies = [ + "aws-smithy-async", + "aws-smithy-runtime-api-macros", + "aws-smithy-types", + "bytes", + "http 0.2.12", + "http 1.4.0", + "pin-project-lite", + "tokio", + "tracing", + "zeroize", +] + +[[package]] +name = "aws-smithy-runtime-api-macros" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d7396fd9500589e62e460e987ecb671bad374934e55ec3b5f498cc7a8a8a7b7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "aws-smithy-schema" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7442cb268338f0eb8278140a107c046756aa01093d8ef5e99628d34ae09c94f5" +dependencies = [ + "aws-smithy-runtime-api", + "aws-smithy-types", + "http 1.4.0", +] + +[[package]] +name = "aws-smithy-types" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "056b66dbce2f81cc0c1e2b05bb402eb58f8a3530479d650efadd5bbae9a4050b" +dependencies = [ + "base64-simd", + "bytes", + "bytes-utils", + "futures-core", + "http 0.2.12", + "http 1.4.0", + "http-body 0.4.6", + "http-body 1.0.1", + "http-body-util", + "itoa", + "num-integer", + "pin-project-lite", + "pin-utils", + "ryu", + "serde", + "time", + "tokio", + "tokio-util", +] + +[[package]] +name = "aws-smithy-xml" +version = "0.60.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce02add1aa3677d022f8adf81dcbe3046a95f17a1b1e8979c145cd21d3d22b3" +dependencies = [ + "xmlparser", +] + +[[package]] +name = "aws-types" +version = "1.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d16bf10b03a3c01e6b3b7d47cd964e873ffe9e7d4e80fad16bd4c077cb068531" +dependencies = [ + "aws-credential-types", + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-schema", + "aws-smithy-types", + "rustc_version", + "tracing", +] + [[package]] name = "axum" version = "0.8.8" @@ -402,8 +674,8 @@ dependencies = [ "bytes", "form_urlencoded", "futures-util", - "http", - "http-body", + "http 1.4.0", + "http-body 1.0.1", "http-body-util", "hyper", "hyper-util", @@ -418,7 +690,7 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sha1", + "sha1 0.10.6", "sync_wrapper", "tokio", "tokio-tungstenite", @@ -436,8 +708,8 @@ checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" dependencies = [ "bytes", "futures-core", - "http", - "http-body", + "http 1.4.0", + "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", @@ -459,8 +731,8 @@ dependencies = [ "cookie", "futures-core", "futures-util", - "http", - "http-body", + "http 1.4.0", + "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", @@ -477,7 +749,7 @@ checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -488,6 +760,8 @@ dependencies = [ "argon2", "async-graphql", "async-graphql-axum", + "aws-credential-types", + "aws-sdk-s3", "axum", "axum-extra", "axum-macros", @@ -503,7 +777,6 @@ dependencies = [ "hex", "jiff", "lettre", - "minio", "moka", "postgres-types", "rand 0.8.6", @@ -527,12 +800,28 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d27c3610c36aee21ce8ac510e6224498de4228ad772a171ed65643a24693a5a8" +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" +dependencies = [ + "outref", + "vsimd", +] + [[package]] name = "base64ct" version = "1.8.1" @@ -554,7 +843,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ - "digest", + "digest 0.10.7", ] [[package]] @@ -579,6 +868,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" +dependencies = [ + "hybrid-array", +] + [[package]] name = "bumpalo" version = "3.19.0" @@ -606,6 +904,16 @@ dependencies = [ "serde", ] +[[package]] +name = "bytes-utils" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dafe3a8757b027e2be6e4e5601ed563c55989fcf1546e933c66c8eb3a058d35" +dependencies = [ + "bytes", + "either", +] + [[package]] name = "camino" version = "1.2.1" @@ -692,7 +1000,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "inout", ] @@ -705,6 +1013,12 @@ dependencies = [ "cc", ] +[[package]] +name = "cmov" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746" + [[package]] name = "codee" version = "0.3.5" @@ -722,12 +1036,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2550f75b8cfac212855f6b1885455df8eaee8fe8e246b647d69146142e016084" -[[package]] -name = "colorchoice" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" - [[package]] name = "combine" version = "4.6.7" @@ -787,6 +1095,18 @@ dependencies = [ "web-sys", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + [[package]] name = "const-random" version = "0.1.18" @@ -871,10 +1191,10 @@ checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" dependencies = [ "aes-gcm", "base64", - "hmac", + "hmac 0.12.1", "percent-encoding", "rand 0.8.6", - "sha2", + "sha2 0.10.9", "subtle", "time", "version_check", @@ -916,19 +1236,32 @@ dependencies = [ ] [[package]] -name = "crc" -version = "3.4.0" +name = "cpufeatures" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ - "crc-catalog", + "libc", ] [[package]] -name = "crc-catalog" -version = "2.4.0" +name = "crc-fast" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e75b2483e97a5a7da73ac68a05b629f9c53cff58d8ed1c77866079e18b00dba5" +dependencies = [ + "digest 0.10.7", + "spin 0.10.0", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] [[package]] name = "crossbeam-channel" @@ -960,6 +1293,18 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" +[[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.7" @@ -971,6 +1316,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "hybrid-array", +] + [[package]] name = "ctr" version = "0.9.2" @@ -980,6 +1334,15 @@ dependencies = [ "cipher", ] +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", +] + [[package]] name = "darling" version = "0.20.11" @@ -1011,7 +1374,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.111", + "syn", ] [[package]] @@ -1024,7 +1387,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.111", + "syn", ] [[package]] @@ -1035,7 +1398,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -1046,7 +1409,7 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core 0.23.0", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -1107,24 +1470,24 @@ dependencies = [ ] [[package]] -name = "deranged" -version = "0.5.5" +name = "der" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ - "powerfmt", - "serde_core", + "const-oid 0.9.6", + "pem-rfc7468", + "zeroize", ] [[package]] -name = "derivative" -version = "2.2.0" +name = "deranged" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "powerfmt", + "serde_core", ] [[package]] @@ -1135,7 +1498,7 @@ checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -1156,7 +1519,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -1166,7 +1529,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.111", + "syn", ] [[package]] @@ -1175,11 +1538,24 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", - "crypto-common", + "block-buffer 0.10.4", + "const-oid 0.9.6", + "crypto-common 0.1.7", "subtle", ] +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.0", + "const-oid 0.10.2", + "crypto-common 0.2.2", + "ctutils", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -1188,7 +1564,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -1218,6 +1594,20 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + [[package]] name = "either" version = "1.15.0" @@ -1234,6 +1624,26 @@ dependencies = [ "pin-project-lite", ] +[[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 0.10.7", + "ff", + "generic-array", + "group", + "pem-rfc7468", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "email-encoding" version = "0.4.1" @@ -1262,29 +1672,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "env_filter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "env_logger" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" -dependencies = [ - "anstream", - "anstyle", - "env_filter", - "jiff", - "log", -] - [[package]] name = "equivalent" version = "1.0.2" @@ -1375,6 +1762,16 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "find-msvc-tools" version = "0.1.5" @@ -1399,6 +1796,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "foreign-types" version = "0.3.2" @@ -1439,7 +1842,7 @@ dependencies = [ "log", "lucide-leptos", "mime", - "reqwest 0.13.1", + "reqwest", "serde", "serde_json", "shared", @@ -1515,7 +1918,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -1562,6 +1965,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1600,7 +2004,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -1623,7 +2027,7 @@ dependencies = [ "futures-core", "futures-sink", "gloo-utils", - "http", + "http 1.4.0", "js-sys", "pin-project", "serde", @@ -1691,7 +2095,7 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 2.0.111", + "syn", ] [[package]] @@ -1702,7 +2106,18 @@ checksum = "b684c77d1b5f9c6006068852e0e0e80c6df3ef85c24fe81ef26fbadbd595af77" dependencies = [ "graphql_client_codegen", "proc-macro2", - "syn 2.0.111", + "syn", +] + +[[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]] @@ -1722,7 +2137,7 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http", + "http 1.4.0", "indexmap", "slab", "tokio", @@ -1761,7 +2176,7 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "foldhash", + "foldhash 0.1.5", ] [[package]] @@ -1769,6 +2184,11 @@ name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] [[package]] name = "hashlink" @@ -1812,7 +2232,16 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest", + "digest 0.10.7", +] + +[[package]] +name = "hmac" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" +dependencies = [ + "digest 0.11.3", ] [[package]] @@ -1835,6 +2264,17 @@ dependencies = [ "utf8-width", ] +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http" version = "1.4.0" @@ -1845,6 +2285,17 @@ dependencies = [ "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" @@ -1852,7 +2303,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http", + "http 1.4.0", ] [[package]] @@ -1863,8 +2314,8 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", - "http", - "http-body", + "http 1.4.0", + "http-body 1.0.1", "pin-project-lite", ] @@ -1880,6 +2331,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "hybrid-array" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" +dependencies = [ + "typenum", +] + [[package]] name = "hydration_context" version = "0.3.0" @@ -1905,8 +2365,8 @@ dependencies = [ "futures-channel", "futures-core", "h2", - "http", - "http-body", + "http 1.4.0", + "http-body 1.0.1", "httparse", "httpdate", "itoa", @@ -1923,32 +2383,17 @@ version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "http", + "http 1.4.0", "hyper", "hyper-util", "rustls", + "rustls-native-certs", "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", ] -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - [[package]] name = "hyper-util" version = "0.1.19" @@ -1960,8 +2405,8 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "http", - "http-body", + "http 1.4.0", + "http-body 1.0.1", "hyper", "ipnet", "libc", @@ -2185,12 +2630,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "is_terminal_polyfill" -version = "1.70.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" - [[package]] name = "itertools" version = "0.14.0" @@ -2202,9 +2641,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" @@ -2229,7 +2668,7 @@ checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -2418,7 +2857,7 @@ dependencies = [ "quote", "rstml", "serde", - "syn 2.0.111", + "syn", "walkdir", ] @@ -2441,7 +2880,7 @@ dependencies = [ "rstml", "rustc_version", "server_fn_macro", - "syn 2.0.111", + "syn", "uuid", ] @@ -2493,7 +2932,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -2610,6 +3049,15 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +[[package]] +name = "lru" +version = "0.16.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39" +dependencies = [ + "hashbrown 0.16.1", +] + [[package]] name = "lru-slab" version = "0.1.2" @@ -2634,7 +3082,7 @@ dependencies = [ "manyhow-macros", "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -2670,14 +3118,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ "cfg-if", - "digest", + "digest 0.10.7", ] [[package]] -name = "md5" -version = "0.7.0" +name = "md-5" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" +checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98" +dependencies = [ + "cfg-if", + "digest 0.11.3", +] [[package]] name = "memchr" @@ -2701,46 +3153,6 @@ dependencies = [ "walkdir", ] -[[package]] -name = "minio" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3824101357fa899d01c729e4a245776e20a03f2f6645979e86b9d3d5d9c42741" -dependencies = [ - "async-recursion", - "async-trait", - "base64", - "byteorder", - "bytes", - "chrono", - "crc", - "dashmap", - "derivative", - "env_logger", - "futures", - "futures-util", - "hex", - "hmac", - "http", - "hyper", - "lazy_static", - "log", - "md5", - "multimap", - "percent-encoding", - "rand 0.8.6", - "regex", - "reqwest 0.12.25", - "serde", - "serde_json", - "sha2", - "tokio", - "tokio-stream", - "tokio-util", - "urlencoding", - "xmltree", -] - [[package]] name = "mio" version = "1.1.1" @@ -2781,7 +3193,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http", + "http 1.4.0", "httparse", "memchr", "mime", @@ -2789,15 +3201,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "multimap" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" -dependencies = [ - "serde", -] - [[package]] name = "native-tls" version = "0.2.14" @@ -2854,6 +3257,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" +[[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-modular" version = "0.6.1" @@ -2908,12 +3320,6 @@ dependencies = [ "portable-atomic", ] -[[package]] -name = "once_cell_polyfill" -version = "1.70.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" - [[package]] name = "oorandom" version = "11.1.5" @@ -2948,7 +3354,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -2991,6 +3397,24 @@ dependencies = [ "hashbrown 0.14.5", ] +[[package]] +name = "outref" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" + +[[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 0.10.9", +] + [[package]] name = "palette" version = "0.7.6" @@ -3012,7 +3436,7 @@ dependencies = [ "by_address", "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -3067,6 +3491,15 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.2" @@ -3103,7 +3536,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -3113,7 +3546,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf1d70880e76bdc13ba52eafa6239ce793d85c8e43896507e43dd8984ff05b82" dependencies = [ "pest", - "sha2", + "sha2 0.10.9", ] [[package]] @@ -3166,7 +3599,7 @@ dependencies = [ "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -3204,7 +3637,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -3219,6 +3652,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[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" @@ -3232,7 +3675,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "opaque-debug", "universal-hash", ] @@ -3261,7 +3704,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -3286,11 +3729,11 @@ dependencies = [ "byteorder", "bytes", "fallible-iterator", - "hmac", - "md-5", + "hmac 0.12.1", + "md-5 0.10.6", "memchr", "rand 0.9.4", - "sha2", + "sha2 0.10.9", "stringprep", ] @@ -3338,7 +3781,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.111", + "syn", +] + +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", ] [[package]] @@ -3369,7 +3821,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -3385,9 +3837,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -3400,7 +3852,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", "version_check", "yansi", ] @@ -3463,9 +3915,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.42" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -3489,7 +3941,7 @@ dependencies = [ "proc-macro-utils", "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -3631,7 +4083,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -3686,7 +4138,7 @@ dependencies = [ "quote", "refinery-core", "regex", - "syn 2.0.111", + "syn", ] [[package]] @@ -3713,49 +4165,16 @@ dependencies = [ ] [[package]] -name = "regex-syntax" -version = "0.8.8" +name = "regex-lite" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" [[package]] -name = "reqwest" -version = "0.12.25" +name = "regex-syntax" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6eff9328d40131d43bd911d42d79eb6a47312002a4daefc9e37f17e74a7701a" -dependencies = [ - "base64", - "bytes", - "futures-core", - "futures-util", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-tls", - "hyper-util", - "js-sys", - "log", - "native-tls", - "percent-encoding", - "pin-project-lite", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tokio-native-tls", - "tokio-util", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", -] +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "reqwest" @@ -3768,8 +4187,8 @@ dependencies = [ "encoding_rs", "futures-core", "h2", - "http", - "http-body", + "http 1.4.0", + "http-body 1.0.1", "http-body-util", "hyper", "hyper-rustls", @@ -3797,6 +4216,16 @@ dependencies = [ "web-sys", ] +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac 0.12.1", + "subtle", +] + [[package]] name = "rhai" version = "1.23.6" @@ -3824,7 +4253,7 @@ checksum = "d4322a2a4e8cf30771dd9f27f7f37ca9ac8fe812dddd811096a98483080dabe6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -3865,7 +4294,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.111", + "syn", "syn_derive", "thiserror 2.0.17", ] @@ -3991,9 +4420,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "same-file" @@ -4019,6 +4448,20 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[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" @@ -4120,7 +4563,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -4201,7 +4644,7 @@ dependencies = [ "dashmap", "futures", "gloo-net", - "http", + "http 1.4.0", "js-sys", "pin-project-lite", "rustc_version", @@ -4232,7 +4675,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.111", + "syn", "xxhash-rust", ] @@ -4243,7 +4686,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63eb08f80db903d3c42f64e60ebb3875e0305be502bdc064ec0a0eab42207f00" dependencies = [ "server_fn_macro", - "syn 2.0.111", + "syn", ] [[package]] @@ -4253,8 +4696,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", - "cpufeatures", - "digest", + "cpufeatures 0.2.17", + "digest 0.10.7", +] + +[[package]] +name = "sha1" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "digest 0.11.3", ] [[package]] @@ -4264,8 +4718,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", - "digest", + "cpufeatures 0.2.17", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "digest 0.11.3", ] [[package]] @@ -4296,6 +4761,16 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + [[package]] name = "siphasher" version = "1.0.1" @@ -4398,6 +4873,22 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "spin" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -4451,7 +4942,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -4462,20 +4953,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.111" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -4491,7 +4971,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -4511,7 +4991,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -4650,7 +5130,7 @@ checksum = "5af50a5123e480e7ee8961e6456f63530816875d0a19cb73060b8e61dd2a95fb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -4703,7 +5183,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -4714,7 +5194,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -4825,7 +5305,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -4899,9 +5379,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.17" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", @@ -5020,8 +5500,8 @@ dependencies = [ "bitflags", "bytes", "futures-util", - "http", - "http-body", + "http 1.4.0", + "http-body 1.0.1", "iri-string", "pin-project-lite", "tower", @@ -5043,9 +5523,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -5061,14 +5541,14 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] name = "tracing-core" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -5117,11 +5597,11 @@ checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" dependencies = [ "bytes", "data-encoding", - "http", + "http 1.4.0", "httparse", "log", "rand 0.9.4", - "sha1", + "sha1 0.10.6", "thiserror 2.0.17", "utf-8", ] @@ -5152,7 +5632,7 @@ checksum = "1ecb9ecf7799210407c14a8cfdfe0173365780968dc57973ed082211958e0b18" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -5163,7 +5643,7 @@ checksum = "0e48cea23f68d1f78eb7bc092881b6bb88d3d6b5b7e6234f6f9c911da1ffb221" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -5174,9 +5654,9 @@ checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "ucd-trie" @@ -5229,7 +5709,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "subtle", ] @@ -5251,12 +5731,6 @@ dependencies = [ "serde", ] -[[package]] -name = "urlencoding" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" - [[package]] name = "utf-8" version = "0.7.6" @@ -5275,12 +5749,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - [[package]] name = "uuid" version = "1.19.0" @@ -5310,6 +5778,12 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + [[package]] name = "walkdir" version = "2.5.0" @@ -5395,7 +5869,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.111", + "syn", "wasm-bindgen-shared", ] @@ -5437,7 +5911,7 @@ checksum = "7150335716dce6028bead2b848e72f47b45e7b9422f64cccdc23bedca89affc1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -5471,8 +5945,8 @@ checksum = "56481f8ed1a9f9ae97ea7b08a5e2b12e8adf9a7818a6ba952b918e09c7be8bf0" dependencies = [ "base16", "quote", - "sha2", - "syn 2.0.111", + "sha2 0.10.9", + "syn", ] [[package]] @@ -5545,7 +6019,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -5556,7 +6030,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -5838,19 +6312,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] -name = "xml-rs" -version = "0.8.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" - -[[package]] -name = "xmltree" -version = "0.11.0" +name = "xmlparser" +version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b619f8c85654798007fb10afa5125590b43b088c225a25fc2fec100a9fad0fc6" -dependencies = [ - "xml-rs", -] +checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" [[package]] name = "xxhash-rust" @@ -5894,7 +6359,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", "synstructure", ] @@ -5915,7 +6380,7 @@ checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] [[package]] @@ -5935,7 +6400,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", "synstructure", ] @@ -5975,5 +6440,5 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn", ] diff --git a/README.md b/README.md index ee13da4..459cba0 100644 --- a/README.md +++ b/README.md @@ -64,10 +64,11 @@ You can optionally configure the build mode and other settings by editing `.env` - `BUILD_MODE="release"`: Optimised build, smaller binaries, slower compilation. - Database, SMTP, and S3 storage configurations. - Local storage uses `S3_ENDPOINT_URL`, `S3_ACCESS_KEY`, `S3_SECRET_KEY`, - `S3_BUCKET_NAME`, `S3_REGION`, and `S3_FORCE_PATH_STYLE`. + `S3_BUCKET_NAME`, `S3_REGION`, `S3_FORCE_PATH_STYLE`, and + `S3_PRESIGNED_URL_TTL_SECONDS`. - The default local S3 API endpoint is `http://127.0.0.1:9000/`, with region `us-east-1`, bucket `memory-map`, and path-style addressing enabled for - RustFS. + RustFS. Presigned media URLs default to a seven-day lifetime. ### 4. Start database & storage diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 858f1d3..0d85693 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -9,6 +9,13 @@ anyhow = "1.0" argon2 = "0.5" async-graphql = "7.1" async-graphql-axum = "7.1" +aws-credential-types = "1.2.14" +aws-sdk-s3 = { version = "1.133.0", default-features = false, features = [ + "default-https-client", + "http-1x", + "rt-tokio", + "sigv4a" +] } axum = { version = "0.8", features = ["multipart"] } axum-extra = { version = "0.12", features = [ "cookie", @@ -32,7 +39,6 @@ lettre = { version = "0.11", features = [ "tokio1", "tokio1-native-tls" ] } -minio = "0.3" moka = { version = "0.12", features = ["future"] } postgres-types = { version = "0.2", features = ["derive"] } rand = "0.8" diff --git a/backend/src/controllers/api/locations.rs b/backend/src/controllers/api/locations.rs index 1b9a5a1..4fea312 100644 --- a/backend/src/controllers/api/locations.rs +++ b/backend/src/controllers/api/locations.rs @@ -8,7 +8,6 @@ use { ERR_MULTIPART_MISSING_FILENAME, ERR_MULTIPART_MISSING_NAME, ERR_UNSUPPORTED_FILE_TYPE, - ERR_UPLOAD_STORAGE, }, errors::AppError, graphql::{ @@ -134,21 +133,19 @@ pub async fn post( let mut uploaded_objects = Vec::new(); for file in files { + let FileData { + filename, + content_type, + bytes, + } = file; tracing::debug!( " - Name: {}, Type: {}, Size: {} bytes", - file.filename, - file.content_type, - file.bytes.len() + filename, + content_type, + bytes.len() ); - state - .inner - .s3_client - .put_object_content(&state.inner.bucket_name, &file.filename, file.bytes) - .content_type(file.content_type) - .send() - .await - .context(ERR_UPLOAD_STORAGE)?; + state.inner.storage.upload_object(&filename, bytes, content_type).await?; let client = state.inner.pool.get().await.context(ERR_DB_CLIENT)?; let location = if let (Some(latitude), Some(longitude)) = (latitude, longitude) { @@ -162,7 +159,7 @@ pub async fn post( match Mutation::upsert_s3_object_worker( &client, - file.filename, + filename, made_on.clone(), location, user_id, diff --git a/backend/src/errors.rs b/backend/src/errors.rs index f9b2bea..5cc8e4d 100644 --- a/backend/src/errors.rs +++ b/backend/src/errors.rs @@ -115,12 +115,6 @@ impl From> for AppError { } } -impl From for AppError { - fn from(err: minio::s3::error::Error) -> Self { - AppError::Internal(anyhow::anyhow!(err)) - } -} - impl From for AppError { fn from(err: argon2::password_hash::Error) -> Self { AppError::Internal(anyhow::anyhow!("{}{}", ERR_HASHING, err)) diff --git a/backend/src/graphql/objects/s3_object.rs b/backend/src/graphql/objects/s3_object.rs index 90d9ed5..e54482f 100644 --- a/backend/src/graphql/objects/s3_object.rs +++ b/backend/src/graphql/objects/s3_object.rs @@ -19,11 +19,9 @@ use { ID, Object, }, - axum::http::Method, deadpool_postgres::Manager, futures::future::join_all, jiff::Timestamp, - minio::s3::types::S3Api, postgres_types::{ FromSql, ToSql, @@ -253,12 +251,7 @@ impl S3Object { ctx: &Context<'_>, ) -> Result { let data = ctx.data::>>()?; - Ok(data - .s3_client - .get_presigned_object_url(&data.bucket_name, &self.name, Method::GET) - .send() - .await? - .url) + data.storage.presigned_get_url(&self.name).await.map_err(GraphQLError::from) } async fn content_type( @@ -266,14 +259,6 @@ impl S3Object { ctx: &Context<'_>, ) -> Result { let data = ctx.data::>>()?; - data.s3_client - .get_object(&data.bucket_name, &self.name) - .send() - .await? - .headers - .get("Content-Type") - .and_then(|content_type| content_type.to_str().ok()) - .map(|s| s.to_string()) - .ok_or_else(|| "Invalid Content-Type".into()) + data.storage.object_content_type(&self.name).await.map_err(GraphQLError::from) } } diff --git a/backend/src/graphql/queries/mutation.rs b/backend/src/graphql/queries/mutation.rs index a804791..bc7ca4a 100644 --- a/backend/src/graphql/queries/mutation.rs +++ b/backend/src/graphql/queries/mutation.rs @@ -38,6 +38,7 @@ use { User, }, }, + storage::StorageClient, }, anyhow::Context as AnyhowContext, argon2::{ @@ -66,11 +67,6 @@ use { email_address::EmailAddress, futures::future::join_all, jiff::Timestamp, - minio::s3::{ - Client as S3Client, - builders::ObjectToDelete, - types::S3Api, - }, rand::{ Rng, distributions::Alphanumeric, @@ -117,8 +113,7 @@ pub struct Mutation; impl Mutation { pub async fn delete_s3_objects_worker( db_client: &Client, - s3_client: &S3Client, - bucket_name: &str, + storage: &StorageClient, ids: &[i64], ) -> Result, AppError> { tracing::debug!("IDs to delete: {:?}", ids); @@ -138,17 +133,13 @@ impl Mutation { )) })?; - let objects_to_delete: Vec = - objects.iter().map(|object| ObjectToDelete::from(&object.name)).collect(); + let objects_to_delete: Vec = + objects.iter().map(|object| object.name.clone()).collect(); tracing::debug!("Objects to delete: {:?}", objects_to_delete); if !objects_to_delete.is_empty() { - s3_client - .delete_objects::<_, ObjectToDelete>(bucket_name, objects_to_delete) - .send() - .await - .context("Failed to delete objects from S3 storage")?; + storage.delete_objects(&objects_to_delete).await?; } Ok(objects) @@ -312,8 +303,7 @@ impl Mutation { ) -> Result, GraphQLError> { let user_id = ctx.data_opt::().ok_or_else(|| GraphQLError::new("Unauthorized"))?.0; let wrapper = ContextWrapper(ctx); - let bucket_name = wrapper.get_bucket_name()?; - let s3_client = wrapper.get_s3_client()?; + let storage = wrapper.get_storage_client()?; let client = wrapper.get_db_client().await?; let ids: Vec = ids .into_iter() @@ -345,7 +335,7 @@ impl Mutation { .ok_or_else(|| GraphQLError::new("Forbidden"))?; } - let result = Self::delete_s3_objects_worker(&client, s3_client, bucket_name, &ids) + let result = Self::delete_s3_objects_worker(&client, storage, &ids) .await .map_err(GraphQLError::from)?; diff --git a/backend/src/lib.rs b/backend/src/lib.rs index 0471107..59567ab 100644 --- a/backend/src/lib.rs +++ b/backend/src/lib.rs @@ -21,7 +21,6 @@ use { Pool, }, deadpool_postgres::Manager, - minio::s3, moka::future::Cache, std::{ fmt, @@ -43,6 +42,9 @@ pub mod db; pub mod email; pub mod errors; pub mod graphql; +pub mod storage; + +use storage::StorageClient; #[derive(Debug, serde::Deserialize, Clone)] pub struct Config { @@ -60,6 +62,7 @@ pub struct Config { pub s3_bucket_name: String, pub s3_region: String, pub s3_force_path_style: bool, + pub s3_presigned_url_ttl_seconds: u64, pub server_host: String, pub server_port: u16, pub cors_allowed_origins: String, @@ -72,10 +75,18 @@ impl Config { .map_err(errors::AppError::from)? .set_default("s3_force_path_style", true) .map_err(errors::AppError::from)? + .set_default("s3_presigned_url_ttl_seconds", 604_800) + .map_err(errors::AppError::from)? .add_source(config::Environment::default().separator("__")) .build() .map_err(errors::AppError::from)?; - cfg.try_deserialize().map_err(errors::AppError::from) + let config: Self = cfg.try_deserialize().map_err(errors::AppError::from)?; + if !(1 ..= 604_800).contains(&config.s3_presigned_url_ttl_seconds) { + return Err(errors::AppError::Internal(anyhow::anyhow!( + "s3_presigned_url_ttl_seconds must be between 1 and 604800" + ))); + } + Ok(config) } } @@ -85,8 +96,7 @@ pub struct UserId(pub i64); pub struct SharedState>> { pub pool: Pool, - pub s3_client: s3::Client, - pub bucket_name: String, + pub storage: StorageClient, pub last_modified: AtomicU64, pub response_cache: Cache, pub key: Key, @@ -145,8 +155,7 @@ impl>> fmt::Debug for SharedState { ) -> fmt::Result { f.debug_struct("SharedState") .field("pool", &"Pool") - .field("s3_client", &self.s3_client) - .field("bucket_name", &self.bucket_name) + .field("storage", &self.storage) .field("last_modified", &self.last_modified) .field("response_cache", &"Cache") .field("enforcer", &"Enforcer") @@ -163,19 +172,11 @@ impl<'a> ContextWrapper<'a> { Ok(pool.get().await?) } - pub fn get_s3_client(&self) -> Result<&s3::Client, GraphQLError> { + pub fn get_storage_client(&self) -> Result<&StorageClient, GraphQLError> { Ok(&self .0 .data::>>()? - .s3_client) - } - - pub fn get_bucket_name(&self) -> Result<&str, GraphQLError> { - Ok(self - .0 - .data::>>()? - .bucket_name - .as_str()) + .storage) } } diff --git a/backend/src/main.rs b/backend/src/main.rs index 820dcbf..3ed10e6 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -62,6 +62,7 @@ use { query::Query, }, migrations, + storage::StorageClient, }, casbin::{ CoreApi, @@ -73,11 +74,6 @@ use { Runtime, }, dotenvy::dotenv, - minio::s3::{ - ClientBuilder, - creds::StaticProvider, - http::BaseUrl, - }, moka::future::Cache, std::{ collections::hash_map::DefaultHasher, @@ -259,28 +255,14 @@ async fn main() -> anyhow::Result<()> { .context("Failed to run database migrations")?; } - // Initialise S3 client - let mut base_url = - cfg.s3_endpoint_url.parse::().context("Failed to parse S3 endpoint URL")?; - base_url.region.clone_from(&cfg.s3_region); - if cfg.s3_force_path_style { - base_url.virtual_style = false; - } + // Initialise S3 storage client tracing::info!( - "S3 endpoint configured: `{:?}` (region: {}, force path-style: {})", - base_url, + "S3 endpoint configured: {} (region: {}, force path-style: {})", + cfg.s3_endpoint_url, cfg.s3_region, cfg.s3_force_path_style ); - - let static_provider = StaticProvider::new(&cfg.s3_access_key, &cfg.s3_secret_key, None); - - let s3_client = ClientBuilder::new(base_url) - .provider(Some(Box::new(static_provider))) - .build() - .context("Failed to build S3 client")?; - - let bucket_name = cfg.s3_bucket_name.clone(); + let storage = StorageClient::from_config(&cfg).context("Failed to build S3 storage client")?; let last_modified = AtomicU64::new( SystemTime::now() @@ -302,8 +284,7 @@ async fn main() -> anyhow::Result<()> { let key = Key::from(cfg.cookie_secret.as_bytes()); let shared_state = Arc::new(SharedState { pool, - s3_client, - bucket_name, + storage, last_modified, response_cache, key: key.clone(), diff --git a/backend/src/storage.rs b/backend/src/storage.rs new file mode 100644 index 0000000..ec0fd38 --- /dev/null +++ b/backend/src/storage.rs @@ -0,0 +1,222 @@ +use { + crate::{ + Config, + constants::ERR_UPLOAD_STORAGE, + }, + anyhow::Context, + aws_credential_types::Credentials, + aws_sdk_s3::{ + Client, + config::{ + BehaviorVersion, + Region, + }, + error::SdkError, + operation::{ + create_bucket::CreateBucketError, + head_bucket::HeadBucketError, + }, + presigning::PresigningConfig, + primitives::ByteStream, + types::{ + Delete, + ObjectIdentifier, + }, + }, + std::{ + fmt, + time::Duration, + }, +}; + +#[derive(Clone)] +pub struct StorageClient { + client: Client, + bucket_name: String, + presigning_config: PresigningConfig, +} + +impl StorageClient { + pub fn from_config(config: &Config) -> anyhow::Result { + let credentials = Credentials::new( + config.s3_access_key.clone(), + config.s3_secret_key.clone(), + None, + None, + "memory-map", + ); + let sdk_config = aws_sdk_s3::Config::builder() + .behavior_version(BehaviorVersion::latest()) + .region(Region::new(config.s3_region.clone())) + .credentials_provider(credentials) + .endpoint_url(config.s3_endpoint_url.clone()) + .force_path_style(config.s3_force_path_style) + .build(); + let presigning_config = + PresigningConfig::expires_in(Duration::from_secs(config.s3_presigned_url_ttl_seconds)) + .context("Failed to configure S3 presigned URL expiry")?; + + Ok(Self { + client: Client::from_conf(sdk_config), + bucket_name: config.s3_bucket_name.clone(), + presigning_config, + }) + } + + pub async fn upload_object( + &self, + object_name: &str, + bytes: impl Into, + content_type: impl Into, + ) -> anyhow::Result<()> { + self.client + .put_object() + .bucket(&self.bucket_name) + .key(object_name) + .body(bytes.into()) + .content_type(content_type.into()) + .send() + .await + .context(ERR_UPLOAD_STORAGE)?; + Ok(()) + } + + pub async fn object_content_type( + &self, + object_name: &str, + ) -> anyhow::Result { + let output = self + .client + .head_object() + .bucket(&self.bucket_name) + .key(object_name) + .send() + .await + .context("Failed to read S3 object metadata")?; + output + .content_type() + .map(str::to_string) + .context("S3 object response did not include Content-Type") + } + + pub async fn presigned_get_url( + &self, + object_name: &str, + ) -> anyhow::Result { + let request = self + .client + .get_object() + .bucket(&self.bucket_name) + .key(object_name) + .presigned(self.presigning_config.clone()) + .await + .context("Failed to generate S3 presigned GET URL")?; + Ok(request.uri().to_string()) + } + + pub async fn delete_objects( + &self, + object_names: &[String], + ) -> anyhow::Result<()> { + if object_names.is_empty() { + return Ok(()); + } + + let mut objects = Vec::with_capacity(object_names.len()); + for object_name in object_names { + objects.push( + ObjectIdentifier::builder() + .key(object_name) + .build() + .context("Failed to build S3 delete object identifier")?, + ); + } + let delete = Delete::builder() + .set_objects(Some(objects)) + .build() + .context("Failed to build S3 delete request")?; + + let output = self + .client + .delete_objects() + .bucket(&self.bucket_name) + .delete(delete) + .send() + .await + .context("Failed to delete objects from S3 storage")?; + let errors = output.errors(); + if !errors.is_empty() { + let details = errors + .iter() + .take(3) + .map(|error| { + let message = + error.message().map(|message| format!(" ({message})")).unwrap_or_default(); + format!( + "{}: {}{}", + error.key().unwrap_or(""), + error.code().unwrap_or("unknown error"), + message + ) + }) + .collect::>() + .join("; "); + anyhow::bail!("S3 reported {} failed object delete(s): {}", errors.len(), details); + } + Ok(()) + } + + pub async fn ensure_bucket_ready(&self) -> anyhow::Result<()> { + self.client.list_buckets().send().await.context("Failed to list S3 buckets")?; + + if self.head_bucket().await? { + return Ok(()); + } + + match self.client.create_bucket().bucket(&self.bucket_name).send().await { + Ok(_) => {} + Err(error) if create_bucket_error_means_existing_bucket(&error) => {} + Err(error) => { + return Err(error).context("Failed to create S3 bucket"); + } + } + + self.client + .head_bucket() + .bucket(&self.bucket_name) + .send() + .await + .context("Failed to verify S3 bucket after readiness check")?; + Ok(()) + } + + async fn head_bucket(&self) -> anyhow::Result { + match self.client.head_bucket().bucket(&self.bucket_name).send().await { + Ok(_) => Ok(true), + Err(error) if head_bucket_error_is_not_found(&error) => Ok(false), + Err(error) => Err(error).context("Failed to check S3 bucket readiness"), + } + } +} + +impl fmt::Debug for StorageClient { + fn fmt( + &self, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + f.debug_struct("StorageClient") + .field("bucket_name", &self.bucket_name) + .field("presigning_config", &self.presigning_config) + .finish_non_exhaustive() + } +} + +fn head_bucket_error_is_not_found(error: &SdkError) -> bool { + error.as_service_error().is_some_and(HeadBucketError::is_not_found) +} + +fn create_bucket_error_means_existing_bucket(error: &SdkError) -> bool { + error.as_service_error().is_some_and(|error| { + error.is_bucket_already_exists() || error.is_bucket_already_owned_by_you() + }) +} diff --git a/devenv/flake.nix b/devenv/flake.nix index 055f0f5..431d858 100644 --- a/devenv/flake.nix +++ b/devenv/flake.nix @@ -472,8 +472,6 @@ env = { # Required by rust-analyzer RUST_SRC_PATH = "${config.packages.rustToolchain}/lib/rustlib/src/rust/library"; - # Required by minio-rs dependency - LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.openssl ]; }; inherit (pre-commit-check) shellHook; From 08f5c3fcb0afbaf90dd91419492fa6eae4109c0a Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Tue, 26 May 2026 23:30:33 +0100 Subject: [PATCH 09/28] Add storage bootstrap helper and tests --- Cargo.lock | 1 + README.md | 3 + backend/Cargo.toml | 3 + .../src/bin/memory-map-storage-bootstrap.rs | 135 ++++++++++++++++++ backend/src/storage.rs | 98 ++++++++++++- backend/tests/storage.rs | 122 ++++++++++++++++ devenv/flake.nix | 103 ++++++------- justfile | 12 +- 8 files changed, 412 insertions(+), 65 deletions(-) create mode 100644 backend/src/bin/memory-map-storage-bootstrap.rs create mode 100644 backend/tests/storage.rs diff --git a/Cargo.lock b/Cargo.lock index 2bed172..405a355 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -781,6 +781,7 @@ dependencies = [ "postgres-types", "rand 0.8.6", "refinery", + "reqwest", "serde", "serde_json", "shared", diff --git a/README.md b/README.md index 459cba0..aa8612f 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,9 @@ The project uses [Just](https://github.com/casey/just) as a task runner. - `just deny`: Check Rust dependencies with `cargo-deny`. - `just doc`: Build documentation with warnings treated as errors and run ASCII/link checks. - `just test`: Run the workspace test suite. +- `just storage-test`: Run ignored storage integration tests against the + configured S3-compatible endpoint. Missing local storage skips by default; set + `STORAGE_TEST_REQUIRE_SERVICE=true` to fail instead. - `just frontend-build`: Build the frontend with Trunk. - `just verify`: Run the full verification suite before submitting a PR. - `just regenerate-schema`: Introspect the backend and update the frontend GraphQL schema. diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 0d85693..ce5aac9 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -55,5 +55,8 @@ tower-http = { version = "0.6", features = ["cors"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } +[dev-dependencies] +reqwest = { version = "0.13", default-features = false, features = ["rustls"] } + [lints] workspace = true diff --git a/backend/src/bin/memory-map-storage-bootstrap.rs b/backend/src/bin/memory-map-storage-bootstrap.rs new file mode 100644 index 0000000..9435827 --- /dev/null +++ b/backend/src/bin/memory-map-storage-bootstrap.rs @@ -0,0 +1,135 @@ +use { + anyhow::Context, + backend::storage::{ + StorageClient, + StorageConfig, + }, + std::{ + io::{ + Read, + Write, + }, + net::{ + TcpStream, + ToSocketAddrs, + }, + time::Duration, + }, +}; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let config = StorageConfig::from_env().context("Failed to read storage bootstrap config")?; + ensure_rustfs_health(&config.endpoint_url) + .context("Failed to verify RustFS health endpoint")?; + let storage = + StorageClient::from_storage_config(&config).context("Failed to build storage client")?; + storage.ensure_bucket_ready().await.context("Failed to ensure S3 bucket readiness")?; + Ok(()) +} + +fn ensure_rustfs_health(endpoint_url: &str) -> anyhow::Result<()> { + let endpoint = parse_http_endpoint(endpoint_url)?; + let timeout = Duration::from_secs(5); + let mut stream = connect_with_timeout(&endpoint.host, endpoint.port, timeout)?; + stream.set_read_timeout(Some(timeout))?; + stream.set_write_timeout(Some(timeout))?; + write!( + stream, + "GET {} HTTP/1.1\r\nHost: {}\r\nConnection: close\r\n\r\n", + endpoint.health_path, endpoint.authority + )?; + + let mut response = String::new(); + stream.read_to_string(&mut response)?; + let (headers, body) = response + .split_once("\r\n\r\n") + .context("RustFS health response did not contain HTTP headers")?; + let status_code = headers + .lines() + .next() + .and_then(|status| status.split_whitespace().nth(1)) + .context("RustFS health response did not contain an HTTP status")?; + if status_code != "200" { + anyhow::bail!("RustFS health endpoint returned HTTP {status_code}"); + } + if !(body.contains("\"service\"") && body.contains("\"rustfs-endpoint\"")) { + anyhow::bail!("RustFS health endpoint did not identify a RustFS service"); + } + Ok(()) +} + +#[derive(Debug)] +struct HttpEndpoint { + authority: String, + host: String, + port: u16, + health_path: String, +} + +fn parse_http_endpoint(endpoint_url: &str) -> anyhow::Result { + let endpoint_url = endpoint_url.trim().trim_end_matches('/'); + let rest = endpoint_url + .strip_prefix("http://") + .context("RustFS bootstrap currently supports only http:// S3 endpoints")?; + let (authority, base_path) = rest.split_once('/').unwrap_or((rest, "")); + if authority.is_empty() { + anyhow::bail!("S3 endpoint URL is missing a host"); + } + let (host, port) = parse_authority(authority)?; + let base_path = base_path.trim_matches('/'); + let health_path = if base_path.is_empty() { + "/health/ready".to_string() + } else { + format!("/{base_path}/health/ready") + }; + + Ok(HttpEndpoint { + authority: authority.to_string(), + host, + port, + health_path, + }) +} + +fn parse_authority(authority: &str) -> anyhow::Result<(String, u16)> { + if let Some(rest) = authority.strip_prefix('[') { + let (host, rest) = + rest.split_once(']').context("Bracketed IPv6 endpoint is missing a closing bracket")?; + let port = rest.strip_prefix(':').map(parse_port).transpose()?.unwrap_or(80); + return Ok((host.to_string(), port)); + } + + let (host, port) = if let Some((host, port)) = authority.split_once(':') { + (host.to_string(), parse_port(port)?) + } else { + (authority.to_string(), 80) + }; + if host.is_empty() { + anyhow::bail!("S3 endpoint URL is missing a host"); + } + Ok((host, port)) +} + +fn parse_port(port: &str) -> anyhow::Result { + port.parse().context("S3 endpoint URL port must be a valid TCP port") +} + +fn connect_with_timeout( + host: &str, + port: u16, + timeout: Duration, +) -> anyhow::Result { + let mut last_error = None; + for address in (host, port).to_socket_addrs()? { + match TcpStream::connect_timeout(&address, timeout) { + Ok(stream) => return Ok(stream), + Err(error) => last_error = Some(error), + } + } + + if let Some(error) = last_error { + return Err(error).with_context(|| format!("Failed to connect to {host}:{port}")); + } + anyhow::bail!("S3 endpoint URL resolved no addresses for {host}:{port}"); +} diff --git a/backend/src/storage.rs b/backend/src/storage.rs index ec0fd38..c039b7d 100644 --- a/backend/src/storage.rs +++ b/backend/src/storage.rs @@ -24,11 +24,67 @@ use { }, }, std::{ + env, fmt, time::Duration, }, }; +#[derive(Clone, Debug)] +pub struct StorageConfig { + pub endpoint_url: String, + pub access_key: String, + pub secret_key: String, + pub bucket_name: String, + pub region: String, + pub force_path_style: bool, + pub presigned_url_ttl_seconds: u64, +} + +impl StorageConfig { + pub const MAX_PRESIGNED_URL_TTL_SECONDS: u64 = 604_800; + + pub fn from_env() -> anyhow::Result { + let config = Self { + endpoint_url: required_env("S3_ENDPOINT_URL")?, + access_key: required_env("S3_ACCESS_KEY")?, + secret_key: required_env("S3_SECRET_KEY")?, + bucket_name: required_env("S3_BUCKET_NAME")?, + region: env_or_default("S3_REGION", "us-east-1"), + force_path_style: parse_bool_env("S3_FORCE_PATH_STYLE", true)?, + presigned_url_ttl_seconds: env_or_default("S3_PRESIGNED_URL_TTL_SECONDS", "604800") + .parse() + .context("S3_PRESIGNED_URL_TTL_SECONDS must be an unsigned integer")?, + }; + config.validate()?; + Ok(config) + } + + pub fn validate(&self) -> anyhow::Result<()> { + if !(1 ..= Self::MAX_PRESIGNED_URL_TTL_SECONDS).contains(&self.presigned_url_ttl_seconds) { + anyhow::bail!( + "s3_presigned_url_ttl_seconds must be between 1 and {}", + Self::MAX_PRESIGNED_URL_TTL_SECONDS + ); + } + Ok(()) + } +} + +impl From<&Config> for StorageConfig { + fn from(config: &Config) -> Self { + Self { + endpoint_url: config.s3_endpoint_url.clone(), + access_key: config.s3_access_key.clone(), + secret_key: config.s3_secret_key.clone(), + bucket_name: config.s3_bucket_name.clone(), + region: config.s3_region.clone(), + force_path_style: config.s3_force_path_style, + presigned_url_ttl_seconds: config.s3_presigned_url_ttl_seconds, + } + } +} + #[derive(Clone)] pub struct StorageClient { client: Client, @@ -38,27 +94,32 @@ pub struct StorageClient { impl StorageClient { pub fn from_config(config: &Config) -> anyhow::Result { + Self::from_storage_config(&StorageConfig::from(config)) + } + + pub fn from_storage_config(config: &StorageConfig) -> anyhow::Result { + config.validate()?; let credentials = Credentials::new( - config.s3_access_key.clone(), - config.s3_secret_key.clone(), + config.access_key.clone(), + config.secret_key.clone(), None, None, "memory-map", ); let sdk_config = aws_sdk_s3::Config::builder() .behavior_version(BehaviorVersion::latest()) - .region(Region::new(config.s3_region.clone())) + .region(Region::new(config.region.clone())) .credentials_provider(credentials) - .endpoint_url(config.s3_endpoint_url.clone()) - .force_path_style(config.s3_force_path_style) + .endpoint_url(config.endpoint_url.clone()) + .force_path_style(config.force_path_style) .build(); let presigning_config = - PresigningConfig::expires_in(Duration::from_secs(config.s3_presigned_url_ttl_seconds)) + PresigningConfig::expires_in(Duration::from_secs(config.presigned_url_ttl_seconds)) .context("Failed to configure S3 presigned URL expiry")?; Ok(Self { client: Client::from_conf(sdk_config), - bucket_name: config.s3_bucket_name.clone(), + bucket_name: config.bucket_name.clone(), presigning_config, }) } @@ -220,3 +281,26 @@ fn create_bucket_error_means_existing_bucket(error: &SdkError error.is_bucket_already_exists() || error.is_bucket_already_owned_by_you() }) } + +fn required_env(name: &str) -> anyhow::Result { + env::var(name).with_context(|| format!("{name} must be set")) +} + +fn env_or_default( + name: &str, + default: &str, +) -> String { + env::var(name).unwrap_or_else(|_| default.to_string()) +} + +fn parse_bool_env( + name: &str, + default: bool, +) -> anyhow::Result { + let value = env_or_default(name, if default { "true" } else { "false" }); + match value.to_ascii_lowercase().as_str() { + "1" | "true" | "yes" | "on" => Ok(true), + "0" | "false" | "no" | "off" => Ok(false), + _ => anyhow::bail!("{name} must be a boolean"), + } +} diff --git a/backend/tests/storage.rs b/backend/tests/storage.rs new file mode 100644 index 0000000..f2f21c5 --- /dev/null +++ b/backend/tests/storage.rs @@ -0,0 +1,122 @@ +use { + aws_sdk_s3::primitives::ByteStream, + backend::storage::{ + StorageClient, + StorageConfig, + }, + std::{ + env, + time::{ + Duration, + SystemTime, + UNIX_EPOCH, + }, + }, + tokio::{ + net::TcpStream, + time::timeout, + }, +}; + +#[tokio::test] +#[ignore = "requires an S3-compatible storage service"] +async fn storage_roundtrip_against_configured_service() -> anyhow::Result<()> { + let config = storage_config_from_env()?; + if !endpoint_is_reachable(&config.endpoint_url).await? { + return skip_or_fail(format!("storage endpoint is not reachable: {}", config.endpoint_url)); + } + + let storage = StorageClient::from_storage_config(&config)?; + storage.ensure_bucket_ready().await?; + + let prefix = unique_prefix()?; + let first_object = format!("{prefix}/first.txt"); + let second_object = format!("{prefix}/second.bin"); + let first_body = b"memory-map storage regression\n"; + let second_body = b"delete me too\n"; + + storage.upload_object(&first_object, ByteStream::from_static(first_body), "text/plain").await?; + storage + .upload_object( + &second_object, + ByteStream::from_static(second_body), + "application/octet-stream", + ) + .await?; + + assert_eq!(storage.object_content_type(&first_object).await?, "text/plain"); + + let url = storage.presigned_get_url(&first_object).await?; + let body = reqwest::get(url).await?.error_for_status()?.bytes().await?; + assert_eq!(body.as_ref(), first_body); + + storage.delete_objects(&[first_object.clone(), second_object.clone()]).await?; + assert!(storage.object_content_type(&first_object).await.is_err()); + assert!(storage.object_content_type(&second_object).await.is_err()); + + Ok(()) +} + +fn storage_config_from_env() -> anyhow::Result { + let config = StorageConfig { + endpoint_url: env_or_default("S3_ENDPOINT_URL", "http://127.0.0.1:9000/"), + access_key: env_or_default("S3_ACCESS_KEY", "memorymapdev"), + secret_key: env_or_default("S3_SECRET_KEY", "memorymapdevsecret"), + bucket_name: env_or_default("S3_BUCKET_NAME", "memory-map"), + region: env_or_default("S3_REGION", "us-east-1"), + force_path_style: parse_bool_env("S3_FORCE_PATH_STYLE", true)?, + presigned_url_ttl_seconds: env_or_default("S3_PRESIGNED_URL_TTL_SECONDS", "604800") + .parse()?, + }; + config.validate()?; + Ok(config) +} + +async fn endpoint_is_reachable(endpoint_url: &str) -> anyhow::Result { + let url = reqwest::Url::parse(endpoint_url)?; + let host = + url.host_str().ok_or_else(|| anyhow::anyhow!("S3 endpoint URL is missing a host"))?; + let port = url + .port_or_known_default() + .ok_or_else(|| anyhow::anyhow!("S3 endpoint URL is missing a port"))?; + Ok(matches!(timeout(Duration::from_secs(2), TcpStream::connect((host, port))).await, Ok(Ok(_)))) +} + +fn skip_or_fail(message: String) -> anyhow::Result<()> { + if storage_service_required() { + anyhow::bail!("{message}"); + } + + eprintln!("skipping storage integration test: {message}"); + Ok(()) +} + +fn storage_service_required() -> bool { + env::var("STORAGE_TEST_REQUIRE_SERVICE") + .map(|value| matches!(value.to_ascii_lowercase().as_str(), "1" | "true" | "yes" | "on")) + .unwrap_or(false) +} + +fn unique_prefix() -> anyhow::Result { + let now = SystemTime::now().duration_since(UNIX_EPOCH)?; + Ok(format!("storage-regression/{}", now.as_nanos())) +} + +fn env_or_default( + name: &str, + default: &str, +) -> String { + env::var(name).unwrap_or_else(|_| default.to_string()) +} + +fn parse_bool_env( + name: &str, + default: bool, +) -> anyhow::Result { + let value = env_or_default(name, if default { "true" } else { "false" }); + match value.to_ascii_lowercase().as_str() { + "1" | "true" | "yes" | "on" => Ok(true), + "0" | "false" | "no" | "off" => Ok(false), + _ => anyhow::bail!("{name} must be a boolean"), + } +} diff --git a/devenv/flake.nix b/devenv/flake.nix index 431d858..48c39b4 100644 --- a/devenv/flake.nix +++ b/devenv/flake.nix @@ -76,6 +76,25 @@ # For Leptos targets.wasm32-unknown-unknown.stable.rust-std ]; + appRustPlatform = pkgs.makeRustPlatform { + cargo = rustToolchain; + rustc = rustToolchain; + }; + appSource = + let + root = toString ./..; + in + lib.cleanSourceWith { + src = ./..; + filter = + path: type: + let + rel = lib.removePrefix "${root}/" (toString path); + in + !(lib.hasPrefix "target/" rel) + && !(lib.hasPrefix "data/" rel) + && !(lib.hasPrefix "frontend/node_modules/" rel); + }; rustfsPkgs = pkgs.extend (import inputs.rust-overlay); rustfsToolchain = rustfsPkgs.rust-bin.stable.latest.default.override { extensions = [ "rust-src" ]; @@ -88,6 +107,22 @@ rustPlatform = rustfsRustPlatform; rustfsSrc = inputs.rustfs-src; }; + storageBootstrap = appRustPlatform.buildRustPackage { + pname = "memory-map-storage-bootstrap"; + version = "0.1.0"; + src = appSource; + cargoLock.lockFile = ../Cargo.lock; + cargoBuildFlags = [ + "-p" + "backend" + "--bin" + "memory-map-storage-bootstrap" + ]; + doCheck = false; + nativeBuildInputs = [ pkgs.pkg-config ]; + buildInputs = [ pkgs.openssl ]; + meta.mainProgram = "memory-map-storage-bootstrap"; + }; dbName = "db"; postgresPort = 5432; @@ -204,66 +239,19 @@ }; rustfsBootstrap = pkgs.writeShellApplication { name = "memory-map-rustfs-bootstrap"; - runtimeInputs = [ - pkgs.coreutils - pkgs.curl - pkgs.gnugrep - ]; + runtimeInputs = [ storageBootstrap ]; text = '' set -euo pipefail - health_body="$(mktemp)" - response_body="$(mktemp)" - trap 'rm -f "$health_body" "$response_body"' EXIT + export S3_ENDPOINT_URL="${s3EndpointUrl}" + export S3_ACCESS_KEY="${s3AccessKey}" + export S3_SECRET_KEY="${s3SecretKey}" + export S3_BUCKET_NAME="${s3BucketName}" + export S3_REGION="${s3Region}" + export S3_FORCE_PATH_STYLE=true + export S3_PRESIGNED_URL_TTL_SECONDS=604800 - curl --fail --silent --show-error --max-time 5 --output "$health_body" "${s3EndpointUrl}/health/ready" - if ! grep -Eq '"service"[[:space:]]*:[[:space:]]*"rustfs-endpoint"' "$health_body"; then - cat "$health_body" >&2 - echo "RustFS readiness probe did not identify a RustFS service at ${s3EndpointUrl}" >&2 - exit 1 - fi - - auth_args=( - --aws-sigv4 "aws:amz:${s3Region}:s3" - --user "${s3AccessKey}:${s3SecretKey}" - --silent - --show-error - --max-time 5 - ) - - curl --fail "''${auth_args[@]}" "${s3EndpointUrl}/" >/dev/null - - bucket_status="$(curl "''${auth_args[@]}" --head --output "$response_body" --write-out "%{http_code}" "${s3EndpointUrl}/${s3BucketName}" || true)" - case "$bucket_status" in - 200) - exit 0 - ;; - 404) - ;; - *) - cat "$response_body" >&2 - echo "Failed to check bucket ${s3BucketName}; HTTP $bucket_status" >&2 - exit 1 - ;; - esac - - http_code="$(curl "''${auth_args[@]}" --request PUT --output "$response_body" --write-out "%{http_code}" "${s3EndpointUrl}/${s3BucketName}" || true)" - case "$http_code" in - 200|409) - ;; - *) - cat "$response_body" >&2 - echo "Failed to create bucket ${s3BucketName}; HTTP $http_code" >&2 - exit 1 - ;; - esac - - bucket_status="$(curl "''${auth_args[@]}" --head --output "$response_body" --write-out "%{http_code}" "${s3EndpointUrl}/${s3BucketName}" || true)" - if [ "$bucket_status" != 200 ]; then - cat "$response_body" >&2 - echo "Failed to verify bucket ${s3BucketName}; HTTP $bucket_status" >&2 - exit 1 - fi + exec memory-map-storage-bootstrap ''; }; @@ -351,11 +339,12 @@ }; overlayAttrs = { - inherit (config.packages) rustToolchain rustfs; + inherit (config.packages) rustToolchain rustfs storageBootstrap; }; packages.rustToolchain = rustToolchain; packages.rustfs = rustfsPackage; + packages.storageBootstrap = storageBootstrap; # `process-compose.foo` will add a flake package output called "foo". # Therefore, this will add a default package that you can build using diff --git a/justfile b/justfile index d64e152..c7be000 100644 --- a/justfile +++ b/justfile @@ -131,6 +131,16 @@ test *args: fi {{ direnv_prefix }} cargo test "$@" +# Run storage integration tests against a configured S3-compatible service. +[positional-arguments] +storage-test *args: + #!/usr/bin/env bash + set -euo pipefail + if [ "$#" -eq 0 ]; then + set -- --ignored --nocapture + fi + {{ direnv_prefix }} cargo test -p backend --test storage -- "$@" + # Remove build artifacts. clean: {{ direnv_prefix }} cargo clean @@ -155,7 +165,7 @@ filtered recipe filter *args: fi case "$recipe" in - build|check|clippy|deny|doc|fmt|frontend-build|test|verify) ;; + build|check|clippy|deny|doc|fmt|frontend-build|storage-test|test|verify) ;; *) echo "ERROR: unsupported filtered recipe: $recipe" >&2 exit 2 From 6e5359bf2d43eedb492fa186710963c18adc593e Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Wed, 27 May 2026 00:17:48 +0100 Subject: [PATCH 10/28] Add storage integration CI --- .github/workflows/ci.yml | 16 ++++++++++++++++ .github/workflows/update-cargo-deps.yml | 23 ++++++++++++++++++++++- .github/workflows/update-nixpkgs.yml | 23 ++++++++++++++++++++++- .gitignore | 1 + justfile | 19 ++++++++++++++++++- 5 files changed, 79 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d2f62fc..011d53a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -77,3 +77,19 @@ jobs: - uses: DeterminateSystems/nix-installer-action@main - uses: DeterminateSystems/magic-nix-cache-action@main - run: nix develop ./devenv/ --command just frontend-build + + storage-integration: + name: Storage Integration + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: DeterminateSystems/nix-installer-action@main + - uses: DeterminateSystems/magic-nix-cache-action@main + - run: nix develop ./devenv/ --command just storage-ci + - name: Upload process-compose log + if: failure() + uses: actions/upload-artifact@v7 + with: + name: process-compose-log + path: process-compose.log + if-no-files-found: ignore diff --git a/.github/workflows/update-cargo-deps.yml b/.github/workflows/update-cargo-deps.yml index 244296a..df42a5c 100644 --- a/.github/workflows/update-cargo-deps.yml +++ b/.github/workflows/update-cargo-deps.yml @@ -15,6 +15,13 @@ jobs: contents: write pull-requests: write steps: + - name: Generate app token + id: app-token + uses: actions/create-github-app-token@v3 + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + - uses: actions/checkout@v6 - uses: DeterminateSystems/nix-installer-action@main - uses: DeterminateSystems/magic-nix-cache-action@main @@ -22,10 +29,24 @@ jobs: - name: Update Cargo dependencies run: nix develop ./devenv/ --command cargo update + - name: Check for changes + id: diff + run: | + if git diff --quiet Cargo.lock; then + echo "changed=false" >> "$GITHUB_OUTPUT" + else + echo "changed=true" >> "$GITHUB_OUTPUT" + fi + + - name: Disable git hooks + if: steps.diff.outputs.changed == 'true' + run: git config --unset core.hooksPath || true + - name: Create pull request + if: steps.diff.outputs.changed == 'true' uses: peter-evans/create-pull-request@v7 with: - token: ${{ secrets.GITHUB_TOKEN }} + token: ${{ steps.app-token.outputs.token }} commit-message: "chore: update Cargo dependencies" branch: update-cargo-deps title: "chore: update Cargo dependencies" diff --git a/.github/workflows/update-nixpkgs.yml b/.github/workflows/update-nixpkgs.yml index 6703edc..378bbbf 100644 --- a/.github/workflows/update-nixpkgs.yml +++ b/.github/workflows/update-nixpkgs.yml @@ -12,6 +12,13 @@ jobs: contents: write pull-requests: write steps: + - name: Generate app token + id: app-token + uses: actions/create-github-app-token@v3 + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + - uses: actions/checkout@v6 - uses: DeterminateSystems/nix-installer-action@main - uses: DeterminateSystems/magic-nix-cache-action@main @@ -19,10 +26,24 @@ jobs: - name: Update nixpkgs input run: nix flake update nixpkgs --flake ./devenv/ + - name: Check for changes + id: diff + run: | + if git diff --quiet devenv/flake.lock; then + echo "changed=false" >> "$GITHUB_OUTPUT" + else + echo "changed=true" >> "$GITHUB_OUTPUT" + fi + + - name: Disable git hooks + if: steps.diff.outputs.changed == 'true' + run: git config --unset core.hooksPath || true + - name: Create pull request + if: steps.diff.outputs.changed == 'true' uses: peter-evans/create-pull-request@v7 with: - token: ${{ secrets.GITHUB_TOKEN }} + token: ${{ steps.app-token.outputs.token }} commit-message: "chore: update nixpkgs input" branch: update-nixpkgs title: "chore: update nixpkgs input" diff --git a/.gitignore b/.gitignore index 89dd2b7..e17d543 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ data/rustfs/ .direnv/ /result /result-* +process-compose.log .claude/worktrees/ .codex/worktrees/ .pre-commit-config.yaml diff --git a/justfile b/justfile index c7be000..6c4b4dd 100644 --- a/justfile +++ b/justfile @@ -141,6 +141,23 @@ storage-test *args: fi {{ direnv_prefix }} cargo test -p backend --test storage -- "$@" +# Run storage integration tests against the headless local service graph. +storage-ci: + #!/usr/bin/env bash + set -euo pipefail + + log_file="${PROCESS_COMPOSE_LOG:-process-compose.log}" + port="${PROCESS_COMPOSE_PORT:-8080}" + + cleanup() { + {{ direnv_prefix }} nix run ./devenv -- --port "$port" down || true + } + trap cleanup EXIT + + {{ direnv_prefix }} nix run ./devenv -- --port "$port" --log-file "$log_file" --detached -t=false --logs-truncate + {{ direnv_prefix }} nix run ./devenv -- --port "$port" project is-ready --wait + STORAGE_TEST_REQUIRE_SERVICE=true just storage-test + # Remove build artifacts. clean: {{ direnv_prefix }} cargo clean @@ -165,7 +182,7 @@ filtered recipe filter *args: fi case "$recipe" in - build|check|clippy|deny|doc|fmt|frontend-build|storage-test|test|verify) ;; + build|check|clippy|deny|doc|fmt|frontend-build|storage-ci|storage-test|test|verify) ;; *) echo "ERROR: unsupported filtered recipe: $recipe" >&2 exit 2 From 4569ce554b1ba9de00859a531c2405439495f2c6 Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Wed, 27 May 2026 00:25:44 +0100 Subject: [PATCH 11/28] Remove obsolete MinIO advisory ignore --- deny.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/deny.toml b/deny.toml index 7287a0a..da30b3d 100644 --- a/deny.toml +++ b/deny.toml @@ -3,10 +3,6 @@ all-features = true [advisories] ignore = [ - # `derivative` is pulled through minio 0.3.0. There is no safe upgrade for - # the crate itself; replacing the object-storage client should be evaluated - # as a separate dependency migration. - "RUSTSEC-2024-0388", # `instant` is pulled through casbin -> rhai. There is no safe upgrade for # the crate itself; keep this visible in dependency migration work. "RUSTSEC-2024-0384", From 8ffc653659b3dfaaac0a5bacf7f17b4a1660bdef Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Wed, 27 May 2026 00:26:32 +0100 Subject: [PATCH 12/28] Generalize Nix flake update workflow --- .github/workflows/update-nixpkgs.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/update-nixpkgs.yml b/.github/workflows/update-nixpkgs.yml index 378bbbf..b90acab 100644 --- a/.github/workflows/update-nixpkgs.yml +++ b/.github/workflows/update-nixpkgs.yml @@ -1,4 +1,4 @@ -name: Update nixpkgs +name: Update Nix flake inputs on: schedule: @@ -23,8 +23,8 @@ jobs: - uses: DeterminateSystems/nix-installer-action@main - uses: DeterminateSystems/magic-nix-cache-action@main - - name: Update nixpkgs input - run: nix flake update nixpkgs --flake ./devenv/ + - name: Update Nix flake inputs + run: nix flake update --flake ./devenv/ - name: Check for changes id: diff @@ -44,8 +44,8 @@ jobs: uses: peter-evans/create-pull-request@v7 with: token: ${{ steps.app-token.outputs.token }} - commit-message: "chore: update nixpkgs input" - branch: update-nixpkgs - title: "chore: update nixpkgs input" + commit-message: "chore: update Nix flake inputs" + branch: update-nix-flake-inputs + title: "chore: update Nix flake inputs" body: | - Automated weekly update of the `nixpkgs` flake input. + Automated weekly update of moving Nix flake inputs. From 050a97be9e32b92747a38ea59f22dab163a14766 Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Wed, 27 May 2026 01:02:49 +0100 Subject: [PATCH 13/28] Update Nix flake inputs --- devenv/flake.lock | 46 +++++++++++++++++++++++----------------------- devenv/flake.nix | 7 +++++-- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/devenv/flake.lock b/devenv/flake.lock index 1356f97..52d2e66 100644 --- a/devenv/flake.lock +++ b/devenv/flake.lock @@ -8,11 +8,11 @@ "rust-analyzer-src": "rust-analyzer-src" }, "locked": { - "lastModified": 1767596244, - "narHash": "sha256-P4NRZUjYbeuzv4hGrXxfdg0QpdGVoeNn0CMmzIyr398=", + "lastModified": 1779790483, + "narHash": "sha256-2wCMtmVmkCcyHaH6hkrbx7XdUgLYP5E1wl/jc1YxxTY=", "owner": "nix-community", "repo": "fenix", - "rev": "eedfb5a27900e82ec0390acc83d4d226ce86e714", + "rev": "6012e5463531342033571efe294ec880bf13dd95", "type": "github" }, "original": { @@ -64,11 +64,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1765495779, - "narHash": "sha256-MhA7wmo/7uogLxiewwRRmIax70g6q1U/YemqTGoFHlM=", + "lastModified": 1778716662, + "narHash": "sha256-m1Yf0wZ8j1OHjTc2UwHwyQRSnNeSgLJOd7q5Y45hzi4=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "5635c32d666a59ec9a55cab87e898889869f7b71", + "rev": "f7c1a2d347e4c52d5fb8d10cb4d94b5884e546fb", "type": "github" }, "original": { @@ -122,12 +122,12 @@ }, "nixpkgs": { "locked": { - "lastModified": 1765186076, - "narHash": "sha256-hM20uyap1a0M9d344I692r+ik4gTMyj60cQWO+hAYP8=", - "rev": "addf7cf5f383a3101ecfba091b98d0a1263dc9b8", - "revCount": 908783, + "lastModified": 1779560665, + "narHash": "sha256-tpyBcxPpcQb8ukyNF7DoCwfSY3VPsxHoYwj00Cayv5o=", + "rev": "64c08a7ca051951c8eae34e3e3cb1e202fe36786", + "revCount": 1004030, "type": "tarball", - "url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.908783%2Brev-addf7cf5f383a3101ecfba091b98d0a1263dc9b8/019b03a0-b1e4-7f2a-9d10-ad8434116660/source.tar.gz" + "url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.1004030%2Brev-64c08a7ca051951c8eae34e3e3cb1e202fe36786/019e5fd8-b716-7e01-9710-e44ec43dc50b/source.tar.gz" }, "original": { "type": "tarball", @@ -136,11 +136,11 @@ }, "nixpkgs-lib": { "locked": { - "lastModified": 1761765539, - "narHash": "sha256-b0yj6kfvO8ApcSE+QmA6mUfu8IYG6/uU28OFn4PaC8M=", + "lastModified": 1777168982, + "narHash": "sha256-GOkGPcboWE9BmGCRMLX3worL4EMnsnG8MyKmXNeYuhQ=", "owner": "nix-community", "repo": "nixpkgs.lib", - "rev": "719359f4562934ae99f5443f20aa06c2ffff91fc", + "rev": "f5901329dade4a6ea039af1433fb087bd9c1fe14", "type": "github" }, "original": { @@ -151,11 +151,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1767379071, - "narHash": "sha256-EgE0pxsrW9jp9YFMkHL9JMXxcqi/OoumPJYwf+Okucw=", + "lastModified": 1779560665, + "narHash": "sha256-tpyBcxPpcQb8ukyNF7DoCwfSY3VPsxHoYwj00Cayv5o=", "owner": "nixos", "repo": "nixpkgs", - "rev": "fb7944c166a3b630f177938e478f0378e64ce108", + "rev": "64c08a7ca051951c8eae34e3e3cb1e202fe36786", "type": "github" }, "original": { @@ -167,11 +167,11 @@ }, "process-compose-flake": { "locked": { - "lastModified": 1764915241, - "narHash": "sha256-vTqn6IAkZhuuctvkxjhzI1EEybyzwaNd7HJvhF662O8=", + "lastModified": 1767863885, + "narHash": "sha256-XXekPAxzbv1DmHFo3Elmj/vDnvWc1V0jdDUvM0/Wf7k=", "owner": "Platonic-Systems", "repo": "process-compose-flake", - "rev": "36678818ecbd0e06a60740a291c55b683fec79dd", + "rev": "99bea96cf269cfd235833ebdf645b567069fd398", "type": "github" }, "original": { @@ -198,11 +198,11 @@ "rust-analyzer-src": { "flake": false, "locked": { - "lastModified": 1767551763, - "narHash": "sha256-lcA/e3++3aZQSj6xCsBi2VpYyC3Q+oO/oukgfHiL+Ts=", + "lastModified": 1779742949, + "narHash": "sha256-Dk0hnFTXbmNmigsJyQkCz2NEEgtpe+MN500dPnki9Ic=", "owner": "rust-lang", "repo": "rust-analyzer", - "rev": "6a1246b69ca761480b9278df019f717b549cface", + "rev": "462d95ca60fa7360b44258be94105bc20e203684", "type": "github" }, "original": { diff --git a/devenv/flake.nix b/devenv/flake.nix index 48c39b4..ab75ea9 100644 --- a/devenv/flake.nix +++ b/devenv/flake.nix @@ -445,8 +445,7 @@ pkgs.trunk # https://github.com/trunk-rs/trunk/issues/732#issuecomment-2391810077 pkgs.dart-sass - # Stable had 0.2.105 and we needed 0.2.106, so we're using unstable here - pkgs.unstable.wasm-bindgen-cli + pkgs.unstable.wasm-bindgen-cli_0_2_118 # Needed for building in release mode pkgs.binaryen # For link checking in markdown @@ -459,6 +458,10 @@ ]; env = { + # Keep Cargo subcommands on the flake-selected toolchain even + # when the parent shell exports stale toolchain paths. + CARGO = "${config.packages.rustToolchain}/bin/cargo"; + RUSTC = "${config.packages.rustToolchain}/bin/rustc"; # Required by rust-analyzer RUST_SRC_PATH = "${config.packages.rustToolchain}/lib/rustlib/src/rust/library"; }; From bd3b24d33e5e42966576304942e747e763807849 Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Wed, 27 May 2026 01:08:07 +0100 Subject: [PATCH 14/28] Update frontend dependencies --- frontend/package.json | 6 +- frontend/pnpm-lock.yaml | 1340 ++++++++++++++++++---------------- frontend/pnpm-workspace.yaml | 2 + frontend/style/uno.css | 4 +- 4 files changed, 715 insertions(+), 637 deletions(-) create mode 100644 frontend/pnpm-workspace.yaml diff --git a/frontend/package.json b/frontend/package.json index 4ccd4f8..2591d82 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,8 +1,8 @@ { "devDependencies": { - "@unocss/cli": "66.5.4", - "@unocss/preset-wind4": "^66.5.4", - "unocss": "^66.5.4" + "@unocss/cli": "66.7.0", + "@unocss/preset-wind4": "^66.7.0", + "unocss": "^66.7.0" }, "dependencies": { "leaflet": "^1.9.4" diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index d0f2ba9..ca1c43a 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -13,60 +13,28 @@ importers: version: 1.9.4 devDependencies: '@unocss/cli': - specifier: 66.5.4 - version: 66.5.4 + specifier: 66.7.0 + version: 66.7.0 '@unocss/preset-wind4': - specifier: ^66.5.4 - version: 66.5.4 + specifier: ^66.7.0 + version: 66.7.0 unocss: - specifier: ^66.5.4 - version: 66.5.4(postcss@8.5.6)(vite@7.1.12(jiti@2.6.1)) + specifier: ^66.7.0 + version: 66.7.0(vite@7.1.12(jiti@2.7.0)) packages: '@antfu/install-pkg@1.1.0': resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==} - '@antfu/utils@9.3.0': - resolution: {integrity: sha512-9hFT4RauhcUzqOE4f1+frMKLZrgNog5b06I7VmZQV1BkvwvqrbC8EBZf3L1eEL2AKb6rNKjER0sEvJiSP1FXEA==} + '@emnapi/core@1.10.0': + resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} - '@babel/code-frame@7.27.1': - resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} - engines: {node: '>=6.9.0'} + '@emnapi/runtime@1.10.0': + resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} - '@babel/generator@7.28.5': - resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-string-parser@7.27.1': - resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.28.5': - resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.27.7': - resolution: {integrity: sha512-qnzXzDXdr/po3bOTbTIQZ7+TxNKxpkN5IifVLXS+r7qwynkZfPyjZfE7hCXbo7IoO9TNcSyibgONsf2HauUd3Q==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/parser@7.28.5': - resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/template@7.27.2': - resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} - engines: {node: '>=6.9.0'} - - '@babel/traverse@7.27.7': - resolution: {integrity: sha512-X6ZlfR/O/s5EQ/SnUSLzr+6kGnkg8HXGMzpgsMsrJVcfDtH1vIp6ctCN4eZ1LS5c0+te5Cb6Y514fASjMRJ1nw==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.28.5': - resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} - engines: {node: '>=6.9.0'} + '@emnapi/wasi-threads@1.2.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} '@esbuild/aix-ppc64@0.25.12': resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} @@ -227,8 +195,8 @@ packages: '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} - '@iconify/utils@3.0.2': - resolution: {integrity: sha512-EfJS0rLfVuRuJRn4psJHtK2A9TqVnkxPpHY6lYHiB9+8eSuudsxbwMiavocG45ujOo6FJ+CIRlRnlOGinzkaGQ==} + '@iconify/utils@3.1.3': + resolution: {integrity: sha512-LPKOXPn/zV+zis1oOfGWogaXVpqUybF3ZS6SCZIsz8vg0ivVp9+fVqyYB7xq0aiST/VhUQYGO1qo6uoYSiEJqw==} '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -246,235 +214,373 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@napi-rs/wasm-runtime@1.1.4': + resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + + '@oxc-parser/binding-android-arm-eabi@0.131.0': + resolution: {integrity: sha512-t2xicr9pfzkSRYx5aPqZqlLaayIwJTqgQ81Jor31Xep2nGyL2Aq3d0K5wOfeR7VevaSdxaS9dzSQP9xDwn8fDg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxc-parser/binding-android-arm64@0.131.0': + resolution: {integrity: sha512-nlGIod6gw75x1aEDgLS+srj+JRGY0HHm9MI9YgzE/B64l6d6+H3MSP9NOgp0+HTg8tp4vV9rVfgQGgd+TfVZcA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxc-parser/binding-darwin-arm64@0.131.0': + resolution: {integrity: sha512-jukuV6xe5RbQKFo7QD34NDCLDZp4PSOm8rmckhNdH/60ymG5zXbDzGBEyc+nTkuLQNama2aSGCt+CPfpjNTqyw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxc-parser/binding-darwin-x64@0.131.0': + resolution: {integrity: sha512-g3JOo4khe9rslHm5WYaVDWb0HS/M1MLR3I9S8560MkKIcC96VQY00QjOlsuRyfSj/JDXj8i9T7ryPO2RidiXVg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxc-parser/binding-freebsd-x64@0.131.0': + resolution: {integrity: sha512-1hziITDTxjMePnX+dR9ocVT+EuZkQ8wm4FPAbmbEiKG+Phbo73J1ZnPAA6Y/aGsWF3McOFnQuZIktAFwalkfJQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxc-parser/binding-linux-arm-gnueabihf@0.131.0': + resolution: {integrity: sha512-9uRxfXwyKG9+MwmGQBo2ncPNwZH5HTmCETFM2WiuDBNDCW4NC5ttSQkwCAMrTAWgwMzVBH1CP8pM0v7nebCWXQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm-musleabihf@0.131.0': + resolution: {integrity: sha512-mgbLvzRShXOLBdWGInf08Af4q+pfj1xD8hSgLClDZ9of/BXkB6+LIhTH7fihiDUipqB3yoSkKBWaZ3Ejlf5Yag==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm64-gnu@0.131.0': + resolution: {integrity: sha512-OPT8++4aN6j2GJ8+3IZHS/byXoZP4aSBn+FoG6rgBJ2fKwPKXWF3MqrFMNW7NKHM28FLY579xYLxJSfgobEqPA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-arm64-musl@0.131.0': + resolution: {integrity: sha512-vtPiwmfVTAXzaxDKsOXG+LwgRAA7WEnaeHzhS5z0GE89gAK18KSXnly7Z6saXXq6L3dVMyK44uoTI03zKxrpmw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-ppc64-gnu@0.131.0': + resolution: {integrity: sha512-8AW8L7w5cGHSdZPcyZX2yR0+GUODsT15rbRjfdD54rv6DMbtuEB19ysLOpKJlRGfH6UNYNpCHaU1uJWgTWf1/w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-riscv64-gnu@0.131.0': + resolution: {integrity: sha512-vvpjkjEOUsPcsYf8evE4MO3aGx9+3wodXEBOicGNnOwTuAik8eBONNkgSdhkGsAblQmfVHJyanRnpxglddTXIA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-riscv64-musl@0.131.0': + resolution: {integrity: sha512-AqmcNC3fClXX+fxQ6VGEN1667xVFiRBkY0CZmDMSiaeFUsv1+UkBPYYi48IUKcA9/ivvoKNRzQl2I4//kT9F/w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-s390x-gnu@0.131.0': + resolution: {integrity: sha512-7d3jOMKy7RSQCcDLIci+ySll2FgsOMl/GiRux4q2JNv0zg4EdhFISa9idvrdN/HEUIQQJNg6dmveUeJl2YErGA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-x64-gnu@0.131.0': + resolution: {integrity: sha512-JHK/h95qVqVQ+ITER837kcTdwBDFpFaNnOTYGCP0zdUSX/mLKC7tXOoyrTb6vG7iRPwGlcgBil3v2IjYw1FqJA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-x64-musl@0.131.0': + resolution: {integrity: sha512-b2BO82O8azXAyf7EUgOPKu145nWypbNyk07HbU09fkzhm9lEA5oPvaN/M8Nlo7tOErVTa2WOgS4QbOnxAPXdDQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-openharmony-arm64@0.131.0': + resolution: {integrity: sha512-GHO9glZaX7LkX/OGfluEPf1yjg+ehiFbUdowbX6uNWOQhmwKWU4m4+nZ9FJkrHNKuxyI1KKertMdGjVKCApKWA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxc-parser/binding-wasm32-wasi@0.131.0': + resolution: {integrity: sha512-3SkikPaEFoih1N83qLVEDLRLeY4nYsf6JT9SnWiMCQ5lGQdKup6bEuKCqkRiG9dD1IIaFeYz9RjlciPmYoFIWA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@oxc-parser/binding-win32-arm64-msvc@0.131.0': + resolution: {integrity: sha512-Os5bEhryeA2jkH+ZrnZyAC1EP5gs+X4YB1Fjqml7UPD5kU7ecsK1MPEVMfCrdt/GDNpDbavYXiOXOdyJ5b3OPw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxc-parser/binding-win32-ia32-msvc@0.131.0': + resolution: {integrity: sha512-m+jNz9EuF0NXoiptc6B9h5yompZQVW/a5MJeOu5zojfH5yWk82tvF2ccrHkfhgtrS9h9DD5l1Qv8dWlfY7Nz8g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxc-parser/binding-win32-x64-msvc@0.131.0': + resolution: {integrity: sha512-o14Hk8dAyiEUMFEWEgmAwFZvBt1RzAYLM3xeQ+5315JXgVYhoemivgYcbYVRbsFkS71ShMGlAFE0kPnr460rww==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@oxc-project/types@0.131.0': + resolution: {integrity: sha512-PgnWDfV0h+b16XNKbXU7Daib/BFSt/J2mEzfYIBu6JB/wNdlU+kVYXCkGA1A9fWkTbOgbjh4e6NhPeQOYvFhEA==} + '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} - '@quansync/fs@0.1.5': - resolution: {integrity: sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA==} + '@quansync/fs@1.0.0': + resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} - '@rollup/rollup-android-arm-eabi@4.52.5': - resolution: {integrity: sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ==} + '@rollup/rollup-android-arm-eabi@4.60.4': + resolution: {integrity: sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.52.5': - resolution: {integrity: sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA==} + '@rollup/rollup-android-arm64@4.60.4': + resolution: {integrity: sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.52.5': - resolution: {integrity: sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA==} + '@rollup/rollup-darwin-arm64@4.60.4': + resolution: {integrity: sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.52.5': - resolution: {integrity: sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA==} + '@rollup/rollup-darwin-x64@4.60.4': + resolution: {integrity: sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.52.5': - resolution: {integrity: sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA==} + '@rollup/rollup-freebsd-arm64@4.60.4': + resolution: {integrity: sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.52.5': - resolution: {integrity: sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ==} + '@rollup/rollup-freebsd-x64@4.60.4': + resolution: {integrity: sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.52.5': - resolution: {integrity: sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==} + '@rollup/rollup-linux-arm-gnueabihf@4.60.4': + resolution: {integrity: sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==} cpu: [arm] os: [linux] + libc: [glibc] - '@rollup/rollup-linux-arm-musleabihf@4.52.5': - resolution: {integrity: sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==} + '@rollup/rollup-linux-arm-musleabihf@4.60.4': + resolution: {integrity: sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==} cpu: [arm] os: [linux] + libc: [musl] - '@rollup/rollup-linux-arm64-gnu@4.52.5': - resolution: {integrity: sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==} + '@rollup/rollup-linux-arm64-gnu@4.60.4': + resolution: {integrity: sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==} cpu: [arm64] os: [linux] + libc: [glibc] - '@rollup/rollup-linux-arm64-musl@4.52.5': - resolution: {integrity: sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==} + '@rollup/rollup-linux-arm64-musl@4.60.4': + resolution: {integrity: sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==} cpu: [arm64] os: [linux] + libc: [musl] - '@rollup/rollup-linux-loong64-gnu@4.52.5': - resolution: {integrity: sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==} + '@rollup/rollup-linux-loong64-gnu@4.60.4': + resolution: {integrity: sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==} cpu: [loong64] os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-loong64-musl@4.60.4': + resolution: {integrity: sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-ppc64-gnu@4.60.4': + resolution: {integrity: sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==} + cpu: [ppc64] + os: [linux] + libc: [glibc] - '@rollup/rollup-linux-ppc64-gnu@4.52.5': - resolution: {integrity: sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==} + '@rollup/rollup-linux-ppc64-musl@4.60.4': + resolution: {integrity: sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==} cpu: [ppc64] os: [linux] + libc: [musl] - '@rollup/rollup-linux-riscv64-gnu@4.52.5': - resolution: {integrity: sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==} + '@rollup/rollup-linux-riscv64-gnu@4.60.4': + resolution: {integrity: sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==} cpu: [riscv64] os: [linux] + libc: [glibc] - '@rollup/rollup-linux-riscv64-musl@4.52.5': - resolution: {integrity: sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==} + '@rollup/rollup-linux-riscv64-musl@4.60.4': + resolution: {integrity: sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==} cpu: [riscv64] os: [linux] + libc: [musl] - '@rollup/rollup-linux-s390x-gnu@4.52.5': - resolution: {integrity: sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==} + '@rollup/rollup-linux-s390x-gnu@4.60.4': + resolution: {integrity: sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==} cpu: [s390x] os: [linux] + libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.52.5': - resolution: {integrity: sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==} + '@rollup/rollup-linux-x64-gnu@4.60.4': + resolution: {integrity: sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==} cpu: [x64] os: [linux] + libc: [glibc] - '@rollup/rollup-linux-x64-musl@4.52.5': - resolution: {integrity: sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==} + '@rollup/rollup-linux-x64-musl@4.60.4': + resolution: {integrity: sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==} cpu: [x64] os: [linux] + libc: [musl] - '@rollup/rollup-openharmony-arm64@4.52.5': - resolution: {integrity: sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==} + '@rollup/rollup-openbsd-x64@4.60.4': + resolution: {integrity: sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.60.4': + resolution: {integrity: sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.52.5': - resolution: {integrity: sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w==} + '@rollup/rollup-win32-arm64-msvc@4.60.4': + resolution: {integrity: sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.52.5': - resolution: {integrity: sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg==} + '@rollup/rollup-win32-ia32-msvc@4.60.4': + resolution: {integrity: sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.52.5': - resolution: {integrity: sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ==} + '@rollup/rollup-win32-x64-gnu@4.60.4': + resolution: {integrity: sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.52.5': - resolution: {integrity: sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg==} + '@rollup/rollup-win32-x64-msvc@4.60.4': + resolution: {integrity: sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==} cpu: [x64] os: [win32] + '@tybys/wasm-util@0.10.2': + resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} + '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - '@unocss/astro@66.5.4': - resolution: {integrity: sha512-6KsilC1SiTBmEJRMuPl+Mg8KDWB1+DaVoirGZR7BAEtMf2NzrfQcR4+O/3DHtzb38pfb0K1aHCfWwCozHxLlfA==} - peerDependencies: - vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 - peerDependenciesMeta: - vite: - optional: true + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} - '@unocss/cli@66.5.4': - resolution: {integrity: sha512-GltHfmJ27O5VHB/ABkkUWwWT72xGBVwFyhTnhIOut4EPkIurKDnfY5MZFEl2PLlIFnYqIJxeTHMHONVg7pySMg==} - engines: {node: '>=14'} + '@unocss/cli@66.7.0': + resolution: {integrity: sha512-Pkd/R+WDs8gc1i9fI5XDW8N5r7aoCWjNzt8wGGj5FWTbmsEzewueaL5LQTH4ymv/BhSHFcYpL7geQ5vYont+BA==} hasBin: true - '@unocss/config@66.5.4': - resolution: {integrity: sha512-TYwkUw9nZlLTBGCndsyrcHCJ7M+sEsJiK77Edggmd6B3urjkVc1cDjKF3k3tjg4ghQteGsc2akhzn1a4TouybQ==} - engines: {node: '>=14'} - - '@unocss/core@66.5.4': - resolution: {integrity: sha512-UDS2CRgyQCEFH+5kStDyJd7OFtgkIUZYn5Ahr5z7v3jc/pEfeOJ0mxsNAr+FgMS/xb17vy4sVFvx3jj/FwMZ1A==} + '@unocss/config@66.7.0': + resolution: {integrity: sha512-C6waL+xzqAPzz5n47qnrs4GbyAtlusNYYmcV6DKYh1MgUP4EFhMnEMyuR2mw3M3tsBpyGuehLdRK5+ECF5yLkA==} - '@unocss/extractor-arbitrary-variants@66.5.4': - resolution: {integrity: sha512-JsgITF11Z2WdXzF8eO2/qkcFIff/dEEc9C2eKYOSUv5pe+RMZxXHoAw4x+D4n0UrGAbHpoUVaJ8E7kG0ayTbGw==} + '@unocss/core@66.7.0': + resolution: {integrity: sha512-j6MFMx5C3iIwW4T4hVbh+30fKWgSGkmS3bCcdjlfqM88lRT+dHFBN9nkfNOBJT6e6IHN9415nexuzcQvTjJXxw==} - '@unocss/inspector@66.5.4': - resolution: {integrity: sha512-eBf1HAxwNz1YItNiiP/YQaIE9LWeErt4Ofdm7Imj0WW464ZZ/TqXhu0ZREcCgyQDy2Lghuyq6Q3d9orm2Cby/w==} + '@unocss/extractor-arbitrary-variants@66.7.0': + resolution: {integrity: sha512-iHMlXmb8aGtYgPQ8o3D4rMz9DKOqSp8g/LWvEoiM7arSjJF9jMpcpYlqZXzkg1mSQX23TRW76Qxj1gyI4lRd9w==} - '@unocss/postcss@66.5.4': - resolution: {integrity: sha512-EpizX20MR8wTWlCI9+E6pI8Xj5S1kk2jRVQuQAxjjXcOEFoLZNTZmyULSlaIpg9vEtT5kuxQgBN6VmvyMgeD7g==} - engines: {node: '>=14'} - peerDependencies: - postcss: ^8.4.21 - - '@unocss/preset-attributify@66.5.4': - resolution: {integrity: sha512-6NmRUKpXp4qc+ZwWI+ImBIUzcdPRKWISfYu65hi8Sads453jzLJko78WOCVTLlgnmkquUJ98akNW5twG9p2mDw==} + '@unocss/inspector@66.7.0': + resolution: {integrity: sha512-W1MOO2d/1ZHwFR8+mrUUW6KW3MgJ6FdrSWfWeQ1+fgb0TVj8CweNzeSh46sTEXEcpvlui5mnGYFxanpLMoyOtA==} - '@unocss/preset-icons@66.5.4': - resolution: {integrity: sha512-wPR2j191mw89hstQflQvsACzu+3QkueV9lHH8as94By9PKfswWnVZ1nPqJBc3Yl5v8fHEAR1YY4i7egN7TEjIA==} + '@unocss/preset-attributify@66.7.0': + resolution: {integrity: sha512-n8ikthHHkAOeHWUwqRNIMGijV6LuIhiZb3D6kreV3oK98wJYupGNGYMByx7R9gQD9uBNLGs0f1jsaAScV3S2Sw==} - '@unocss/preset-mini@66.5.4': - resolution: {integrity: sha512-KaBGsw3+Pi5ZTsp5u0OrUUUXFVltHin02cYhv3A4b9392Kej5R3y7zIf1VjiQ3ZXR4KZWfv0CQj0LBqIqAJ5WA==} + '@unocss/preset-icons@66.7.0': + resolution: {integrity: sha512-y6I2qZ2cwNAS2XRBig1lHzdFG9qTnZM/mx3fL3XnURnEYZird4uidLyWOyUGcdy1kMot1QcYVb0D/s9NgrEOgQ==} - '@unocss/preset-tagify@66.5.4': - resolution: {integrity: sha512-ck71rFCQZEwYDzwf99sjCBuzpT0PnkzwdqWwnR34pN71Lf3ePN16hV6pEo7pWuIiatAGFzXh0AHzJrIQ/61Cxw==} + '@unocss/preset-mini@66.7.0': + resolution: {integrity: sha512-+YtRlr1Fjd24GYWhPB93r6fjefTBCnFUsZCASncSEU29u2Mi8MYINjefLfKlSJFMKg6AKzWbelKMCQfoKlUkbg==} - '@unocss/preset-typography@66.5.4': - resolution: {integrity: sha512-RG0Bw4lGvwAJxHw8I/0Hx2/r4t8L6fnkWyEP4Iehie3kEGJ+S7Ku9sF6kkIeyOqjwL6Hp68rlnTGAycnYofoEg==} + '@unocss/preset-tagify@66.7.0': + resolution: {integrity: sha512-MaM07ChHsX8XZM3tlMPuRsZxbNvRVTbmIncOj9cCCrFpeOu8hy2ggRAgGOalWIwnIHc+5KQIkqucbgmXN7KBdA==} - '@unocss/preset-uno@66.5.4': - resolution: {integrity: sha512-CEBtkNbbd1lYbCJw+s7HDeOtPeCEkvf+NDi/IrVkkBhOCcYRtYC+VDxjBgh4zjlmgZIQifkU2l7PPfGjd4IMNA==} + '@unocss/preset-typography@66.7.0': + resolution: {integrity: sha512-Ekdz7jw/TYTiH+QFqMWcWNMnvBnUZ/XPUF938C8DfqD79hZyLdRPo0kQaZh62cit13xNRAb49QP3HIUJIUxoGA==} - '@unocss/preset-web-fonts@66.5.4': - resolution: {integrity: sha512-FQ/P/a1fSmGkkjWn/FNmErwK5YtsuX2VrkHsEa9DTP372td8Oea3hkK40UUYj3zRUivA71PmjVwhbBf+35nAiA==} + '@unocss/preset-uno@66.7.0': + resolution: {integrity: sha512-fcLTj5Wax3QydCSdJq9yQHhqKph6Mx9exwNnkaBCXtmBvrSBd2O6O9ZAylcISnACeXJkjSverU8qVu1X2tITdA==} - '@unocss/preset-wind3@66.5.4': - resolution: {integrity: sha512-cqQGg9E2476YVpnX3sgO/jEoA4cKCA5rEl2NgemoAJpKAgdM68JPB+Tve4LlSLssxRQZ7ZYNO6hOfW8R2gVVuw==} + '@unocss/preset-web-fonts@66.7.0': + resolution: {integrity: sha512-jpNLjo/2X/J2J+G/M9W+y6VuiIhjZ9AyOnyNJHsdhmSJYCsnMuaYtP9eFn4d9+oe3Sz2lVNPV0A9RiqQ+xVAyQ==} - '@unocss/preset-wind4@66.5.4': - resolution: {integrity: sha512-S5ZysCSTfl/h93jDnXIss214jqYfq+W6xZH50Krc1QTWy5teAOVCFTluRJEB70JTDOdUMwcTtmqFklSHIU5I7g==} + '@unocss/preset-wind3@66.7.0': + resolution: {integrity: sha512-1xxHBV4TtUHXPpYnWH8J2UHhxaMF84fTvadVzRRaXkyVrXD86Hveh/lfbXHXnCyf0JxwqsleOq8CnCTT8AgoAg==} - '@unocss/preset-wind@66.5.4': - resolution: {integrity: sha512-2TWP2QrJwGFr21iwVsPKVzDa2JWjh1EUt1+OtAk5JQfGmmTeyw8EF3pIAcaM06WVi/m4em55RKIPNoW/Kr61yg==} + '@unocss/preset-wind4@66.7.0': + resolution: {integrity: sha512-5o3y2BcImLbkxa0fNtwaH8iB47FrOKzT7Xogni5PIDOX/DsoHfDLNiNBRrHHHHBeZ3jqvjv2T9T5kEkD5/WtYQ==} - '@unocss/reset@66.5.4': - resolution: {integrity: sha512-RF/Xscv4mOEDUltUpdKYZEBgIiE7nAVkipJ8gZWEwKfmUFz0TRcwlf0igjqjgGn11tuix0mJyk5Uwis9LioX4Q==} + '@unocss/preset-wind@66.7.0': + resolution: {integrity: sha512-K2cCgQawl4GzFyI9almN4jZ33OJNI6U7WxZ9s7D5bivZYfHPaStLTPffNxWlmawwUZF0qpH0S+S7H745ZzgajQ==} - '@unocss/rule-utils@66.5.4': - resolution: {integrity: sha512-LFzLuXQfZKI/qJBrsqkaVKlw0ECU8Xw7m+MaKIKyFH/hqggzkvNG0PyWU2HnPNzz1dIiVBn+Epfpz8pzi+MLFA==} - engines: {node: '>=14'} + '@unocss/rule-utils@66.7.0': + resolution: {integrity: sha512-DMJIiey/m+xr0hpSbxFhSbKlC3e7QsuwdAEdgMmIM7pEcu/AEMl7oH198QYX9880P2X0hy5iFE6UCWx9CwGAXQ==} - '@unocss/transformer-attributify-jsx@66.5.4': - resolution: {integrity: sha512-VHzrxiWKBVsUZhFU0vG7e6MjSiQG/rR/PidPgi8KaMGAWi+CA6faRBfHaUQbfix2bLBhtDOdaZUDp9AsIgu1ZQ==} + '@unocss/transformer-attributify-jsx@66.7.0': + resolution: {integrity: sha512-mmsAUluRprSyejbzeQnC3ST056EUj2IxD2hMpPJPtnA4QkkyIgBNCmi2OSeVcEWMat1s3r4LcYSTqN88EcX5Kg==} - '@unocss/transformer-compile-class@66.5.4': - resolution: {integrity: sha512-H+IX9C8PHFMCJfYutIRjzkpgIiW/AFC7PzP/EQwM+p9VoC8LH+Wd8Csl/Uyi+uoQ+a78q4nQ2lDYZr42eanmgg==} + '@unocss/transformer-compile-class@66.7.0': + resolution: {integrity: sha512-Z3K/s3TmUqUBGgB2SThWbUAP5E9VIFacbs2+bNJNn+53y1kqdLA1MIje3xlU5hig3OzGk8newwiMflh3s3Jzhg==} - '@unocss/transformer-directives@66.5.4': - resolution: {integrity: sha512-BqM4fRqCC5wIRkEB14SN476/KWKlEhHhrHECL9kOjbZYmIcxBDCYKf/iuZGvtK9IZJtE0JhrSGAdYfyp0Td7fQ==} + '@unocss/transformer-directives@66.7.0': + resolution: {integrity: sha512-6T9JxrPfLQlJFNLv7paG4yGiIgGrJY30268HWLkBFwgsldNPtQ+GeQJOzfemCH19UXXqqXMP0WnvbsFucdclmg==} - '@unocss/transformer-variant-group@66.5.4': - resolution: {integrity: sha512-n/A74083b8zZtl05A3M0Lo9oWepFKuvRZKPXh+y4bJM2oSZl1Clzm1I+qmgvO/DKoa4rjgj4a/CRaIxeDpoO9A==} + '@unocss/transformer-variant-group@66.7.0': + resolution: {integrity: sha512-2TXYLowPMXszGNYRXAWzQ1G9nGP6EYv9XeJvwNvnf0w9J6qOQVVtW/ZViIz61Kk083c06cZ6nai8pCBnc8aPAw==} - '@unocss/vite@66.5.4': - resolution: {integrity: sha512-dmSJ3h7/kMbFOIrAyycg2W1VVN+59WCnH5s0dJTGRla2kUTAFB0iWJWdIa/W6IsvFlicMtsoLYJmTnQ/kBQm7A==} + '@unocss/vite@66.7.0': + resolution: {integrity: sha512-7J8Mk9M1j55S3bXL87/yHOspnuAaftQWbc3HjCH0/sXNLZJZnlpmUue3EtT5Ez+PE01T3DK1D9Xxn/MvtdvXtA==} peerDependencies: - vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 + vite: ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 || ^8.0.0-0 - acorn@8.15.0: - resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} engines: {node: '>=0.4.0'} hasBin: true - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - - binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - - cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} + cac@7.0.0: + resolution: {integrity: sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==} + engines: {node: '>=20.19.0'} - chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} + chokidar@5.0.0: + resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} + engines: {node: '>= 20.19.0'} colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} @@ -482,28 +588,16 @@ packages: confbox@0.1.8: resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} - confbox@0.2.2: - resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==} - consola@3.4.2: resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} engines: {node: ^14.18.0 || >=16.10.0} - css-tree@3.1.0: - resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} + css-tree@3.2.1: + resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} - debug@4.4.3: - resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - defu@6.1.4: - resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + defu@6.1.7: + resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} destr@2.0.5: resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} @@ -516,8 +610,8 @@ packages: engines: {node: '>=18'} hasBin: true - exsolve@1.0.7: - resolution: {integrity: sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} @@ -528,139 +622,97 @@ packages: picomatch: optional: true - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - - globals@15.15.0: - resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} - engines: {node: '>=18'} - gzip-size@6.0.0: resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} engines: {node: '>=10'} - is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} + import-meta-resolve@4.2.0: + resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - jiti@2.6.1: - resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} hasBin: true - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - jsesc@3.1.0: - resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} - engines: {node: '>=6'} - hasBin: true - - kolorist@1.8.0: - resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} - leaflet@1.9.4: resolution: {integrity: sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==} - local-pkg@1.1.2: - resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==} - engines: {node: '>=14'} + magic-regexp@0.10.0: + resolution: {integrity: sha512-Uly1Bu4lO1hwHUW0CQeSWuRtzCMNO00CmXtS8N6fyvB3B979GOEEeAkiTUDsmbYLAbvpUS/Kt5c4ibosAzVyVg==} magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - mdn-data@2.12.2: - resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} + mdn-data@2.27.1: + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} - mlly@1.8.0: - resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} + mlly@1.8.2: + resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==} mrmime@2.0.1: resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} engines: {node: '>=10'} - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + nanoid@3.3.12: + resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true node-fetch-native@1.6.7: resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - ofetch@1.5.1: resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==} - package-manager-detector@1.5.0: - resolution: {integrity: sha512-uBj69dVlYe/+wxj8JOpr97XfsxH/eumMt6HqjNTmJDf/6NO9s+0uxeOneIz3AsPt2m6y9PqzDzd3ATcU17MNfw==} + oxc-parser@0.131.0: + resolution: {integrity: sha512-SJ3/7ZPbgie8dr5Z9BI/M51zZbpXba+hRSG0MDzVwMW5CRQg2fjYE0jHGlLX4eeiibGgC/mzoDFKSDHwVZEHRQ==} + engines: {node: ^20.19.0 || >=22.12.0} + + oxc-walker@0.7.0: + resolution: {integrity: sha512-54B4KUhrzbzc4sKvKwVYm7E2PgeROpGba0/2nlNZMqfDyca+yOor5IMb4WLGBatGDT0nkzYdYuzylg7n3YfB7A==} + peerDependencies: + oxc-parser: '>=0.98.0' + + package-manager-detector@1.6.0: + resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - perfect-debounce@1.0.0: - resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + perfect-debounce@2.1.0: + resolution: {integrity: sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==} picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - picomatch@4.0.3: - resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} engines: {node: '>=12'} pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} - pkg-types@2.3.0: - resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} - - postcss@8.5.6: - resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + postcss@8.5.15: + resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} engines: {node: ^10 || ^12 || >=14} - quansync@0.2.11: - resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} + quansync@1.0.0: + resolution: {integrity: sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==} - readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} + readdirp@5.0.0: + resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + engines: {node: '>= 20.19.0'} - rollup@4.52.5: - resolution: {integrity: sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==} + regexp-tree@0.1.27: + resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} + hasBin: true + + rollup@4.60.4: + resolution: {integrity: sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -672,43 +724,55 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - tinyexec@1.0.1: - resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==} + tinyexec@1.2.2: + resolution: {integrity: sha512-M/Q0B2cp4K7kynaT/vnED1j8TlLY+Pp7C6Wl2bl/7u/F0mUVwdyOpwomQb8JpYLitHUssAJRmLZdMCGsrx7i+g==} + engines: {node: '>=18'} - tinyglobby@0.2.15: - resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + tinyglobby@0.2.16: + resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} engines: {node: '>=12.0.0'} - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} - ufo@1.6.1: - resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-level-regexp@0.1.17: + resolution: {integrity: sha512-wTk4DH3cxwk196uGLK/E9pE45aLfeKJacKmcEgEOA/q5dnPGNxXt0cfYdFxb57L+sEpf1oJH4Dnx/pnRcku9jg==} - unconfig@7.3.3: - resolution: {integrity: sha512-QCkQoOnJF8L107gxfHL0uavn7WD9b3dpBcFX6HtfQYmjw2YzWxGuFQ0N0J6tE9oguCBJn9KOvfqYDCMPHIZrBA==} + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} - unocss@66.5.4: - resolution: {integrity: sha512-yNajR8ADgvOzLhDkMKAXVE/SHM4sDrtVhhCnhBjiUMOR0LHIYO7cqunJJudbccrsfJbRTn/odSTBGu9f2IaXOg==} - engines: {node: '>=14'} + unconfig-core@7.5.0: + resolution: {integrity: sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==} + + unconfig@7.5.0: + resolution: {integrity: sha512-oi8Qy2JV4D3UQ0PsopR28CzdQ3S/5A1zwsUwp/rosSbfhJ5z7b90bIyTwi/F7hCLD4SGcZVjDzd4XoUQcEanvA==} + + unocss@66.7.0: + resolution: {integrity: sha512-dVfkL7SQv3fOiZdqeRX1PdpQqXlB+wHcEQjVR0D/2nXsuqmUqTVnX3EUUWFjqVR83Z51zQ0EyVgym8ooDfcVvw==} peerDependencies: - '@unocss/webpack': 66.5.4 - vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 + '@unocss/astro': 66.7.0 + '@unocss/postcss': 66.7.0 + '@unocss/webpack': 66.7.0 peerDependenciesMeta: - '@unocss/webpack': + '@unocss/astro': + optional: true + '@unocss/postcss': optional: true - vite: + '@unocss/webpack': optional: true unplugin-utils@0.3.1: resolution: {integrity: sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==} engines: {node: '>=20.19.0'} + unplugin@2.3.11: + resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==} + engines: {node: '>=18.12.0'} + vite@7.1.12: resolution: {integrity: sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==} engines: {node: ^20.19.0 || >=22.12.0} @@ -749,66 +813,31 @@ packages: yaml: optional: true - vue-flow-layout@0.2.0: - resolution: {integrity: sha512-zKgsWWkXq0xrus7H4Mc+uFs1ESrmdTXlO0YNbR6wMdPaFvosL3fMB8N7uTV308UhGy9UvTrGhIY7mVz9eN+L0Q==} + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} snapshots: '@antfu/install-pkg@1.1.0': dependencies: - package-manager-detector: 1.5.0 - tinyexec: 1.0.1 - - '@antfu/utils@9.3.0': {} - - '@babel/code-frame@7.27.1': - dependencies: - '@babel/helper-validator-identifier': 7.28.5 - js-tokens: 4.0.0 - picocolors: 1.1.1 - - '@babel/generator@7.28.5': - dependencies: - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 3.1.0 - - '@babel/helper-string-parser@7.27.1': {} - - '@babel/helper-validator-identifier@7.28.5': {} - - '@babel/parser@7.27.7': - dependencies: - '@babel/types': 7.28.5 + package-manager-detector: 1.6.0 + tinyexec: 1.2.2 - '@babel/parser@7.28.5': + '@emnapi/core@1.10.0': dependencies: - '@babel/types': 7.28.5 - - '@babel/template@7.27.2': - dependencies: - '@babel/code-frame': 7.27.1 - '@babel/parser': 7.27.7 - '@babel/types': 7.28.5 + '@emnapi/wasi-threads': 1.2.1 + tslib: 2.8.1 + optional: true - '@babel/traverse@7.27.7': + '@emnapi/runtime@1.10.0': dependencies: - '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.5 - '@babel/parser': 7.27.7 - '@babel/template': 7.27.2 - '@babel/types': 7.28.5 - debug: 4.4.3 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color + tslib: 2.8.1 + optional: true - '@babel/types@7.28.5': + '@emnapi/wasi-threads@1.2.1': dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 + tslib: 2.8.1 + optional: true '@esbuild/aix-ppc64@0.25.12': optional: true @@ -890,18 +919,11 @@ snapshots: '@iconify/types@2.0.0': {} - '@iconify/utils@3.0.2': + '@iconify/utils@3.1.3': dependencies: '@antfu/install-pkg': 1.1.0 - '@antfu/utils': 9.3.0 '@iconify/types': 2.0.0 - debug: 4.4.3 - globals: 15.15.0 - kolorist: 1.8.0 - local-pkg: 1.1.2 - mlly: 1.8.0 - transitivePeerDependencies: - - supports-color + import-meta-resolve: 4.2.0 '@jridgewell/gen-mapping@0.3.13': dependencies: @@ -922,274 +944,318 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@tybys/wasm-util': 0.10.2 + optional: true + + '@oxc-parser/binding-android-arm-eabi@0.131.0': + optional: true + + '@oxc-parser/binding-android-arm64@0.131.0': + optional: true + + '@oxc-parser/binding-darwin-arm64@0.131.0': + optional: true + + '@oxc-parser/binding-darwin-x64@0.131.0': + optional: true + + '@oxc-parser/binding-freebsd-x64@0.131.0': + optional: true + + '@oxc-parser/binding-linux-arm-gnueabihf@0.131.0': + optional: true + + '@oxc-parser/binding-linux-arm-musleabihf@0.131.0': + optional: true + + '@oxc-parser/binding-linux-arm64-gnu@0.131.0': + optional: true + + '@oxc-parser/binding-linux-arm64-musl@0.131.0': + optional: true + + '@oxc-parser/binding-linux-ppc64-gnu@0.131.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-gnu@0.131.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-musl@0.131.0': + optional: true + + '@oxc-parser/binding-linux-s390x-gnu@0.131.0': + optional: true + + '@oxc-parser/binding-linux-x64-gnu@0.131.0': + optional: true + + '@oxc-parser/binding-linux-x64-musl@0.131.0': + optional: true + + '@oxc-parser/binding-openharmony-arm64@0.131.0': + optional: true + + '@oxc-parser/binding-wasm32-wasi@0.131.0': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + optional: true + + '@oxc-parser/binding-win32-arm64-msvc@0.131.0': + optional: true + + '@oxc-parser/binding-win32-ia32-msvc@0.131.0': + optional: true + + '@oxc-parser/binding-win32-x64-msvc@0.131.0': + optional: true + + '@oxc-project/types@0.131.0': {} + '@polka/url@1.0.0-next.29': {} - '@quansync/fs@0.1.5': + '@quansync/fs@1.0.0': dependencies: - quansync: 0.2.11 + quansync: 1.0.0 - '@rollup/rollup-android-arm-eabi@4.52.5': + '@rollup/rollup-android-arm-eabi@4.60.4': optional: true - '@rollup/rollup-android-arm64@4.52.5': + '@rollup/rollup-android-arm64@4.60.4': optional: true - '@rollup/rollup-darwin-arm64@4.52.5': + '@rollup/rollup-darwin-arm64@4.60.4': optional: true - '@rollup/rollup-darwin-x64@4.52.5': + '@rollup/rollup-darwin-x64@4.60.4': optional: true - '@rollup/rollup-freebsd-arm64@4.52.5': + '@rollup/rollup-freebsd-arm64@4.60.4': optional: true - '@rollup/rollup-freebsd-x64@4.52.5': + '@rollup/rollup-freebsd-x64@4.60.4': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.52.5': + '@rollup/rollup-linux-arm-gnueabihf@4.60.4': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.52.5': + '@rollup/rollup-linux-arm-musleabihf@4.60.4': optional: true - '@rollup/rollup-linux-arm64-gnu@4.52.5': + '@rollup/rollup-linux-arm64-gnu@4.60.4': optional: true - '@rollup/rollup-linux-arm64-musl@4.52.5': + '@rollup/rollup-linux-arm64-musl@4.60.4': optional: true - '@rollup/rollup-linux-loong64-gnu@4.52.5': + '@rollup/rollup-linux-loong64-gnu@4.60.4': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.52.5': + '@rollup/rollup-linux-loong64-musl@4.60.4': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.52.5': + '@rollup/rollup-linux-ppc64-gnu@4.60.4': optional: true - '@rollup/rollup-linux-riscv64-musl@4.52.5': + '@rollup/rollup-linux-ppc64-musl@4.60.4': optional: true - '@rollup/rollup-linux-s390x-gnu@4.52.5': + '@rollup/rollup-linux-riscv64-gnu@4.60.4': optional: true - '@rollup/rollup-linux-x64-gnu@4.52.5': + '@rollup/rollup-linux-riscv64-musl@4.60.4': optional: true - '@rollup/rollup-linux-x64-musl@4.52.5': + '@rollup/rollup-linux-s390x-gnu@4.60.4': optional: true - '@rollup/rollup-openharmony-arm64@4.52.5': + '@rollup/rollup-linux-x64-gnu@4.60.4': optional: true - '@rollup/rollup-win32-arm64-msvc@4.52.5': + '@rollup/rollup-linux-x64-musl@4.60.4': optional: true - '@rollup/rollup-win32-ia32-msvc@4.52.5': + '@rollup/rollup-openbsd-x64@4.60.4': optional: true - '@rollup/rollup-win32-x64-gnu@4.52.5': + '@rollup/rollup-openharmony-arm64@4.60.4': optional: true - '@rollup/rollup-win32-x64-msvc@4.52.5': + '@rollup/rollup-win32-arm64-msvc@4.60.4': optional: true - '@types/estree@1.0.8': {} + '@rollup/rollup-win32-ia32-msvc@4.60.4': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.60.4': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.60.4': + optional: true - '@unocss/astro@66.5.4(vite@7.1.12(jiti@2.6.1))': + '@tybys/wasm-util@0.10.2': dependencies: - '@unocss/core': 66.5.4 - '@unocss/reset': 66.5.4 - '@unocss/vite': 66.5.4(vite@7.1.12(jiti@2.6.1)) - optionalDependencies: - vite: 7.1.12(jiti@2.6.1) + tslib: 2.8.1 + optional: true + + '@types/estree@1.0.8': {} - '@unocss/cli@66.5.4': + '@types/estree@1.0.9': {} + + '@unocss/cli@66.7.0': dependencies: '@jridgewell/remapping': 2.3.5 - '@unocss/config': 66.5.4 - '@unocss/core': 66.5.4 - '@unocss/preset-uno': 66.5.4 - cac: 6.7.14 - chokidar: 3.6.0 + '@unocss/config': 66.7.0 + '@unocss/core': 66.7.0 + '@unocss/preset-wind3': 66.7.0 + '@unocss/preset-wind4': 66.7.0 + '@unocss/transformer-directives': 66.7.0 + cac: 7.0.0 + chokidar: 5.0.0 colorette: 2.0.20 consola: 3.4.2 magic-string: 0.30.21 pathe: 2.0.3 - perfect-debounce: 1.0.0 - tinyglobby: 0.2.15 + perfect-debounce: 2.1.0 + tinyglobby: 0.2.16 unplugin-utils: 0.3.1 - '@unocss/config@66.5.4': + '@unocss/config@66.7.0': dependencies: - '@unocss/core': 66.5.4 - unconfig: 7.3.3 + '@unocss/core': 66.7.0 + colorette: 2.0.20 + consola: 3.4.2 + unconfig: 7.5.0 - '@unocss/core@66.5.4': {} + '@unocss/core@66.7.0': {} - '@unocss/extractor-arbitrary-variants@66.5.4': + '@unocss/extractor-arbitrary-variants@66.7.0': dependencies: - '@unocss/core': 66.5.4 + '@unocss/core': 66.7.0 - '@unocss/inspector@66.5.4': + '@unocss/inspector@66.7.0': dependencies: - '@unocss/core': 66.5.4 - '@unocss/rule-utils': 66.5.4 + '@unocss/core': 66.7.0 + '@unocss/rule-utils': 66.7.0 colorette: 2.0.20 gzip-size: 6.0.0 sirv: 3.0.2 - vue-flow-layout: 0.2.0 - '@unocss/postcss@66.5.4(postcss@8.5.6)': - dependencies: - '@unocss/config': 66.5.4 - '@unocss/core': 66.5.4 - '@unocss/rule-utils': 66.5.4 - css-tree: 3.1.0 - postcss: 8.5.6 - tinyglobby: 0.2.15 - - '@unocss/preset-attributify@66.5.4': + '@unocss/preset-attributify@66.7.0': dependencies: - '@unocss/core': 66.5.4 + '@unocss/core': 66.7.0 - '@unocss/preset-icons@66.5.4': + '@unocss/preset-icons@66.7.0': dependencies: - '@iconify/utils': 3.0.2 - '@unocss/core': 66.5.4 + '@iconify/utils': 3.1.3 + '@unocss/core': 66.7.0 ofetch: 1.5.1 - transitivePeerDependencies: - - supports-color - '@unocss/preset-mini@66.5.4': + '@unocss/preset-mini@66.7.0': dependencies: - '@unocss/core': 66.5.4 - '@unocss/extractor-arbitrary-variants': 66.5.4 - '@unocss/rule-utils': 66.5.4 + '@unocss/core': 66.7.0 + '@unocss/extractor-arbitrary-variants': 66.7.0 + '@unocss/rule-utils': 66.7.0 - '@unocss/preset-tagify@66.5.4': + '@unocss/preset-tagify@66.7.0': dependencies: - '@unocss/core': 66.5.4 + '@unocss/core': 66.7.0 - '@unocss/preset-typography@66.5.4': + '@unocss/preset-typography@66.7.0': dependencies: - '@unocss/core': 66.5.4 - '@unocss/rule-utils': 66.5.4 + '@unocss/core': 66.7.0 + '@unocss/rule-utils': 66.7.0 - '@unocss/preset-uno@66.5.4': + '@unocss/preset-uno@66.7.0': dependencies: - '@unocss/core': 66.5.4 - '@unocss/preset-wind3': 66.5.4 + '@unocss/core': 66.7.0 + '@unocss/preset-wind3': 66.7.0 - '@unocss/preset-web-fonts@66.5.4': + '@unocss/preset-web-fonts@66.7.0': dependencies: - '@unocss/core': 66.5.4 + '@unocss/core': 66.7.0 ofetch: 1.5.1 - '@unocss/preset-wind3@66.5.4': + '@unocss/preset-wind3@66.7.0': dependencies: - '@unocss/core': 66.5.4 - '@unocss/preset-mini': 66.5.4 - '@unocss/rule-utils': 66.5.4 + '@unocss/core': 66.7.0 + '@unocss/preset-mini': 66.7.0 + '@unocss/rule-utils': 66.7.0 - '@unocss/preset-wind4@66.5.4': + '@unocss/preset-wind4@66.7.0': dependencies: - '@unocss/core': 66.5.4 - '@unocss/extractor-arbitrary-variants': 66.5.4 - '@unocss/rule-utils': 66.5.4 + '@unocss/core': 66.7.0 + '@unocss/extractor-arbitrary-variants': 66.7.0 + '@unocss/rule-utils': 66.7.0 - '@unocss/preset-wind@66.5.4': + '@unocss/preset-wind@66.7.0': dependencies: - '@unocss/core': 66.5.4 - '@unocss/preset-wind3': 66.5.4 - - '@unocss/reset@66.5.4': {} + '@unocss/core': 66.7.0 + '@unocss/preset-wind3': 66.7.0 - '@unocss/rule-utils@66.5.4': + '@unocss/rule-utils@66.7.0': dependencies: - '@unocss/core': 66.5.4 + '@unocss/core': 66.7.0 magic-string: 0.30.21 - '@unocss/transformer-attributify-jsx@66.5.4': + '@unocss/transformer-attributify-jsx@66.7.0': dependencies: - '@babel/parser': 7.27.7 - '@babel/traverse': 7.27.7 - '@unocss/core': 66.5.4 - transitivePeerDependencies: - - supports-color + '@unocss/core': 66.7.0 + oxc-parser: 0.131.0 + oxc-walker: 0.7.0(oxc-parser@0.131.0) - '@unocss/transformer-compile-class@66.5.4': + '@unocss/transformer-compile-class@66.7.0': dependencies: - '@unocss/core': 66.5.4 + '@unocss/core': 66.7.0 - '@unocss/transformer-directives@66.5.4': + '@unocss/transformer-directives@66.7.0': dependencies: - '@unocss/core': 66.5.4 - '@unocss/rule-utils': 66.5.4 - css-tree: 3.1.0 + '@unocss/core': 66.7.0 + '@unocss/rule-utils': 66.7.0 + css-tree: 3.2.1 - '@unocss/transformer-variant-group@66.5.4': + '@unocss/transformer-variant-group@66.7.0': dependencies: - '@unocss/core': 66.5.4 + '@unocss/core': 66.7.0 - '@unocss/vite@66.5.4(vite@7.1.12(jiti@2.6.1))': + '@unocss/vite@66.7.0(vite@7.1.12(jiti@2.7.0))': dependencies: '@jridgewell/remapping': 2.3.5 - '@unocss/config': 66.5.4 - '@unocss/core': 66.5.4 - '@unocss/inspector': 66.5.4 - chokidar: 3.6.0 + '@unocss/config': 66.7.0 + '@unocss/core': 66.7.0 + '@unocss/inspector': 66.7.0 + chokidar: 5.0.0 magic-string: 0.30.21 pathe: 2.0.3 - tinyglobby: 0.2.15 + tinyglobby: 0.2.16 unplugin-utils: 0.3.1 - vite: 7.1.12(jiti@2.6.1) + vite: 7.1.12(jiti@2.7.0) - acorn@8.15.0: {} - - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 + acorn@8.16.0: {} - binary-extensions@2.3.0: {} + cac@7.0.0: {} - braces@3.0.3: + chokidar@5.0.0: dependencies: - fill-range: 7.1.1 - - cac@6.7.14: {} - - chokidar@3.6.0: - dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 + readdirp: 5.0.0 colorette@2.0.20: {} confbox@0.1.8: {} - confbox@0.2.2: {} - consola@3.4.2: {} - css-tree@3.1.0: + css-tree@3.2.1: dependencies: - mdn-data: 2.12.2 + mdn-data: 2.27.1 source-map-js: 1.2.1 - debug@4.4.3: - dependencies: - ms: 2.1.3 - - defu@6.1.4: {} + defu@6.1.7: {} destr@2.0.5: {} @@ -1224,150 +1290,149 @@ snapshots: '@esbuild/win32-ia32': 0.25.12 '@esbuild/win32-x64': 0.25.12 - exsolve@1.0.7: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.9 - fdir@6.5.0(picomatch@4.0.3): + fdir@6.5.0(picomatch@4.0.4): optionalDependencies: - picomatch: 4.0.3 - - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 + picomatch: 4.0.4 fsevents@2.3.3: optional: true - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - globals@11.12.0: {} - - globals@15.15.0: {} - gzip-size@6.0.0: dependencies: duplexer: 0.1.2 - is-binary-path@2.1.0: - dependencies: - binary-extensions: 2.3.0 - - is-extglob@2.1.1: {} - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-number@7.0.0: {} - - jiti@2.6.1: {} + import-meta-resolve@4.2.0: {} - js-tokens@4.0.0: {} - - jsesc@3.1.0: {} - - kolorist@1.8.0: {} + jiti@2.7.0: {} leaflet@1.9.4: {} - local-pkg@1.1.2: + magic-regexp@0.10.0: dependencies: - mlly: 1.8.0 - pkg-types: 2.3.0 - quansync: 0.2.11 + estree-walker: 3.0.3 + magic-string: 0.30.21 + mlly: 1.8.2 + regexp-tree: 0.1.27 + type-level-regexp: 0.1.17 + ufo: 1.6.4 + unplugin: 2.3.11 magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - mdn-data@2.12.2: {} + mdn-data@2.27.1: {} - mlly@1.8.0: + mlly@1.8.2: dependencies: - acorn: 8.15.0 + acorn: 8.16.0 pathe: 2.0.3 pkg-types: 1.3.1 - ufo: 1.6.1 + ufo: 1.6.4 mrmime@2.0.1: {} - ms@2.1.3: {} - - nanoid@3.3.11: {} + nanoid@3.3.12: {} node-fetch-native@1.6.7: {} - normalize-path@3.0.0: {} - ofetch@1.5.1: dependencies: destr: 2.0.5 node-fetch-native: 1.6.7 - ufo: 1.6.1 + ufo: 1.6.4 + + oxc-parser@0.131.0: + dependencies: + '@oxc-project/types': 0.131.0 + optionalDependencies: + '@oxc-parser/binding-android-arm-eabi': 0.131.0 + '@oxc-parser/binding-android-arm64': 0.131.0 + '@oxc-parser/binding-darwin-arm64': 0.131.0 + '@oxc-parser/binding-darwin-x64': 0.131.0 + '@oxc-parser/binding-freebsd-x64': 0.131.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.131.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.131.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.131.0 + '@oxc-parser/binding-linux-arm64-musl': 0.131.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.131.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.131.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.131.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.131.0 + '@oxc-parser/binding-linux-x64-gnu': 0.131.0 + '@oxc-parser/binding-linux-x64-musl': 0.131.0 + '@oxc-parser/binding-openharmony-arm64': 0.131.0 + '@oxc-parser/binding-wasm32-wasi': 0.131.0 + '@oxc-parser/binding-win32-arm64-msvc': 0.131.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.131.0 + '@oxc-parser/binding-win32-x64-msvc': 0.131.0 + + oxc-walker@0.7.0(oxc-parser@0.131.0): + dependencies: + magic-regexp: 0.10.0 + oxc-parser: 0.131.0 - package-manager-detector@1.5.0: {} + package-manager-detector@1.6.0: {} pathe@2.0.3: {} - perfect-debounce@1.0.0: {} + perfect-debounce@2.1.0: {} picocolors@1.1.1: {} - picomatch@2.3.1: {} - - picomatch@4.0.3: {} + picomatch@4.0.4: {} pkg-types@1.3.1: dependencies: confbox: 0.1.8 - mlly: 1.8.0 + mlly: 1.8.2 pathe: 2.0.3 - pkg-types@2.3.0: + postcss@8.5.15: dependencies: - confbox: 0.2.2 - exsolve: 1.0.7 - pathe: 2.0.3 - - postcss@8.5.6: - dependencies: - nanoid: 3.3.11 + nanoid: 3.3.12 picocolors: 1.1.1 source-map-js: 1.2.1 - quansync@0.2.11: {} + quansync@1.0.0: {} - readdirp@3.6.0: - dependencies: - picomatch: 2.3.1 + readdirp@5.0.0: {} - rollup@4.52.5: + regexp-tree@0.1.27: {} + + rollup@4.60.4: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.52.5 - '@rollup/rollup-android-arm64': 4.52.5 - '@rollup/rollup-darwin-arm64': 4.52.5 - '@rollup/rollup-darwin-x64': 4.52.5 - '@rollup/rollup-freebsd-arm64': 4.52.5 - '@rollup/rollup-freebsd-x64': 4.52.5 - '@rollup/rollup-linux-arm-gnueabihf': 4.52.5 - '@rollup/rollup-linux-arm-musleabihf': 4.52.5 - '@rollup/rollup-linux-arm64-gnu': 4.52.5 - '@rollup/rollup-linux-arm64-musl': 4.52.5 - '@rollup/rollup-linux-loong64-gnu': 4.52.5 - '@rollup/rollup-linux-ppc64-gnu': 4.52.5 - '@rollup/rollup-linux-riscv64-gnu': 4.52.5 - '@rollup/rollup-linux-riscv64-musl': 4.52.5 - '@rollup/rollup-linux-s390x-gnu': 4.52.5 - '@rollup/rollup-linux-x64-gnu': 4.52.5 - '@rollup/rollup-linux-x64-musl': 4.52.5 - '@rollup/rollup-openharmony-arm64': 4.52.5 - '@rollup/rollup-win32-arm64-msvc': 4.52.5 - '@rollup/rollup-win32-ia32-msvc': 4.52.5 - '@rollup/rollup-win32-x64-gnu': 4.52.5 - '@rollup/rollup-win32-x64-msvc': 4.52.5 + '@rollup/rollup-android-arm-eabi': 4.60.4 + '@rollup/rollup-android-arm64': 4.60.4 + '@rollup/rollup-darwin-arm64': 4.60.4 + '@rollup/rollup-darwin-x64': 4.60.4 + '@rollup/rollup-freebsd-arm64': 4.60.4 + '@rollup/rollup-freebsd-x64': 4.60.4 + '@rollup/rollup-linux-arm-gnueabihf': 4.60.4 + '@rollup/rollup-linux-arm-musleabihf': 4.60.4 + '@rollup/rollup-linux-arm64-gnu': 4.60.4 + '@rollup/rollup-linux-arm64-musl': 4.60.4 + '@rollup/rollup-linux-loong64-gnu': 4.60.4 + '@rollup/rollup-linux-loong64-musl': 4.60.4 + '@rollup/rollup-linux-ppc64-gnu': 4.60.4 + '@rollup/rollup-linux-ppc64-musl': 4.60.4 + '@rollup/rollup-linux-riscv64-gnu': 4.60.4 + '@rollup/rollup-linux-riscv64-musl': 4.60.4 + '@rollup/rollup-linux-s390x-gnu': 4.60.4 + '@rollup/rollup-linux-x64-gnu': 4.60.4 + '@rollup/rollup-linux-x64-musl': 4.60.4 + '@rollup/rollup-openbsd-x64': 4.60.4 + '@rollup/rollup-openharmony-arm64': 4.60.4 + '@rollup/rollup-win32-arm64-msvc': 4.60.4 + '@rollup/rollup-win32-ia32-msvc': 4.60.4 + '@rollup/rollup-win32-x64-gnu': 4.60.4 + '@rollup/rollup-win32-x64-msvc': 4.60.4 fsevents: 2.3.3 sirv@3.0.2: @@ -1378,70 +1443,79 @@ snapshots: source-map-js@1.2.1: {} - tinyexec@1.0.1: {} - - tinyglobby@0.2.15: - dependencies: - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 + tinyexec@1.2.2: {} - to-regex-range@5.0.1: + tinyglobby@0.2.16: dependencies: - is-number: 7.0.0 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 totalist@3.0.1: {} - ufo@1.6.1: {} + tslib@2.8.1: + optional: true - unconfig@7.3.3: + type-level-regexp@0.1.17: {} + + ufo@1.6.4: {} + + unconfig-core@7.5.0: dependencies: - '@quansync/fs': 0.1.5 - defu: 6.1.4 - jiti: 2.6.1 - quansync: 0.2.11 + '@quansync/fs': 1.0.0 + quansync: 1.0.0 - unocss@66.5.4(postcss@8.5.6)(vite@7.1.12(jiti@2.6.1)): + unconfig@7.5.0: dependencies: - '@unocss/astro': 66.5.4(vite@7.1.12(jiti@2.6.1)) - '@unocss/cli': 66.5.4 - '@unocss/core': 66.5.4 - '@unocss/postcss': 66.5.4(postcss@8.5.6) - '@unocss/preset-attributify': 66.5.4 - '@unocss/preset-icons': 66.5.4 - '@unocss/preset-mini': 66.5.4 - '@unocss/preset-tagify': 66.5.4 - '@unocss/preset-typography': 66.5.4 - '@unocss/preset-uno': 66.5.4 - '@unocss/preset-web-fonts': 66.5.4 - '@unocss/preset-wind': 66.5.4 - '@unocss/preset-wind3': 66.5.4 - '@unocss/preset-wind4': 66.5.4 - '@unocss/transformer-attributify-jsx': 66.5.4 - '@unocss/transformer-compile-class': 66.5.4 - '@unocss/transformer-directives': 66.5.4 - '@unocss/transformer-variant-group': 66.5.4 - '@unocss/vite': 66.5.4(vite@7.1.12(jiti@2.6.1)) - optionalDependencies: - vite: 7.1.12(jiti@2.6.1) + '@quansync/fs': 1.0.0 + defu: 6.1.7 + jiti: 2.7.0 + quansync: 1.0.0 + unconfig-core: 7.5.0 + + unocss@66.7.0(vite@7.1.12(jiti@2.7.0)): + dependencies: + '@unocss/cli': 66.7.0 + '@unocss/core': 66.7.0 + '@unocss/preset-attributify': 66.7.0 + '@unocss/preset-icons': 66.7.0 + '@unocss/preset-mini': 66.7.0 + '@unocss/preset-tagify': 66.7.0 + '@unocss/preset-typography': 66.7.0 + '@unocss/preset-uno': 66.7.0 + '@unocss/preset-web-fonts': 66.7.0 + '@unocss/preset-wind': 66.7.0 + '@unocss/preset-wind3': 66.7.0 + '@unocss/preset-wind4': 66.7.0 + '@unocss/transformer-attributify-jsx': 66.7.0 + '@unocss/transformer-compile-class': 66.7.0 + '@unocss/transformer-directives': 66.7.0 + '@unocss/transformer-variant-group': 66.7.0 + '@unocss/vite': 66.7.0(vite@7.1.12(jiti@2.7.0)) transitivePeerDependencies: - - postcss - - supports-color + - vite unplugin-utils@0.3.1: dependencies: pathe: 2.0.3 - picomatch: 4.0.3 + picomatch: 4.0.4 + + unplugin@2.3.11: + dependencies: + '@jridgewell/remapping': 2.3.5 + acorn: 8.16.0 + picomatch: 4.0.4 + webpack-virtual-modules: 0.6.2 - vite@7.1.12(jiti@2.6.1): + vite@7.1.12(jiti@2.7.0): dependencies: esbuild: 0.25.12 - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - postcss: 8.5.6 - rollup: 4.52.5 - tinyglobby: 0.2.15 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + postcss: 8.5.15 + rollup: 4.60.4 + tinyglobby: 0.2.16 optionalDependencies: fsevents: 2.3.3 - jiti: 2.6.1 + jiti: 2.7.0 - vue-flow-layout@0.2.0: {} + webpack-virtual-modules@0.6.2: {} diff --git a/frontend/pnpm-workspace.yaml b/frontend/pnpm-workspace.yaml new file mode 100644 index 0000000..5ed0b5a --- /dev/null +++ b/frontend/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +allowBuilds: + esbuild: true diff --git a/frontend/style/uno.css b/frontend/style/uno.css index 4a1bab5..914da53 100644 --- a/frontend/style/uno.css +++ b/frontend/style/uno.css @@ -515,14 +515,16 @@ input:where([type='button'], [type='reset'], [type='submit']), .mx-auto{margin-inline:auto;} .mb-2{margin-bottom:calc(var(--spacing) * 2);} .mb-4{margin-bottom:calc(var(--spacing) * 4);} +.me{margin-inline-end:calc(var(--spacing) * 4);} .mt-100px{margin-top:100px;} .p-0{padding:calc(var(--spacing) * 0);} .p-2{padding:calc(var(--spacing) * 2);} .p-20px{padding:20px;} .p-4{padding:calc(var(--spacing) * 4);} .p-unset{padding:unset;} -.px-2{padding-inline:calc(var(--spacing) * 2);} +.px, .px-4{padding-inline:calc(var(--spacing) * 4);} +.px-2{padding-inline:calc(var(--spacing) * 2);} .py-2{padding-block:calc(var(--spacing) * 2);} .py-4{padding-block:calc(var(--spacing) * 4);} .pt-10{padding-top:calc(var(--spacing) * 10);} From 4e064cb1103d73599be907deb34c42ccaadc5942 Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Wed, 27 May 2026 01:27:50 +0100 Subject: [PATCH 15/28] Update Rust dependencies --- Cargo.lock | 1577 +++++++++++++---------- backend/Cargo.toml | 10 +- backend/src/graphql/queries/mutation.rs | 12 +- deny.toml | 3 - frontend/Cargo.toml | 10 +- 5 files changed, 915 insertions(+), 697 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 405a355..e4325ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,7 +14,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "crypto-common 0.1.7", + "crypto-common 0.1.6", "generic-array", ] @@ -88,15 +88,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1384d3fe1eecb464229fcf6eebb72306591c56bf27b373561489458a7c73027d" dependencies = [ "futures", - "thiserror 2.0.17", + "thiserror 2.0.18", "wasm-bindgen-futures", ] [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "approx" @@ -145,23 +145,23 @@ checksum = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a" [[package]] name = "async-graphql" -version = "7.1.0" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b75c5a43a58890d6dcc02d03952456570671332bb0a5a947b1f09c699912a5" +checksum = "1057a9f7ccf2404d94571dec3451ade1cb524790df6f1ada0d19c2a49f6b0f40" dependencies = [ "async-graphql-derive", "async-graphql-parser", "async-graphql-value", + "async-io", "async-trait", "asynk-strim", "base64", "bytes", "fast_chemail", "fnv", - "futures-timer", "futures-util", "handlebars", - "http 1.4.0", + "http 1.4.1", "indexmap", "mime", "multer", @@ -173,14 +173,14 @@ dependencies = [ "serde_urlencoded", "static_assertions_next", "tempfile", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "async-graphql-axum" -version = "7.1.0" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "599e663e170f69baa0b9f18f52cdfd701e01ade0ac1baef2c4bc488cb68e35c1" +checksum = "a1e37c5532e4b686acf45e7162bc93da91fc2c702fb0d465efc2c20c8f973795" dependencies = [ "async-graphql", "axum", @@ -195,9 +195,9 @@ dependencies = [ [[package]] name = "async-graphql-derive" -version = "7.1.0" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c266ec9a094bbf2d088e016f71aa8d3be7f18c7343b2f0fe6d0e6c1e78977ea" +checksum = "2e6cbeadc8515e66450fba0985ce722192e28443697799988265d86304d7cc68" dependencies = [ "Inflector", "async-graphql-parser", @@ -207,14 +207,14 @@ dependencies = [ "quote", "strum", "syn", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "async-graphql-parser" -version = "7.1.0" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67e2188d3f1299087aa02cfb281f12414905ce63f425dbcfe7b589773468d771" +checksum = "e64ef70f77a1c689111e52076da1cd18f91834bcb847de0a9171f83624b07fbf" dependencies = [ "async-graphql-value", "pest", @@ -224,9 +224,9 @@ dependencies = [ [[package]] name = "async-graphql-value" -version = "7.1.0" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527a4c6022fc4dac57b4f03f12395e9a391512e85ba98230b93315f8f45f27fc" +checksum = "3e3ef112905abea9dea592fc868a6873b10ebd3f983e83308f995d6284e9ba41" dependencies = [ "bytes", "indexmap", @@ -234,11 +234,29 @@ dependencies = [ "serde_json", ] +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "windows-sys 0.61.2", +] + [[package]] name = "async-lock" -version = "3.4.1" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ "event-listener", "event-listener-strategy", @@ -310,9 +328,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "aws-credential-types" @@ -367,7 +385,7 @@ dependencies = [ "bytes-utils", "fastrand", "http 0.2.12", - "http 1.4.0", + "http 1.4.1", "http-body 0.4.6", "http-body 1.0.1", "percent-encoding", @@ -401,7 +419,7 @@ dependencies = [ "hex", "hmac 0.13.0", "http 0.2.12", - "http 1.4.0", + "http 1.4.1", "http-body 1.0.1", "lru", "percent-encoding", @@ -428,7 +446,7 @@ dependencies = [ "hex", "hmac 0.13.0", "http 0.2.12", - "http 1.4.0", + "http 1.4.1", "p256", "percent-encoding", "sha2 0.11.0", @@ -460,10 +478,10 @@ dependencies = [ "bytes", "crc-fast", "hex", - "http 1.4.0", + "http 1.4.1", "http-body 1.0.1", "http-body-util", - "md-5 0.11.0", + "md-5", "pin-project-lite", "sha1 0.11.0", "sha2 0.11.0", @@ -494,7 +512,7 @@ dependencies = [ "bytes-utils", "futures-core", "futures-util", - "http 1.4.0", + "http 1.4.1", "http-body 1.0.1", "http-body-util", "percent-encoding", @@ -513,7 +531,7 @@ dependencies = [ "aws-smithy-runtime-api", "aws-smithy-types", "h2", - "http 1.4.0", + "http 1.4.1", "hyper", "hyper-rustls", "hyper-util", @@ -563,7 +581,7 @@ dependencies = [ "bytes", "fastrand", "http 0.2.12", - "http 1.4.0", + "http 1.4.1", "http-body 0.4.6", "http-body 1.0.1", "http-body-util", @@ -584,7 +602,7 @@ dependencies = [ "aws-smithy-types", "bytes", "http 0.2.12", - "http 1.4.0", + "http 1.4.1", "pin-project-lite", "tokio", "tracing", @@ -610,7 +628,7 @@ checksum = "7442cb268338f0eb8278140a107c046756aa01093d8ef5e99628d34ae09c94f5" dependencies = [ "aws-smithy-runtime-api", "aws-smithy-types", - "http 1.4.0", + "http 1.4.1", ] [[package]] @@ -624,7 +642,7 @@ dependencies = [ "bytes-utils", "futures-core", "http 0.2.12", - "http 1.4.0", + "http 1.4.1", "http-body 0.4.6", "http-body 1.0.1", "http-body-util", @@ -665,16 +683,16 @@ dependencies = [ [[package]] name = "axum" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8" +checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" dependencies = [ "axum-core", "base64", "bytes", "form_urlencoded", "futures-util", - "http 1.4.0", + "http 1.4.1", "http-body 1.0.1", "http-body-util", "hyper", @@ -702,13 +720,13 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" dependencies = [ "bytes", "futures-core", - "http 1.4.0", + "http 1.4.1", "http-body 1.0.1", "http-body-util", "mime", @@ -721,9 +739,9 @@ dependencies = [ [[package]] name = "axum-extra" -version = "0.12.5" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fef252edff26ddba56bbcdf2ee3307b8129acb86f5749b68990c168a6fcc9c76" +checksum = "be44683b41ccb9ab2d23a5230015c9c3c55be97a25e4428366de8873103f7970" dependencies = [ "axum", "axum-core", @@ -731,7 +749,7 @@ dependencies = [ "cookie", "futures-core", "futures-util", - "http 1.4.0", + "http 1.4.1", "http-body 1.0.1", "http-body-util", "mime", @@ -743,9 +761,9 @@ dependencies = [ [[package]] name = "axum-macros" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" +checksum = "7aa268c23bfbbd2c4363b9cd302a4f504fb2a9dfe7e3451d66f35dd392e20aca" dependencies = [ "proc-macro2", "quote", @@ -779,13 +797,13 @@ dependencies = [ "lettre", "moka", "postgres-types", - "rand 0.8.6", + "rand 0.10.1", "refinery", "reqwest", "serde", "serde_json", "shared", - "thiserror 2.0.17", + "thiserror 2.0.18", "time", "tokio", "tokio-postgres", @@ -825,15 +843,15 @@ dependencies = [ [[package]] name = "base64ct" -version = "1.8.1" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e050f626429857a27ddccb31e0aca21356bfa709c04041aefddac081a8f068a" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" dependencies = [ "serde_core", ] @@ -849,15 +867,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.8.2" +version = "1.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" +checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", + "cpufeatures 0.3.0", ] [[package]] @@ -880,9 +899,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "by_address" @@ -917,15 +936,15 @@ dependencies = [ [[package]] name = "camino" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609" +checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" [[package]] name = "casbin" -version = "2.19.0" +version = "2.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b12705127ab9fcf4fbc22a0c93f441514fe7bd7a7248ce443e4bf531c54b7ee" +checksum = "c53f7476c2d0d9cd7ccc88c16ffc5c7889a0497b3462b10b12b5329adde69665" dependencies = [ "async-trait", "fixedbitset", @@ -954,9 +973,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.49" +version = "1.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215" +checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" dependencies = [ "find-msvc-tools", "jobserver", @@ -964,12 +983,6 @@ dependencies = [ "shlex", ] -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - [[package]] name = "cfg-if" version = "1.0.4" @@ -982,11 +995,22 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.1", +] + [[package]] name = "chrono" -version = "0.4.42" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ "iana-time-zone", "js-sys", @@ -1001,15 +1025,15 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common 0.1.7", + "crypto-common 0.1.6", "inout", ] [[package]] name = "cmake" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" dependencies = [ "cc", ] @@ -1028,7 +1052,7 @@ checksum = "a9dbbdc4b4d349732bc6690de10a9de952bd39ba6a065c586e26600b6b0b91f5" dependencies = [ "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -1058,9 +1082,9 @@ dependencies = [ [[package]] name = "config" -version = "0.15.19" +version = "0.15.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30fa8254caad766fc03cb0ccae691e14bf3bd72bfff27f72802ce729551b3d6" +checksum = "f316c6237b2d38be61949ecd15268a4c6ca32570079394a2444d9ce2c72a72d8" dependencies = [ "async-trait", "convert_case 0.6.0", @@ -1071,8 +1095,8 @@ dependencies = [ "serde-untagged", "serde_core", "serde_json", - "toml 0.9.8", - "winnow", + "toml 1.1.2+spec-1.1.0", + "winnow 1.0.3", "yaml-rust2", ] @@ -1123,24 +1147,25 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "once_cell", "tiny-keccak", ] [[package]] name = "const-str" -version = "0.6.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451d0640545a0553814b4c646eb549343561618838e9b42495f466131fe3ad49" +checksum = "18f12cc9948ed9604230cdddc7c86e270f9401ccbe3c2e98a4378c5e7632212f" [[package]] name = "const_format" -version = "0.2.35" +version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" +checksum = "4481a617ad9a412be3b97c5d403fef8ed023103368908b9c50af598ff467cc1e" dependencies = [ "const_format_proc_macros", + "konst", ] [[package]] @@ -1162,9 +1187,9 @@ checksum = "f67855af358fcb20fac58f9d714c94e2b228fe5694c1c9b4ead4a366343eda1b" [[package]] name = "constant_time_eq" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" [[package]] name = "convert_case" @@ -1184,6 +1209,24 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "convert_case" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "affbf0190ed2caf063e3def54ff444b449371d55c58e513a95ab98eca50adb49" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "convert_case_extras" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589c70f0faf8aa9d17787557d5eae854d7755cac50f5c3d12c81d3d57661cebb" +dependencies = [ + "convert_case 0.11.0", +] + [[package]] name = "cookie" version = "0.18.1" @@ -1308,9 +1351,9 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.7" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", "rand_core 0.6.4", @@ -1415,9 +1458,9 @@ dependencies = [ [[package]] name = "dashmap" -version = "6.1.0" +version = "6.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +checksum = "e6361d5c062261c78a176addb82d4c821ae42bed6089de0e12603cd25de2059c" dependencies = [ "cfg-if", "crossbeam-utils", @@ -1429,9 +1472,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.9.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" [[package]] name = "deadpool" @@ -1454,7 +1497,7 @@ checksum = "3d697d376cbfa018c23eb4caab1fd1883dd9c906a8c034e8d9a3cb06a7e0bef9" dependencies = [ "async-trait", "deadpool", - "getrandom 0.2.16", + "getrandom 0.2.17", "serde", "tokio", "tokio-postgres", @@ -1483,9 +1526,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.5" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", "serde_core", @@ -1493,9 +1536,9 @@ dependencies = [ [[package]] name = "derive-where" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" +checksum = "d08b3a0bcc0d079199cd476b2cae8435016ec11d1c0986c6901c5ac223041534" dependencies = [ "proc-macro2", "quote", @@ -1541,7 +1584,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "const-oid 0.9.6", - "crypto-common 0.1.7", + "crypto-common 0.1.6", "subtle", ] @@ -1611,15 +1654,15 @@ dependencies = [ [[package]] name = "either" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" [[package]] name = "either_of" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216d23e0ec69759a17f05e1c553f3a6870e5ec73420fbb07807a6f34d5d1d5a4" +checksum = "5060e0a4cbf26a87550792688ade88e6b8aec9208613631a7a363bda7bc2d4cd" dependencies = [ "paste", "pin-project-lite", @@ -1696,9 +1739,9 @@ dependencies = [ [[package]] name = "erased-serde" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e8918065695684b2b0702da20382d5ae6065cf3327bc2d6436bd49a71ce9f3" +checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" dependencies = [ "serde", "serde_core", @@ -1759,9 +1802,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.3.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "ff" @@ -1775,9 +1818,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.5" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "fixedbitset" @@ -1848,7 +1891,7 @@ dependencies = [ "serde_json", "shared", "thaw", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "wasm-bindgen", "wasm-bindgen-futures", @@ -1864,9 +1907,9 @@ checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -1879,9 +1922,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -1889,33 +1932,42 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", "futures-util", - "num_cpus", ] [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-lite" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "futures-core", + "pin-project-lite", +] [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", @@ -1924,27 +1976,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-timer" -version = "3.0.3" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -1954,15 +2000,14 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] [[package]] name = "generic-array" -version = "0.14.7" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", @@ -1971,14 +2016,14 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "wasm-bindgen", ] @@ -1991,8 +2036,24 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", + "r-efi 5.3.0", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 6.0.0", + "rand_core 0.10.1", "wasip2", + "wasip3", "wasm-bindgen", ] @@ -2028,7 +2089,7 @@ dependencies = [ "futures-core", "futures-sink", "gloo-utils", - "http 1.4.0", + "http 1.4.1", "js-sys", "pin-project", "serde", @@ -2073,9 +2134,9 @@ dependencies = [ [[package]] name = "graphql_client" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83ce10ae0a8ba29e295f9296a4a400a5222b1aa0e65a72d66c5e489ed17fa217" +checksum = "b0f04840854efa7b06377d86fab117f598f5f5c95727067463417ccaf8aa7635" dependencies = [ "graphql_query_derive", "serde", @@ -2084,14 +2145,13 @@ dependencies = [ [[package]] name = "graphql_client_codegen" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61d9d9d96a7397130da7ce3664851f51ce850137e62b030ac78c8a529661151a" +checksum = "aa0141e66c8d0302f8a586df12ad5d0cf87c0fa8c391f2f5b5dc296312dce569" dependencies = [ "graphql-introspection-query", "graphql-parser", "heck", - "lazy_static", "proc-macro2", "quote", "serde", @@ -2101,9 +2161,9 @@ dependencies = [ [[package]] name = "graphql_query_derive" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b684c77d1b5f9c6006068852e0e0e80c6df3ef85c24fe81ef26fbadbd595af77" +checksum = "e16ecf9bb87a6760cf5227f66cbe48bad7b89505aeb002aa9439ea090e6038a3" dependencies = [ "graphql_client_codegen", "proc-macro2", @@ -2129,16 +2189,16 @@ checksum = "17e2ac29387b1aa07a1e448f7bb4f35b500787971e965b02842b900afa5c8f6f" [[package]] name = "h2" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733" dependencies = [ "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "http 1.4.0", + "http 1.4.1", "indexmap", "slab", "tokio", @@ -2148,9 +2208,9 @@ dependencies = [ [[package]] name = "handlebars" -version = "6.4.0" +version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b3f9296c208515b87bd915a2f5d1163d4b3f863ba83337d7713cf478055948e" +checksum = "d43ccdfe15a81ab0a8af639e90254227c9a46afd9c5f5b6ec7efaa345c4b0f00" dependencies = [ "derive_builder", "log", @@ -2159,7 +2219,7 @@ dependencies = [ "pest_derive", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -2191,6 +2251,12 @@ dependencies = [ "foldhash 0.2.0", ] +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + [[package]] name = "hashlink" version = "0.9.1" @@ -2202,11 +2268,11 @@ dependencies = [ [[package]] name = "hashlink" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +checksum = "ea0b22561a9c04a7cb1a302c013e0259cd3b4bb619f145b32f72b8b4bcbed230" dependencies = [ - "hashbrown 0.15.5", + "hashbrown 0.16.1", ] [[package]] @@ -2278,9 +2344,9 @@ dependencies = [ [[package]] name = "http" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +checksum = "8be7462df143984c4598a256ef469b251d7d7f9e271135073e78fc535414f3d0" dependencies = [ "bytes", "itoa", @@ -2304,7 +2370,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.4.0", + "http 1.4.1", ] [[package]] @@ -2315,7 +2381,7 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", - "http 1.4.0", + "http 1.4.1", "http-body 1.0.1", "pin-project-lite", ] @@ -2357,22 +2423,21 @@ dependencies = [ [[package]] name = "hyper" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" dependencies = [ "atomic-waker", "bytes", "futures-channel", "futures-core", "h2", - "http 1.4.0", + "http 1.4.1", "http-body 1.0.1", "httparse", "httpdate", "itoa", "pin-project-lite", - "pin-utils", "smallvec", "tokio", "want", @@ -2380,16 +2445,15 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.7" +version = "0.27.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ - "http 1.4.0", + "http 1.4.1", "hyper", "hyper-util", "rustls", "rustls-native-certs", - "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", @@ -2397,16 +2461,15 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "base64", "bytes", "futures-channel", - "futures-core", "futures-util", - "http 1.4.0", + "http 1.4.1", "http-body 1.0.1", "hyper", "ipnet", @@ -2423,9 +2486,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.64" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -2462,12 +2525,13 @@ checksum = "6c97be924215abd5e630d84e95a47c710138a6559b4c55039f4f33aa897fa859" [[package]] name = "icu_collections" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", "potential_utf", + "utf8_iter", "yoke", "zerofrom", "zerovec", @@ -2475,9 +2539,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ "displaydoc", "litemap", @@ -2488,9 +2552,9 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ "icu_collections", "icu_normalizer_data", @@ -2502,15 +2566,15 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ "icu_collections", "icu_locale_core", @@ -2522,15 +2586,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", "icu_locale_core", @@ -2541,6 +2605,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "ident_case" version = "1.0.1" @@ -2560,9 +2630,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" dependencies = [ "icu_normalizer", "icu_properties", @@ -2570,12 +2640,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.12.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.1", "serde", "serde_core", ] @@ -2589,15 +2659,6 @@ dependencies = [ "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 = "interpolator" version = "0.5.0" @@ -2606,19 +2667,9 @@ checksum = "71dd52191aae121e8611f1e8dc3e324dd0dd1dee1e6dd91d10ee07a3cfb4d9d8" [[package]] name = "ipnet" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "iri-string" -version = "0.7.9" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" -dependencies = [ - "memchr", - "serde", -] +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "is-terminal" @@ -2648,9 +2699,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" -version = "0.2.16" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35" +checksum = "392c70591e8749fe235ddaf513e6f58b26bce3dcc16524cecc8936f75afa161e" dependencies = [ "jiff-static", "jiff-tzdb-platform", @@ -2658,14 +2709,14 @@ dependencies = [ "portable-atomic", "portable-atomic-util", "serde_core", - "windows-sys 0.61.2", + "windows-link", ] [[package]] name = "jiff-static" -version = "0.2.16" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" +checksum = "47b605b0c050d845fc355bb11eb3f9a8deddc218ea60c76e61aa1f2adfb2c96a" dependencies = [ "proc-macro2", "quote", @@ -2674,9 +2725,9 @@ dependencies = [ [[package]] name = "jiff-tzdb" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68971ebff725b9e2ca27a601c5eb38a4c5d64422c4cbab0c535f248087eda5c2" +checksum = "c900ef84826f1338a557697dc8fc601df9ca9af4ac137c7fb61d4c6f2dfd3076" [[package]] name = "jiff-tzdb-platform" @@ -2689,25 +2740,52 @@ dependencies = [ [[package]] name = "jni" -version = "0.21.1" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" dependencies = [ - "cesu8", "cfg-if", "combine", + "jni-macros", "jni-sys", "log", - "thiserror 1.0.69", + "simd_cesu8", + "thiserror 2.0.18", "walkdir", - "windows-sys 0.45.0", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn", ] [[package]] name = "jni-sys" -version = "0.3.0" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn", +] [[package]] name = "jobserver" @@ -2721,10 +2799,12 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.83" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" dependencies = [ + "cfg-if", + "futures-util", "once_cell", "wasm-bindgen", ] @@ -2740,6 +2820,21 @@ dependencies = [ "serde", ] +[[package]] +name = "konst" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128133ed7824fcd73d6e7b17957c5eb7bacb885649bd8c69708b2331a10bcefb" +dependencies = [ + "konst_macro_rules", +] + +[[package]] +name = "konst_macro_rules" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4933f3f57a8e9d9da04db23fb153356ecaf00cbd14aee46279c33dc80925c37" + [[package]] name = "lazy_static" version = "1.5.0" @@ -2759,17 +2854,23 @@ dependencies = [ "web-sys", ] +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "leptos" -version = "0.8.14" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87c98f6d751e524ff425ad9d63d53e120ed68311ffbc22bbd9c0b3c4005a421e" +checksum = "efa3982e7fe36c1de68f91f3c9083124f389a975523881f3d7e3363362feda41" dependencies = [ "any_spawner", "cfg-if", "either_of", "futures", - "getrandom 0.3.4", + "getrandom 0.4.2", "hydration_context", "leptos_config", "leptos_dom", @@ -2789,10 +2890,10 @@ dependencies = [ "server_fn", "slotmap", "tachys", - "thiserror 2.0.17", + "thiserror 2.0.18", "throw_error", - "typed-builder 0.22.0", - "typed-builder-macro 0.22.0", + "typed-builder", + "typed-builder-macro", "wasm-bindgen", "wasm-bindgen-futures", "wasm_split_helpers", @@ -2818,22 +2919,22 @@ dependencies = [ [[package]] name = "leptos_config" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071fc40aeb9fcab885965bad1887990477253ad51f926cd19068f45a44c59e89" +checksum = "0c06f751315bccc0d193fab302ac01d25bcfcd97474d4676440e7e3250dc3fc3" dependencies = [ "config", "regex", "serde", - "thiserror 2.0.17", - "typed-builder 0.21.2", + "thiserror 2.0.18", + "typed-builder", ] [[package]] name = "leptos_dom" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78f4330c88694c5575e0bfe4eecf81b045d14e76a4f8b00d5fd2a63f8779f895" +checksum = "35742e9ed8f8aaf9e549b454c68a7ac0992536e06856365639b111f72ab07884" dependencies = [ "js-sys", "or_poisoned", @@ -2846,14 +2947,14 @@ dependencies = [ [[package]] name = "leptos_hot_reload" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d61ec3e1ff8aaee8c5151688550c0363f85bc37845450764c31ff7584a33f38" +checksum = "9d2a0f220c8a5ef3c51199dfb9cdd702bc0eb80d52fbe70c7890adfaaae8a4b1" dependencies = [ "anyhow", "camino", "indexmap", - "parking_lot", + "or_poisoned", "proc-macro2", "quote", "rstml", @@ -2864,13 +2965,14 @@ dependencies = [ [[package]] name = "leptos_macro" -version = "0.8.12" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d199fafe14b7925fd392764fdd851215909604955acfda7c0263b8722d57c23" +checksum = "9360df573fb57582384a8b7640a3de94ce6501d49be3b69f637cf11a42da484b" dependencies = [ "attribute-derive", "cfg-if", - "convert_case 0.8.0", + "convert_case 0.11.0", + "convert_case_extras", "html-escape", "itertools", "leptos_hot_reload", @@ -2887,9 +2989,9 @@ dependencies = [ [[package]] name = "leptos_meta" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d489e38d3f541e9e43ecc2e3a815527840345a2afca629b3e23fcc1dd254578" +checksum = "6c3efe657b4c55ed2e078922786ffe20acfb71767c3dd913767b09a35c75c890" dependencies = [ "futures", "indexmap", @@ -2902,9 +3004,9 @@ dependencies = [ [[package]] name = "leptos_router" -version = "0.8.10" +version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b824cae28db1551b71f8c2a45eab7bb98d61407f5adcc368cfe7b671e4a71d" +checksum = "c15158449162e099e2273442f7fd9b924f5cefd935d52af5755ec62aa819fa52" dependencies = [ "any_spawner", "either_of", @@ -2918,7 +3020,7 @@ dependencies = [ "rustc_version", "send_wrapper", "tachys", - "thiserror 2.0.17", + "thiserror 2.0.18", "url", "wasm-bindgen", "web-sys", @@ -2938,9 +3040,9 @@ dependencies = [ [[package]] name = "leptos_server" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf1045af93050bf3388d1c138426393fc131f6d9e46a65519da884c033ed730" +checksum = "da974775c5ccbb6bd64be7f53f75e8321542e28f21563a416574dbe4d5447eae" dependencies = [ "any_spawner", "base64", @@ -2996,44 +3098,36 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.178" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libm" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.10" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" dependencies = [ - "bitflags", "libc", - "redox_syscall", ] -[[package]] -name = "linear-map" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfae20f6b19ad527b550c223fddc3077a547fc70cda94b9b566575423fd303ee" - [[package]] name = "linux-raw-sys" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "lock_api" @@ -3046,9 +3140,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.29" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "616ec5685824bcc94416c6d4a7a446eea774a31efd7062c8480ba6fd06d7a6e5" [[package]] name = "lru" @@ -3067,9 +3161,9 @@ checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" [[package]] name = "lucide-leptos" -version = "2.562.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b9d26634ee1f15a7c025695f109b33fa6a7bd5d8727c8890bf2e0f0049b70e1" +checksum = "36daed62ba36289baeb7eb4690a71909f465155ec3b3a9dc3ca2daf143c333cd" dependencies = [ "leptos", ] @@ -3112,16 +3206,6 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest 0.10.7", -] - [[package]] name = "md-5" version = "0.11.0" @@ -3134,9 +3218,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "mime" @@ -3156,20 +3240,20 @@ dependencies = [ [[package]] name = "mio" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "windows-sys 0.61.2", ] [[package]] name = "moka" -version = "0.12.12" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3dec6bd31b08944e08b58fd99373893a6c17054d6f3ea5006cc894f4f4eee2a" +checksum = "957228ad12042ee839f93c8f257b62b4c0ab5eaae1d4fa60de53b27c9d7c5046" dependencies = [ "async-lock", "crossbeam-channel", @@ -3194,7 +3278,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http 1.4.0", + "http 1.4.1", "httparse", "memchr", "mime", @@ -3204,17 +3288,17 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.14" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" dependencies = [ "libc", "log", "openssl", - "openssl-probe 0.1.6", + "openssl-probe", "openssl-sys", "schannel", - "security-framework 2.11.1", + "security-framework", "security-framework-sys", "tempfile", ] @@ -3254,9 +3338,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] name = "num-integer" @@ -3303,20 +3387,38 @@ dependencies = [ ] [[package]] -name = "oco_ref" -version = "0.2.1" +name = "objc2-core-foundation" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0423ff9973dea4d6bd075934fdda86ebb8c05bdf9d6b0507067d4a1226371d" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "serde", - "thiserror 2.0.17", + "bitflags", ] [[package]] -name = "once_cell" -version = "1.21.3" +name = "objc2-system-configuration" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7216bd11cbda54ccabcab84d523dc93b858ec75ecfb3a7d89513fa22464da396" +dependencies = [ + "objc2-core-foundation", +] + +[[package]] +name = "oco_ref" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "ed0423ff9973dea4d6bd075934fdda86ebb8c05bdf9d6b0507067d4a1226371d" +dependencies = [ + "serde", + "thiserror 2.0.18", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" dependencies = [ "portable-atomic", ] @@ -3360,15 +3462,9 @@ dependencies = [ [[package]] name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "openssl-probe" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-sys" @@ -3509,9 +3605,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.4" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbcfd20a6d4eeba40179f05735784ad32bdaef05ce8e8af05f180d45bb3e7e22" +checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" dependencies = [ "memchr", "ucd-trie", @@ -3519,9 +3615,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.8.4" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f72981ade67b1ca6adc26ec221be9f463f2b5839c7508998daa17c23d94d7f" +checksum = "11f486f1ea21e6c10ed15d5a7c77165d0ee443402f0780849d1768e7d9d6fe77" dependencies = [ "pest", "pest_generator", @@ -3529,9 +3625,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.8.4" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee9efd8cdb50d719a80088b76f81aec7c41ed6d522ee750178f83883d271625" +checksum = "8040c4647b13b210a963c1ed407c1ff4fdfa01c31d6d2a098218702e6664f94f" dependencies = [ "pest", "pest_meta", @@ -3542,9 +3638,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.8.4" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf1d70880e76bdc13ba52eafa6239ce793d85c8e43896507e43dd8984ff05b82" +checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" dependencies = [ "pest", "sha2 0.10.9", @@ -3623,18 +3719,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", @@ -3643,9 +3739,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pin-utils" @@ -3665,9 +3761,23 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "windows-sys 0.61.2", +] [[package]] name = "polyval" @@ -3683,24 +3793,24 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.4" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" dependencies = [ "portable-atomic", ] [[package]] name = "postgres-derive" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56df96f5394370d1b20e49de146f9e6c25aa9ae750f449c9d665eafecb3ccae6" +checksum = "ca1dad89d9ffdbf78502fde418eeede499b87772d88be780478f7f76dc8d471f" dependencies = [ "heck", "proc-macro2", @@ -3710,9 +3820,9 @@ dependencies = [ [[package]] name = "postgres-native-tls" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac73153d92e4bde922bd6f1dfba7f1ab8132266c031153b55e20a1521cd36d49" +checksum = "fef4de47bb81477e0c3deaf153a1b10ae176484713ff1640969f4cb96b653ebc" dependencies = [ "native-tls", "tokio", @@ -3722,27 +3832,27 @@ dependencies = [ [[package]] name = "postgres-protocol" -version = "0.6.9" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbef655056b916eb868048276cfd5d6a7dea4f81560dfd047f97c8c6fe3fcfd4" +checksum = "56201207dac53e2f38e848e31b4b91616a6bb6e0c7205b77718994a7f49e70fc" dependencies = [ "base64", "byteorder", "bytes", "fallible-iterator", - "hmac 0.12.1", - "md-5 0.10.6", + "hmac 0.13.0", + "md-5", "memchr", - "rand 0.9.4", - "sha2 0.10.9", + "rand 0.10.1", + "sha2 0.11.0", "stringprep", ] [[package]] name = "postgres-types" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4605b7c057056dd35baeb6ac0c0338e4975b1f2bef0f65da953285eb007095" +checksum = "8dc729a129e682e8d24170cd30ae1aa01b336b096cbb56df6d534ffec133d186" dependencies = [ "bytes", "fallible-iterator", @@ -3753,9 +3863,9 @@ dependencies = [ [[package]] name = "potential_utf" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] @@ -3796,11 +3906,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.23.9", + "toml_edit 0.25.11+spec-1.1.0", ] [[package]] @@ -3872,7 +3982,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", "web-time", @@ -3894,7 +4004,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.17", + "thiserror 2.0.18", "tinyvec", "tracing", "web-time", @@ -3947,9 +4057,9 @@ dependencies = [ [[package]] name = "quoted_printable" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "640c9bd8497b02465aeef5375144c26062e0dcd5939dfcbb0f5db76cb8c17c73" +checksum = "478e0585659a122aa407eb7e3c0e1fa51b1d8a870038bd29f0cf4a8551eea972" [[package]] name = "r-efi" @@ -3957,6 +4067,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "rand" version = "0.8.6" @@ -3975,7 +4091,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.3", + "rand_core 0.9.5", +] + +[[package]] +name = "rand" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" +dependencies = [ + "chacha20", + "getrandom 0.4.2", + "rand_core 0.10.1", ] [[package]] @@ -3995,7 +4122,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -4004,23 +4131,29 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + [[package]] name = "reactive_graph" -version = "0.2.11" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4043190442021086719fb9183daacb050f44d4ed8d3a1c8534e366d45dd95c29" +checksum = "00c5a025366836190c7030e883cc2bcd9e384ff555336e3c7954741ca411b177" dependencies = [ "any_spawner", "async-lock", @@ -4036,7 +4169,7 @@ dependencies = [ "send_wrapper", "serde", "slotmap", - "thiserror 2.0.17", + "thiserror 2.0.18", "web-sys", ] @@ -4052,24 +4185,24 @@ dependencies = [ "or_poisoned", "paste", "reactive_graph", - "reactive_stores_macro", + "reactive_stores_macro 0.2.6", "rustc-hash", "send_wrapper", ] [[package]] name = "reactive_stores" -version = "0.3.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b73d94139821e0a2f31fb4e0eaf6ebbcf4d15c5e2fb353dc3babd4f6d35674" +checksum = "c30fd35b7d299c591293bb69fed47a703eb2703b1cff0493e78b16ed007e5382" dependencies = [ - "dashmap", "guardian", + "indexmap", "itertools", "or_poisoned", "paste", "reactive_graph", - "reactive_stores_macro", + "reactive_stores_macro 0.4.2", "rustc-hash", "send_wrapper", ] @@ -4087,6 +4220,19 @@ dependencies = [ "syn", ] +[[package]] +name = "reactive_stores_macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d8e790a5ae5ddf9b7fa380c728375b06858e0cca7d063a73b3408320c523e1" +dependencies = [ + "convert_case 0.11.0", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "redox_syscall" version = "0.5.18" @@ -4098,9 +4244,9 @@ dependencies = [ [[package]] name = "refinery" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52c427f2572afe5c6cbfa2b1bf40071c89bf1a8539e958ea582842f6f38dcfae" +checksum = "ee5133e5b207e5703c2a4a9dc9bd8c8f2cc74c4ac04ca5510acaa907012c77ac" dependencies = [ "refinery-core", "refinery-macros", @@ -4108,9 +4254,9 @@ dependencies = [ [[package]] name = "refinery-core" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702655abfc67f93a6f735e9fa4ace7d2e580633f8961f28acbfd7583ddce936c" +checksum = "023a2a96d959c9b5b5da78e965bfdb1363b365bf5e84531a67d0eee827a702a3" dependencies = [ "async-trait", "cfg-if", @@ -4120,7 +4266,7 @@ dependencies = [ "regex", "serde", "siphasher", - "thiserror 2.0.17", + "thiserror 2.0.18", "time", "tokio", "tokio-postgres", @@ -4131,9 +4277,9 @@ dependencies = [ [[package]] name = "refinery-macros" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5145756cdf293b5089dc6b4f103f1a1229cc55d67082c866f8c8289531c4b983" +checksum = "c56c2e960c8e47c7c5c30ad334afea8b5502da796a59e34d640d6239d876d924" dependencies = [ "proc-macro2", "quote", @@ -4144,9 +4290,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -4156,9 +4302,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -4173,22 +4319,22 @@ checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reqwest" -version = "0.13.1" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04e9018c9d814e5f30cc16a0f03271aeab3571e609612d9fe78c1aa8d11c2f62" +checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" dependencies = [ "base64", "bytes", "encoding_rs", "futures-core", "h2", - "http 1.4.0", + "http 1.4.1", "http-body 1.0.1", "http-body-util", "hyper", @@ -4229,13 +4375,12 @@ dependencies = [ [[package]] name = "rhai" -version = "1.23.6" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4e35aaaa439a5bda2f8d15251bc375e4edfac75f9865734644782c9701b5709" +checksum = "5cdc552c1c198f0565e1deb9d85d380caedcc488e6ac3cb6f947c7ae77041e08" dependencies = [ "ahash", "bitflags", - "instant", "no-std-compat", "num-traits", "once_cell", @@ -4244,13 +4389,14 @@ dependencies = [ "smallvec", "smartstring", "thin-vec", + "web-time", ] [[package]] name = "rhai_codegen" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4322a2a4e8cf30771dd9f27f7f37ca9ac8fe812dddd811096a98483080dabe6" +checksum = "3cd3a7535e50bf36857e7be7bec276d334e8c2dfa469c2201226fd01638ea5ca" dependencies = [ "proc-macro2", "quote", @@ -4265,7 +4411,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", @@ -4273,9 +4419,9 @@ dependencies = [ [[package]] name = "ron" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd490c5b18261893f14449cbd28cb9c0b637aebf161cd77900bfdedaff21ec32" +checksum = "4147b952f3f819eca0e99527022f7d6a8d05f111aeb0a62960c74eb283bec8fc" dependencies = [ "bitflags", "once_cell", @@ -4297,7 +4443,7 @@ dependencies = [ "quote", "syn", "syn_derive", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -4312,9 +4458,9 @@ dependencies = [ [[package]] name = "rustc-hash" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" [[package]] name = "rustc_version" @@ -4327,9 +4473,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags", "errno", @@ -4358,17 +4504,17 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ - "openssl-probe 0.2.0", + "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.5.1", + "security-framework", ] [[package]] name = "rustls-pki-types" -version = "1.13.1" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ "web-time", "zeroize", @@ -4376,9 +4522,9 @@ dependencies = [ [[package]] name = "rustls-platform-verifier" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" dependencies = [ "core-foundation 0.10.1", "core-foundation-sys", @@ -4389,7 +4535,7 @@ dependencies = [ "rustls-native-certs", "rustls-platform-verifier-android", "rustls-webpki", - "security-framework 3.5.1", + "security-framework", "security-framework-sys", "webpki-root-certs", "windows-sys 0.61.2", @@ -4436,9 +4582,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ "windows-sys 0.61.2", ] @@ -4465,22 +4611,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework" -version = "3.5.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ "bitflags", "core-foundation 0.10.1", @@ -4491,9 +4624,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.15.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", @@ -4501,9 +4634,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "send_wrapper" @@ -4530,7 +4663,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058" dependencies = [ - "erased-serde 0.4.9", + "erased-serde 0.4.10", "serde", "serde_core", "typeid", @@ -4569,15 +4702,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] @@ -4599,7 +4732,7 @@ checksum = "f3faaf9e727533a19351a43cc5a8de957372163c7d35cc48c90b75cdda13c352" dependencies = [ "percent-encoding", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -4613,9 +4746,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.3" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" dependencies = [ "serde_core", ] @@ -4634,19 +4767,19 @@ dependencies = [ [[package]] name = "server_fn" -version = "0.8.8" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc30228718f62d80a376964baf990edbcb5e97688fdc71183a8ef3d44cb6c89" +checksum = "5d60e4c1dfccd91fe0990141f69f1d5cf5679797ad53aa1b45e5bd658eb119f0" dependencies = [ "base64", "bytes", "const-str", "const_format", - "dashmap", "futures", "gloo-net", - "http 1.4.0", + "http 1.4.1", "js-sys", + "or_poisoned", "pin-project-lite", "rustc_version", "rustversion", @@ -4655,7 +4788,7 @@ dependencies = [ "serde_json", "serde_qs", "server_fn_macro_default", - "thiserror 2.0.17", + "thiserror 2.0.18", "throw_error", "url", "wasm-bindgen", @@ -4667,12 +4800,12 @@ dependencies = [ [[package]] name = "server_fn_macro" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "950b8cfc9ff5f39ca879c5a7c5e640de2695a199e18e424c3289d0964cabe642" +checksum = "1295b54815397d30d986b63f93cfd515fa86d5e528e0bb589ce9d530502f9e0f" dependencies = [ "const_format", - "convert_case 0.8.0", + "convert_case 0.11.0", "proc-macro2", "quote", "rustc_version", @@ -4755,10 +4888,11 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.7" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] @@ -4772,17 +4906,33 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "slog" @@ -4854,12 +5004,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -4997,9 +5147,9 @@ dependencies = [ [[package]] name = "system-configuration" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ "bitflags", "core-foundation 0.9.4", @@ -5018,9 +5168,9 @@ dependencies = [ [[package]] name = "tachys" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b2db11e455f7e84e2cc3e76f8a3f3843f7956096265d5ecff781eabe235077" +checksum = "2989c94c59db8497727875aa561d4d0daa3cc79b5774d5ced48263f7091beff1" dependencies = [ "any_spawner", "async-trait", @@ -5033,14 +5183,12 @@ dependencies = [ "indexmap", "itertools", "js-sys", - "linear-map", "next_tuple", "oco_ref", "or_poisoned", - "parking_lot", "paste", "reactive_graph", - "reactive_stores 0.3.0", + "reactive_stores 0.4.3", "rustc-hash", "rustc_version", "send_wrapper", @@ -5064,12 +5212,12 @@ checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" [[package]] name = "tempfile" -version = "3.23.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.2", "once_cell", "rustix", "windows-sys 0.61.2", @@ -5151,9 +5299,9 @@ dependencies = [ [[package]] name = "thin-vec" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "259cdf8ed4e4aca6f1e9d011e10bd53f524a2d0637d7b28450f6c64ac298c4c6" +checksum = "b0f7e269b48f0a7dd0146680fa24b50cc67fc0373f086a5b2f99bd084639b482" dependencies = [ "serde", ] @@ -5169,11 +5317,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.17", + "thiserror-impl 2.0.18", ] [[package]] @@ -5189,9 +5337,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", @@ -5258,9 +5406,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -5268,9 +5416,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -5283,9 +5431,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.49.0" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ "bytes", "libc", @@ -5300,9 +5448,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", @@ -5321,9 +5469,9 @@ dependencies = [ [[package]] name = "tokio-postgres" -version = "0.7.15" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b40d66d9b2cfe04b628173409368e58247e8eddbbd3b0e6c6ba1d09f20f6c9e" +checksum = "4dd8df5ef180f6364759a6f00f7aadda4fbbac86cdee37480826a6ff9f3574ce" dependencies = [ "async-trait", "byteorder", @@ -5338,7 +5486,7 @@ dependencies = [ "pin-project-lite", "postgres-protocol", "postgres-types", - "rand 0.9.4", + "rand 0.10.1", "socket2", "tokio", "tokio-util", @@ -5357,9 +5505,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", @@ -5368,9 +5516,9 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" +checksum = "8f72a05e828585856dacd553fba484c242c46e391fb0e58917c942ee9202915c" dependencies = [ "futures-util", "log", @@ -5406,15 +5554,15 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.8" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" dependencies = [ "serde_core", - "serde_spanned 1.0.3", - "toml_datetime 0.7.3", + "serde_spanned 1.1.1", + "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow", + "winnow 1.0.3", ] [[package]] @@ -5428,9 +5576,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.3" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" dependencies = [ "serde_core", ] @@ -5446,28 +5594,28 @@ dependencies = [ "serde_spanned 0.6.9", "toml_datetime 0.6.11", "toml_write", - "winnow", + "winnow 0.7.15", ] [[package]] name = "toml_edit" -version = "0.23.9" +version = "0.25.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d7cbc3b4b49633d57a0509303158ca50de80ae32c265093b24c414705807832" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" dependencies = [ "indexmap", - "toml_datetime 0.7.3", + "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow", + "winnow 1.0.3", ] [[package]] name = "toml_parser" -version = "1.0.4" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow", + "winnow 1.0.3", ] [[package]] @@ -5478,9 +5626,9 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "tower" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", @@ -5494,20 +5642,20 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ "bitflags", "bytes", "futures-util", - "http 1.4.0", + "http 1.4.1", "http-body 1.0.1", - "iri-string", "pin-project-lite", "tower", "tower-layer", "tower-service", + "url", ] [[package]] @@ -5568,9 +5716,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "matchers", "nu-ansi-term", @@ -5592,55 +5740,34 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tungstenite" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" +checksum = "6c01152af293afb9c7c2a57e4b559c5620b421f6d133261c60dd2d0cdb38e6b8" dependencies = [ "bytes", "data-encoding", - "http 1.4.0", + "http 1.4.1", "httparse", "log", "rand 0.9.4", "sha1 0.10.6", - "thiserror 2.0.17", - "utf-8", -] - -[[package]] -name = "typed-builder" -version = "0.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fef81aec2ca29576f9f6ae8755108640d0a86dd3161b2e8bca6cfa554e98f77d" -dependencies = [ - "typed-builder-macro 0.21.2", + "thiserror 2.0.18", ] [[package]] name = "typed-builder" -version = "0.22.0" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "398a3a3c918c96de527dc11e6e846cd549d4508030b8a33e1da12789c856b81a" +checksum = "31aa81521b70f94402501d848ccc0ecaa8f93c8eb6999eb9747e72287757ffda" dependencies = [ - "typed-builder-macro 0.22.0", -] - -[[package]] -name = "typed-builder-macro" -version = "0.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecb9ecf7799210407c14a8cfdfe0173365780968dc57973ed082211958e0b18" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "typed-builder-macro", ] [[package]] name = "typed-builder-macro" -version = "0.22.0" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e48cea23f68d1f78eb7bc092881b6bb88d3d6b5b7e6234f6f9c911da1ffb221" +checksum = "076a02dc54dd46795c2e9c8282ed40bcfb1e22747e955de9389a1de28190fb26" dependencies = [ "proc-macro2", "quote", @@ -5673,9 +5800,9 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-normalization" @@ -5694,9 +5821,9 @@ checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" [[package]] name = "unicode-segmentation" -version = "1.12.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" [[package]] name = "unicode-xid" @@ -5710,7 +5837,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common 0.1.7", + "crypto-common 0.1.6", "subtle", ] @@ -5722,9 +5849,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.7" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", @@ -5732,12 +5859,6 @@ dependencies = [ "serde", ] -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - [[package]] name = "utf8-width" version = "0.1.8" @@ -5752,11 +5873,11 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.19.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.2", "js-sys", "wasm-bindgen", ] @@ -5810,26 +5931,47 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +[[package]] +name = "wasi" +version = "0.14.7+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" +dependencies = [ + "wasip2", +] + [[package]] name = "wasip2" -version = "1.0.1+wasi-0.2.4" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.57.1", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", ] [[package]] name = "wasite" -version = "0.1.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" +checksum = "66fe902b4a6b8028a753d5424909b764ccf79b7a209eac9bf97e59cda9f71a42" +dependencies = [ + "wasi 0.14.7+wasi-0.2.4", +] [[package]] name = "wasm-bindgen" -version = "0.2.106" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" dependencies = [ "cfg-if", "once_cell", @@ -5840,22 +5982,19 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.56" +version = "0.4.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" +checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" dependencies = [ - "cfg-if", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.106" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5863,9 +6002,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.106" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" dependencies = [ "bumpalo", "proc-macro2", @@ -5876,18 +6015,18 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.106" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" dependencies = [ "unicode-ident", ] [[package]] name = "wasm-bindgen-test" -version = "0.3.56" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25e90e66d265d3a1efc0e72a54809ab90b9c0c515915c67cdf658689d2c22c6c" +checksum = "6bb55e2540ad1c56eec35fd63e2aea15f83b11ce487fd2de9ad11578dfc047ea" dependencies = [ "async-trait", "cast", @@ -5902,24 +6041,53 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "wasm-bindgen-test-macro", + "wasm-bindgen-test-shared", ] [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.56" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7150335716dce6028bead2b848e72f47b45e7b9422f64cccdc23bedca89affc1" +checksum = "caf0ca1bd612b988616bac1ab34c4e4290ef18f7148a1d8b7f31c150080e9295" dependencies = [ "proc-macro2", "quote", "syn", ] +[[package]] +name = "wasm-bindgen-test-shared" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cda5ecc67248c48d3e705d3e03e00af905769b78b9d2a1678b663b8b9d4472" + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + [[package]] name = "wasm-streams" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" dependencies = [ "futures-util", "js-sys", @@ -5930,9 +6098,9 @@ dependencies = [ [[package]] name = "wasm_split_helpers" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a114b3073258dd5de3d812cdd048cca6842342755e828a14dbf15f843f2d1b84" +checksum = "d0cb6d1008be3c4c5abc31a407bfb8c8449ae14efc8561c1db821f79b9614b0a" dependencies = [ "async-once-cell", "wasm_split_macros", @@ -5940,9 +6108,9 @@ dependencies = [ [[package]] name = "wasm_split_macros" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56481f8ed1a9f9ae97ea7b08a5e2b12e8adf9a7818a6ba952b918e09c7be8bf0" +checksum = "d0a659ffe5c7f4538aa6357c07e3d73221cc61eba03bd9a081e14bc91ed09b8c" dependencies = [ "base16", "quote", @@ -5950,11 +6118,23 @@ dependencies = [ "syn", ] +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + [[package]] name = "web-sys" -version = "0.3.83" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" +checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" dependencies = [ "js-sys", "wasm-bindgen", @@ -5972,20 +6152,22 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.5" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36a29fc0408b113f68cf32637857ab740edfafdf460c326cd2afaa2d84cc05dc" +checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" dependencies = [ "rustls-pki-types", ] [[package]] name = "whoami" -version = "1.6.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" +checksum = "998767ef88740d1f5b0682a9c53c24431453923962269c2db68ee43788c5a40d" dependencies = [ + "libc", "libredox", + "objc2-system-configuration", "wasite", "web-sys", ] @@ -6069,15 +6251,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.52.0" @@ -6105,21 +6278,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-targets" version = "0.52.6" @@ -6153,12 +6311,6 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -6171,12 +6323,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -6189,12 +6335,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -6219,12 +6359,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -6237,12 +6371,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -6255,12 +6383,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -6273,12 +6395,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -6293,24 +6409,121 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.7.14" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + [[package]] name = "wit-bindgen" -version = "0.46.0" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] [[package]] name = "writeable" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "xmlparser" @@ -6326,13 +6539,13 @@ checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" [[package]] name = "yaml-rust2" -version = "0.10.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2462ea039c445496d8793d052e13787f2b90e750b833afee748e601c17621ed9" +checksum = "631a50d867fafb7093e709d75aaee9e0e0d5deb934021fcea25ac2fe09edc51e" dependencies = [ "arraydeque", "encoding_rs", - "hashlink 0.10.0", + "hashlink 0.11.0", ] [[package]] @@ -6343,9 +6556,9 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "yoke" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -6354,9 +6567,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", @@ -6366,18 +6579,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.31" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.31" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", @@ -6386,18 +6599,18 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", @@ -6413,9 +6626,9 @@ checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[package]] name = "zerotrie" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", "yoke", @@ -6424,9 +6637,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "yoke", "zerofrom", @@ -6435,11 +6648,17 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", "syn", ] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/backend/Cargo.toml b/backend/Cargo.toml index ce5aac9..8a781f3 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -7,8 +7,8 @@ license = "BlueOak-1.0.0" [dependencies] anyhow = "1.0" argon2 = "0.5" -async-graphql = "7.1" -async-graphql-axum = "7.1" +async-graphql = "7.2" +async-graphql-axum = "7.2" aws-credential-types = "1.2.14" aws-sdk-s3 = { version = "1.133.0", default-features = false, features = [ "default-https-client", @@ -24,7 +24,7 @@ axum-extra = { version = "0.12", features = [ ] } axum-macros = "0.5" blake3 = "1.8" -casbin = { version = "2.19", features = ["logging", "runtime-tokio"] } +casbin = { version = "2.20", features = ["logging", "runtime-tokio"] } config = "0.15" deadpool = "0.12" deadpool-postgres = { version = "0.14", features = ["rt_tokio_1", "serde"] } @@ -41,14 +41,14 @@ lettre = { version = "0.11", features = [ ] } moka = { version = "0.12", features = ["future"] } postgres-types = { version = "0.2", features = ["derive"] } -rand = "0.8" +rand = "0.10" refinery = { version = "0.9", features = ["tokio-postgres"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" shared = { path = "../shared" } thiserror = "2.0" time = "0.3" -tokio = { version = "1.49", features = ["full"] } +tokio = { version = "1.52", features = ["full"] } tokio-postgres = { version = "0.7", features = ["with-jiff-0_2"] } tower = { version = "0.5", features = ["util"] } tower-http = { version = "0.6", features = ["cors"] } diff --git a/backend/src/graphql/queries/mutation.rs b/backend/src/graphql/queries/mutation.rs index bc7ca4a..e794cac 100644 --- a/backend/src/graphql/queries/mutation.rs +++ b/backend/src/graphql/queries/mutation.rs @@ -46,7 +46,10 @@ use { PasswordHash, PasswordHasher, PasswordVerifier, - password_hash::SaltString, + password_hash::{ + SaltString, + rand_core::OsRng, + }, }, async_graphql::{ Context, @@ -68,9 +71,8 @@ use { futures::future::join_all, jiff::Timestamp, rand::{ - Rng, - distributions::Alphanumeric, - rngs::OsRng, + RngExt, + distr::Alphanumeric, }, std::sync::{ Arc, @@ -760,7 +762,7 @@ impl Mutation { let user_opt = User::by_email(ctx, &email).await?; if let Some(user) = user_opt { let token: String = - rand::thread_rng().sample_iter(&Alphanumeric).take(32).map(char::from).collect(); + rand::rng().sample_iter(Alphanumeric).take(32).map(char::from).collect(); let token_hash = blake3::hash(token.as_bytes()).to_string(); diff --git a/deny.toml b/deny.toml index da30b3d..126dd47 100644 --- a/deny.toml +++ b/deny.toml @@ -3,9 +3,6 @@ all-features = true [advisories] ignore = [ - # `instant` is pulled through casbin -> rhai. There is no safe upgrade for - # the crate itself; keep this visible in dependency migration work. - "RUSTSEC-2024-0384", # `paste` is still used by the current Leptos ecosystem. There is no safe # upgrade for the crate itself. "RUSTSEC-2024-0436", diff --git a/frontend/Cargo.toml b/frontend/Cargo.toml index 7c73b82..442036a 100644 --- a/frontend/Cargo.toml +++ b/frontend/Cargo.toml @@ -11,7 +11,7 @@ anyhow = "1.0" console_error_panic_hook = "0.1" console_log = "1" email_address = "0.2" -graphql_client = "0.15" +graphql_client = "0.16" leptos = { version = "0.8", features = ["csr"] } leptos-leaflet = { version = "0.10", features = [ "csr", @@ -19,7 +19,7 @@ leptos-leaflet = { version = "0.10", features = [ leptos_meta = { version = "0.8" } leptos_router = { version = "0.8" } log = "0.4" -lucide-leptos = { version = "2", features = [ +lucide-leptos = { version = "3", features = [ "account", "arrows", "files", @@ -37,7 +37,7 @@ shared = { path = "../shared" } # @todo Bump this once out of beta. thaw = { version = "0.5.0-beta", features = ["csr"] } thiserror = "2.0" -tokio = { version = "1.49", features = [ +tokio = { version = "1.52", features = [ "io-util", "macros", "rt", @@ -61,8 +61,8 @@ web-sys = { version = "0.3", features = [ ] } [dev-dependencies] -# Locked to =0.2.106 since that's the latest available on nixpkgs -wasm-bindgen = "=0.2.106" +# Locked to match wasm-bindgen-cli_0_2_118 from nixpkgs. +wasm-bindgen = "=0.2.118" wasm-bindgen-test = "0.3" [lints] From 908c9f148dc99423eaeb76fdd1c3256b2e24a179 Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Wed, 27 May 2026 15:45:50 +0100 Subject: [PATCH 16/28] Document production deployment --- README.md | 5 ++ docs/deployment.md | 132 +++++++++++++++++++++++++++++++++++++++++++++ justfile | 4 +- 3 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 docs/deployment.md diff --git a/README.md b/README.md index aa8612f..e4d1698 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,11 @@ The project uses [Just](https://github.com/casey/just) as a task runner. - `just regenerate-schema`: Introspect the backend and update the frontend GraphQL schema. - `just scan-hardcoded`: Scan the codebase for hardcoded secrets or values. +## Production Deployment + +Production uses real PostgreSQL, SMTP, S3-compatible storage, runtime secrets, +and a generated frontend `/config.json`. See [Production Deployment](docs/deployment.md). + ## Tech Stack | Layer | Technology | diff --git a/docs/deployment.md b/docs/deployment.md new file mode 100644 index 0000000..ae2f66b --- /dev/null +++ b/docs/deployment.md @@ -0,0 +1,132 @@ +# Production Deployment + +This project can run outside the Nix development service graph. Production +deployments should provide real runtime services and secrets through the +hosting platform, not through `devenv/flake.nix`. + +## Runtime Shape + +- Run the backend as a service or container with environment variables supplied + by the production platform. +- Serve the frontend as static files built by Trunk. +- Provide `/config.json` at the frontend origin at deploy time. +- Use a real PostgreSQL instance or managed PostgreSQL service. +- Use AWS S3, RustFS, Garage, or another S3-compatible object store. +- Put TLS and a reverse proxy or load balancer in front of the public app. + +The process-compose services in `devenv/flake.nix` are for local development +and CI only. Their deterministic credentials are not production secrets. + +## Backend Environment + +The backend reads configuration from environment variables. + +Required database settings: + +- `PG__DBNAME` +- `PG__HOST` +- `PG__PORT` + +Required SMTP settings: + +- `SMTP_HOST` +- `SMTP_USER` +- `SMTP_PASS` +- `SMTP_FROM` + +Required app settings: + +- `COOKIE_SECRET` +- `FRONTEND_URL` +- `SERVER_HOST` +- `SERVER_PORT` +- `CORS_ALLOWED_ORIGINS` + +Required S3-compatible storage settings: + +- `S3_ENDPOINT_URL` +- `S3_ACCESS_KEY` +- `S3_SECRET_KEY` +- `S3_BUCKET_NAME` +- `S3_REGION` +- `S3_FORCE_PATH_STYLE` +- `S3_PRESIGNED_URL_TTL_SECONDS` + +`COOKIE_SECRET`, `SMTP_PASS`, `S3_ACCESS_KEY`, and `S3_SECRET_KEY` must come +from production secret management. Do not copy values from `.env.example` or +`devenv/flake.nix` into production. + +`S3_PRESIGNED_URL_TTL_SECONDS` must be between `1` and `604800`. + +## Frontend Runtime Config + +The frontend is a static client-side rendered app. At runtime it fetches +`/config.json` from the same origin as the frontend. + +Production must provide a concrete `/config.json` during deployment: + +```json +{ + "api_url": "https://api.example.com" +} +``` + +`api_url` is public runtime configuration, not a secret. It should point to the +public backend GraphQL/API origin used by browsers. + +The local development API URL, `http://127.0.0.1:8000`, is not suitable for +production. Do not deploy a frontend build with that runtime config. + +## PostgreSQL + +Production should use a real PostgreSQL instance or a managed PostgreSQL +service. Do not use local `data/postgres` state from process-compose. + +The backend runs database migrations on startup using the configured database +connection. The database user must have the privileges needed to run those +migrations. + +## Object Storage + +The backend uses the AWS Rust S3 SDK against the configured S3-compatible +endpoint. The app needs: + +- object upload +- object metadata lookup +- presigned GET URLs +- content-type metadata +- bulk object delete + +Path-style guidance: + +- Local RustFS uses `S3_FORCE_PATH_STYLE=true`. +- AWS S3 normally uses `S3_FORCE_PATH_STYLE=false`. +- Other S3-compatible services should follow the provider's requirements. + +The configured bucket must be usable by the configured credentials. The backend +storage helper can create or verify a bucket for local and CI RustFS, but +production bucket lifecycle should be managed intentionally by the deployment. + +## Reverse Proxy And TLS + +Serve the frontend over HTTPS in production. + +Route backend GraphQL and upload traffic to the backend service. The backend +serves GraphQL at `/` and uploads at `/api/locations/`. + +Set `FRONTEND_URL` and `CORS_ALLOWED_ORIGINS` to the public frontend origin. +For example: + +```sh +FRONTEND_URL=https://memory-map.example.com +CORS_ALLOWED_ORIGINS=https://memory-map.example.com +``` + +Keep browser traffic on HTTPS so authenticated cookies and presigned media URL +access are not exposed over plaintext connections. + +## Out Of Scope + +This repository does not currently define a production Docker image, systemd +unit, NixOS module, Kubernetes manifest, or hosting-specific deployment +artifact. Add those only after choosing a concrete production platform. diff --git a/justfile b/justfile index 6c4b4dd..0886a6e 100644 --- a/justfile +++ b/justfile @@ -70,7 +70,7 @@ doc *args: set -euo pipefail ascii_roots=() - for path in README.md CONTRIBUTING.md AGENTS.md frontend/README.md backend/src frontend/src shared/src; do + for path in README.md CONTRIBUTING.md AGENTS.md docs frontend/README.md backend/src frontend/src shared/src; do if [[ -e "$path" ]]; then ascii_roots+=("$path") fi @@ -85,7 +85,7 @@ doc *args: exit 1 fi - {{ direnv_prefix }} lychee --offline --no-progress README.md frontend/README.md + {{ direnv_prefix }} lychee --offline --no-progress README.md docs/deployment.md frontend/README.md if [ "$#" -eq 0 ]; then set -- --workspace --all-features --no-deps From 566a223ffaeb1d379537004b7043626a0977fa1c Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Wed, 27 May 2026 15:49:02 +0100 Subject: [PATCH 17/28] Stop tracking frontend runtime config --- .gitignore | 1 + README.md | 5 +++++ docs/deployment.md | 9 ++++++--- frontend/config.example.json | 3 +++ frontend/public/config.json | 3 --- justfile | 11 +++++++++-- 6 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 frontend/config.example.json delete mode 100644 frontend/public/config.json diff --git a/.gitignore b/.gitignore index e17d543..149cb34 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ data/pg1/ data/postgres/ data/rustfs/ .env +frontend/public/config.json .direnv/ /result /result-* diff --git a/README.md b/README.md index e4d1698..03da885 100644 --- a/README.md +++ b/README.md @@ -53,11 +53,15 @@ cd memory-map ```sh cp .env.example .env +just frontend-config direnv allow ``` This installs all dependencies and auto-loads the development shell whenever you enter the directory. +`just frontend-config` creates the ignored local runtime config at +`frontend/public/config.json` from `frontend/config.example.json`. + You can optionally configure the build mode and other settings by editing `.env`: - `BUILD_MODE="debug"` (default): Faster compilation, includes debug info. @@ -108,6 +112,7 @@ The project uses [Just](https://github.com/casey/just) as a task runner. - `just servers`: Start PostgreSQL and RustFS via Nix. - `just clean-service-state`: Remove local PostgreSQL and storage service state. - `just backend`: Start the Axum backend with hot-reloading (via Bacon). +- `just frontend-config`: Create local frontend runtime config when missing. - `just frontend`: Start the Leptos frontend (via Trunk). - `just fmt`: Format Rust, Nix, Markdown, YAML, and TOML files. - `just check`: Run `cargo check` for the workspace. diff --git a/docs/deployment.md b/docs/deployment.md index ae2f66b..eda7ae9 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -61,7 +61,8 @@ from production secret management. Do not copy values from `.env.example` or ## Frontend Runtime Config The frontend is a static client-side rendered app. At runtime it fetches -`/config.json` from the same origin as the frontend. +`/config.json` from the same origin as the frontend. The concrete runtime file +`frontend/public/config.json` is intentionally ignored by Git. Production must provide a concrete `/config.json` during deployment: @@ -74,8 +75,10 @@ Production must provide a concrete `/config.json` during deployment: `api_url` is public runtime configuration, not a secret. It should point to the public backend GraphQL/API origin used by browsers. -The local development API URL, `http://127.0.0.1:8000`, is not suitable for -production. Do not deploy a frontend build with that runtime config. +For local development, run `just frontend-config` to create +`frontend/public/config.json` from `frontend/config.example.json`. The example +uses the local backend API URL, `http://127.0.0.1:8000`, which is not suitable +for production. Do not deploy a frontend build with that local runtime config. ## PostgreSQL diff --git a/frontend/config.example.json b/frontend/config.example.json new file mode 100644 index 0000000..2a5dea4 --- /dev/null +++ b/frontend/config.example.json @@ -0,0 +1,3 @@ +{ + "api_url": "http://127.0.0.1:8000" +} diff --git a/frontend/public/config.json b/frontend/public/config.json deleted file mode 100644 index 077c969..0000000 --- a/frontend/public/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "api_url": "http://127.0.0.1:8000" -} diff --git a/justfile b/justfile index 0886a6e..4153426 100644 --- a/justfile +++ b/justfile @@ -31,8 +31,15 @@ clean-service-state: backend: {{ direnv_prefix }} bash -c 'cd backend; {{ log_prefix }} bacon run -- {{ release_flag }}' +# Create local frontend runtime config when missing. +frontend-config: + @if [ ! -f frontend/public/config.json ]; then \ + cp frontend/config.example.json frontend/public/config.json; \ + echo "Created frontend/public/config.json from frontend/config.example.json"; \ + fi + # Start frontend server. https://github.com/trunk-rs/trunk/issues/732#issuecomment-2391810077 -frontend: +frontend: frontend-config {{ direnv_prefix }} bash -c 'cd frontend; ping -c 1 8.8.8.8 && pnpm i --prefer-offline; env -u NO_COLOR trunk serve {{ release_flag }} --skip-version-check --offline --open' # Regenerate "frontend/graphql/schema.json". @@ -103,7 +110,7 @@ build *args: {{ direnv_prefix }} cargo build "$@" # Build the frontend application through Trunk. -frontend-build: +frontend-build: frontend-config {{ direnv_prefix }} bash -c 'cd frontend && pnpm install --frozen-lockfile --prefer-offline && env -u NO_COLOR trunk build {{ release_flag }} --skip-version-check' # Run any cargo subcommand except test; use `just test` for tests. From e702ec71767e02ac5780a6ee15afde891a41499d Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Wed, 27 May 2026 15:57:48 +0100 Subject: [PATCH 18/28] Centralize local service defaults --- devenv/flake.nix | 93 +++++++++++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/devenv/flake.nix b/devenv/flake.nix index ab75ea9..b44681c 100644 --- a/devenv/flake.nix +++ b/devenv/flake.nix @@ -124,19 +124,40 @@ meta.mainProgram = "memory-map-storage-bootstrap"; }; - dbName = "db"; - postgresPort = 5432; - postgresDataDir = "data/postgres"; + localPostgres = { + dbName = "db"; + host = "127.0.0.1"; + port = 5432; + dataDir = "data/postgres"; + }; + localRustfs = { + dataDir = "data/rustfs"; + apiAddress = "127.0.0.1:9000"; + consoleAddress = "127.0.0.1:9001"; + consoleEnabled = true; + healthEndpointEnabled = true; + }; + localS3 = { + endpointUrl = "http://${localRustfs.apiAddress}"; + region = "us-east-1"; + bucketName = "memory-map"; + forcePathStyle = true; + presignedUrlTtlSeconds = 604800; + # Deterministic local/CI credentials for the RustFS service. + # These are not production secrets. + accessKey = "memorymapdev"; + secretKey = "memorymapdevsecret"; + }; postgresPackage = pkgs.postgresql.withPackages (postgresExtensions: [ postgresExtensions.postgis ]); postgresHbaConf = pkgs.writeText "pg_hba.conf" '' # Generated by Nix local all all trust - host all all 127.0.0.1/32 trust + host all all ${localPostgres.host}/32 trust host all all ::1/128 trust local replication all trust - host replication all 127.0.0.1/32 trust + host replication all ${localPostgres.host}/32 trust host replication all ::1/128 trust ''; postgresInit = pkgs.writeShellApplication { @@ -148,7 +169,7 @@ text = '' set -euo pipefail - PGDATA="$(readlink -m "${postgresDataDir}")" + PGDATA="$(readlink -m "${localPostgres.dataDir}")" export PGDATA mkdir -p "$PGDATA" @@ -169,13 +190,13 @@ text = '' set -euo pipefail - PGDATA="$(readlink -m "${postgresDataDir}")" + PGDATA="$(readlink -m "${localPostgres.dataDir}")" export PGDATA exec postgres \ -D "$PGDATA" \ - -c listen_addresses=127.0.0.1 \ - -c port=${toString postgresPort} \ + -c listen_addresses=${localPostgres.host} \ + -c port=${toString localPostgres.port} \ -c hba_file=${postgresHbaConf} \ -c unix_socket_directories= ''; @@ -189,13 +210,13 @@ text = '' set -euo pipefail - export PGHOST=127.0.0.1 - export PGPORT=${toString postgresPort} + export PGHOST=${localPostgres.host} + export PGPORT=${toString localPostgres.port} export PGDATABASE=postgres export PGCONNECT_TIMEOUT=5 - if ! psql -v ON_ERROR_STOP=1 -tAc "SELECT 1 FROM pg_database WHERE datname = '${dbName}'" | grep -qx 1; then - createdb "${dbName}" + if ! psql -v ON_ERROR_STOP=1 -tAc "SELECT 1 FROM pg_database WHERE datname = '${localPostgres.dbName}'" | grep -qx 1; then + createdb "${localPostgres.dbName}" fi psql -v ON_ERROR_STOP=1 -tAc "SELECT name FROM pg_available_extensions WHERE name = 'postgis'" | grep -qx postgis @@ -210,19 +231,11 @@ text = '' set -euo pipefail - psql -h 127.0.0.1 -p ${toString postgresPort} -d ${dbName} -v ON_ERROR_STOP=1 -c 'SELECT version();' - psql -h 127.0.0.1 -p ${toString postgresPort} -d ${dbName} -v ON_ERROR_STOP=1 -tAc "SELECT name FROM pg_available_extensions WHERE name = 'postgis'" | grep -qx postgis + psql -h ${localPostgres.host} -p ${toString localPostgres.port} -d ${localPostgres.dbName} -v ON_ERROR_STOP=1 -c 'SELECT version();' + psql -h ${localPostgres.host} -p ${toString localPostgres.port} -d ${localPostgres.dbName} -v ON_ERROR_STOP=1 -tAc "SELECT name FROM pg_available_extensions WHERE name = 'postgis'" | grep -qx postgis ''; }; - rustfsDataDir = "data/rustfs"; - rustfsApiAddress = "127.0.0.1:9000"; - rustfsConsoleAddress = "127.0.0.1:9001"; - s3EndpointUrl = "http://${rustfsApiAddress}"; - s3Region = "us-east-1"; - s3BucketName = "memory-map"; - s3AccessKey = "memorymapdev"; - s3SecretKey = "memorymapdevsecret"; rustfsStart = pkgs.writeShellApplication { name = "memory-map-rustfs-start"; runtimeInputs = [ @@ -232,7 +245,7 @@ text = '' set -euo pipefail - data_dir="$(readlink -m "${rustfsDataDir}")" + data_dir="$(readlink -m "${localRustfs.dataDir}")" mkdir -p "$data_dir" exec rustfs server "$data_dir" ''; @@ -243,13 +256,13 @@ text = '' set -euo pipefail - export S3_ENDPOINT_URL="${s3EndpointUrl}" - export S3_ACCESS_KEY="${s3AccessKey}" - export S3_SECRET_KEY="${s3SecretKey}" - export S3_BUCKET_NAME="${s3BucketName}" - export S3_REGION="${s3Region}" - export S3_FORCE_PATH_STYLE=true - export S3_PRESIGNED_URL_TTL_SECONDS=604800 + export S3_ENDPOINT_URL="${localS3.endpointUrl}" + export S3_ACCESS_KEY="${localS3.accessKey}" + export S3_SECRET_KEY="${localS3.secretKey}" + export S3_BUCKET_NAME="${localS3.bucketName}" + export S3_REGION="${localS3.region}" + export S3_FORCE_PATH_STYLE=${lib.boolToString localS3.forcePathStyle} + export S3_PRESIGNED_URL_TTL_SECONDS=${toString localS3.presignedUrlTtlSeconds} exec memory-map-storage-bootstrap ''; @@ -362,7 +375,7 @@ timeout_seconds = 10; }; readiness_probe = { - exec.command = "${postgresPackage}/bin/pg_isready -h 127.0.0.1 -p ${toString postgresPort} -d postgres"; + exec.command = "${postgresPackage}/bin/pg_isready -h ${localPostgres.host} -p ${toString localPostgres.port} -d postgres"; initial_delay_seconds = 1; period_seconds = 2; timeout_seconds = 5; @@ -379,7 +392,7 @@ depends_on."pg1".condition = "process_healthy"; }; pgweb = { - environment.PGWEB_DATABASE_URL = "postgres://127.0.0.1:${toString postgresPort}/${dbName}"; + environment.PGWEB_DATABASE_URL = "postgres://${localPostgres.host}:${toString localPostgres.port}/${localPostgres.dbName}"; command = pkgs.pgweb; depends_on."pg1-bootstrap".condition = "process_completed_successfully"; }; @@ -390,13 +403,13 @@ rustfs = { command = rustfsStart; environment = { - RUSTFS_ACCESS_KEY = s3AccessKey; - RUSTFS_SECRET_KEY = s3SecretKey; - RUSTFS_ADDRESS = rustfsApiAddress; - RUSTFS_CONSOLE_ENABLE = "true"; - RUSTFS_CONSOLE_ADDRESS = rustfsConsoleAddress; - RUSTFS_REGION = s3Region; - RUSTFS_HEALTH_ENDPOINT_ENABLE = "true"; + RUSTFS_ACCESS_KEY = localS3.accessKey; + RUSTFS_SECRET_KEY = localS3.secretKey; + RUSTFS_ADDRESS = localRustfs.apiAddress; + RUSTFS_CONSOLE_ENABLE = lib.boolToString localRustfs.consoleEnabled; + RUSTFS_CONSOLE_ADDRESS = localRustfs.consoleAddress; + RUSTFS_REGION = localS3.region; + RUSTFS_HEALTH_ENDPOINT_ENABLE = lib.boolToString localRustfs.healthEndpointEnabled; }; shutdown = { signal = 15; From a94031fdd84197a09757dc59bf9b75f19a4fd91f Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Wed, 27 May 2026 15:59:18 +0100 Subject: [PATCH 19/28] Regenerate frontend UnoCSS output --- frontend/style/uno.css | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/style/uno.css b/frontend/style/uno.css index 914da53..bf13064 100644 --- a/frontend/style/uno.css +++ b/frontend/style/uno.css @@ -1,5 +1,5 @@ /* layer: properties */ -@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*, ::before, ::after, ::backdrop{--un-translate-x:initial;--un-translate-y:initial;--un-translate-z:initial;--un-bg-opacity:100%;--un-text-opacity:100%;--un-from-opacity:100%;--un-to-opacity:100%;--un-border-opacity:100%;}} +@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*, ::before, ::after, ::backdrop{--un-translate-x:initial;--un-translate-y:initial;--un-translate-z:initial;--un-bg-opacity:100%;--un-border-opacity:100%;--un-text-opacity:100%;--un-from-opacity:100%;--un-to-opacity:100%;}} @property --un-text-opacity{syntax:"";inherits:false;initial-value:100%;} @property --un-border-opacity{syntax:"";inherits:false;initial-value:100%;} @property --un-bg-opacity{syntax:"";inherits:false;initial-value:100%;} @@ -52,14 +52,11 @@ --spacing: 0.25rem; --default-transition-timingFunction: cubic-bezier(0.4, 0, 0.2, 1); --default-transition-duration: 150ms; ---radius-none: 0; ---colors-white: #fff; --fontWeight-bold: 700; +--container-md: 28rem; --radius-DEFAULT: 0.25rem; +--colors-white: #fff; --colors-gray-200: oklch(92.8% 0.006 264.531); ---colors-black: #000; ---radius-sm: 0.25rem; ---container-md: 28rem; --colors-gray-700: oklch(37.3% 0.034 259.733); --colors-green-500: oklch(72.3% 0.219 149.579); --colors-red-500: oklch(63.7% 0.237 25.331); @@ -75,6 +72,9 @@ --colors-blue-700: oklch(48.8% 0.243 264.376); --text-4xl-fontSize: 2.25rem; --text-4xl-lineHeight: 2.5rem; +--radius-none: 0; +--colors-black: #000; +--radius-sm: 0.25rem; --colors-red-100: oklch(93.6% 0.032 17.717); --colors-red-700: oklch(50.5% 0.213 27.518); --font-sans: ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"; From 55e3035442315724099226f69888671291a40da0 Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Wed, 27 May 2026 16:42:06 +0100 Subject: [PATCH 20/28] Fix local app startup and upload flow --- devenv/flake.nix | 3 +++ frontend/src/components/file_upload.rs | 12 ++++++++---- justfile | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/devenv/flake.nix b/devenv/flake.nix index b44681c..2744796 100644 --- a/devenv/flake.nix +++ b/devenv/flake.nix @@ -475,6 +475,9 @@ # when the parent shell exports stale toolchain paths. CARGO = "${config.packages.rustToolchain}/bin/cargo"; RUSTC = "${config.packages.rustToolchain}/bin/rustc"; + LD_LIBRARY_PATH = lib.makeLibraryPath [ + pkgs.openssl + ]; # Required by rust-analyzer RUST_SRC_PATH = "${config.packages.rustToolchain}/lib/rustlib/src/rust/library"; }; diff --git a/frontend/src/components/file_upload.rs b/frontend/src/components/file_upload.rs index affa477..80bf690 100644 --- a/frontend/src/components/file_upload.rs +++ b/frontend/src/components/file_upload.rs @@ -38,11 +38,11 @@ use { HtmlFormElement, MouseEvent, Request, + RequestCredentials, RequestInit, SubmitEvent, }, }, - leptos_router::components::Form, shared::ALLOWED_MIME_TYPES, thaw::*, wasm_bindgen_futures::JsFuture, @@ -114,6 +114,7 @@ pub fn FileUpload( spawn_local(async move { let options = RequestInit::new(); options.set_method("POST"); + options.set_credentials(RequestCredentials::Include); options.set_body(&form_data); let url = format!("{api_url}/api/locations/"); @@ -163,7 +164,7 @@ pub fn FileUpload( }; view! { -
+
- +
-
+
} .into_any() diff --git a/justfile b/justfile index 4153426..326b524 100644 --- a/justfile +++ b/justfile @@ -29,7 +29,7 @@ clean-service-state: # Start backend server. backend: - {{ direnv_prefix }} bash -c 'cd backend; {{ log_prefix }} bacon run -- {{ release_flag }}' + {{ direnv_prefix }} bash -c 'cd backend; {{ log_prefix }} bacon run -- --bin backend {{ release_flag }}' # Create local frontend runtime config when missing. frontend-config: From 19a515df0d16763ea10399073a041da8210d0df8 Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Fri, 29 May 2026 16:51:11 +0100 Subject: [PATCH 21/28] Add Playwright test infrastructure --- .gitignore | 3 ++ devenv/flake.nix | 4 +++ frontend/e2e/fixtures/memory-map-e2e.svg | 5 ++++ frontend/e2e/smoke.spec.js | 26 ++++++++++++++++ frontend/package.json | 1 + frontend/playwright.config.js | 31 +++++++++++++++++++ frontend/pnpm-lock.yaml | 38 ++++++++++++++++++++++++ frontend/style/uno.css | 12 ++++---- 8 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 frontend/e2e/fixtures/memory-map-e2e.svg create mode 100644 frontend/e2e/smoke.spec.js create mode 100644 frontend/playwright.config.js diff --git a/.gitignore b/.gitignore index 149cb34..8f3d70a 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,9 @@ frontend/public/config.json /result /result-* process-compose.log +frontend/playwright-report/ +frontend/test-results/ +frontend/blob-report/ .claude/worktrees/ .codex/worktrees/ .pre-commit-config.yaml diff --git a/devenv/flake.nix b/devenv/flake.nix index 2744796..2da73c6 100644 --- a/devenv/flake.nix +++ b/devenv/flake.nix @@ -452,6 +452,8 @@ pkgs.just pkgs.pnpm pkgs.nodejs-slim + pkgs.playwright-driver + pkgs.playwright-driver.browsers pkgs.graphql-client # For Leptos pkgs.leptosfmt @@ -478,6 +480,8 @@ LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.openssl ]; + PLAYWRIGHT_BROWSERS_PATH = "${pkgs.playwright-driver.browsers}"; + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD = "1"; # Required by rust-analyzer RUST_SRC_PATH = "${config.packages.rustToolchain}/lib/rustlib/src/rust/library"; }; diff --git a/frontend/e2e/fixtures/memory-map-e2e.svg b/frontend/e2e/fixtures/memory-map-e2e.svg new file mode 100644 index 0000000..4e4cfed --- /dev/null +++ b/frontend/e2e/fixtures/memory-map-e2e.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/frontend/e2e/smoke.spec.js b/frontend/e2e/smoke.spec.js new file mode 100644 index 0000000..861110b --- /dev/null +++ b/frontend/e2e/smoke.spec.js @@ -0,0 +1,26 @@ +const { expect, test } = require("@playwright/test"); + +test("home page loads the map shell", async ({ page }) => { + const consoleErrors = []; + const failedRequests = []; + + page.on("console", (message) => { + if (message.type() === "error") { + consoleErrors.push(message.text()); + } + }); + + page.on("requestfailed", (request) => { + const failure = request.failure(); + failedRequests.push(`${request.method()} ${request.url()} ${failure?.errorText ?? "failed"}`); + }); + + await page.goto("/"); + + await expect(page).toHaveTitle(/Memory Map/); + await expect(page.locator(".leaflet-container")).toBeVisible(); + await expect(page.getByRole("button", { name: "Open menu" })).toBeVisible(); + + expect(consoleErrors).toEqual([]); + expect(failedRequests).toEqual([]); +}); diff --git a/frontend/package.json b/frontend/package.json index 2591d82..b83955d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,5 +1,6 @@ { "devDependencies": { + "@playwright/test": "1.59.1", "@unocss/cli": "66.7.0", "@unocss/preset-wind4": "^66.7.0", "unocss": "^66.7.0" diff --git a/frontend/playwright.config.js b/frontend/playwright.config.js new file mode 100644 index 0000000..a3c5f5c --- /dev/null +++ b/frontend/playwright.config.js @@ -0,0 +1,31 @@ +const { defineConfig, devices } = require("@playwright/test"); + +const frontendUrl = process.env.E2E_FRONTEND_URL ?? "http://127.0.0.1:3000"; + +module.exports = defineConfig({ + testDir: "./e2e", + timeout: 60_000, + expect: { + timeout: 10_000, + }, + fullyParallel: false, + workers: 1, + reporter: [ + ["list"], + ["html", { open: "never" }], + ], + use: { + baseURL: frontendUrl, + trace: "retain-on-failure", + screenshot: "only-on-failure", + video: "retain-on-failure", + actionTimeout: 10_000, + navigationTimeout: 30_000, + }, + projects: [ + { + name: "chromium", + use: { ...devices["Desktop Chrome"] }, + }, + ], +}); diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index ca1c43a..adcd4d0 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -12,6 +12,9 @@ importers: specifier: ^1.9.4 version: 1.9.4 devDependencies: + '@playwright/test': + specifier: 1.59.1 + version: 1.59.1 '@unocss/cli': specifier: 66.7.0 version: 66.7.0 @@ -350,6 +353,11 @@ packages: '@oxc-project/types@0.131.0': resolution: {integrity: sha512-PgnWDfV0h+b16XNKbXU7Daib/BFSt/J2mEzfYIBu6JB/wNdlU+kVYXCkGA1A9fWkTbOgbjh4e6NhPeQOYvFhEA==} + '@playwright/test@1.59.1': + resolution: {integrity: sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==} + engines: {node: '>=18'} + hasBin: true + '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} @@ -622,6 +630,11 @@ packages: picomatch: optional: true + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -696,6 +709,16 @@ packages: pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + playwright-core@1.59.1: + resolution: {integrity: sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.59.1: + resolution: {integrity: sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==} + engines: {node: '>=18'} + hasBin: true + postcss@8.5.15: resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} engines: {node: ^10 || ^12 || >=14} @@ -1017,6 +1040,10 @@ snapshots: '@oxc-project/types@0.131.0': {} + '@playwright/test@1.59.1': + dependencies: + playwright: 1.59.1 + '@polka/url@1.0.0-next.29': {} '@quansync/fs@1.0.0': @@ -1298,6 +1325,9 @@ snapshots: optionalDependencies: picomatch: 4.0.4 + fsevents@2.3.2: + optional: true + fsevents@2.3.3: optional: true @@ -1392,6 +1422,14 @@ snapshots: mlly: 1.8.2 pathe: 2.0.3 + playwright-core@1.59.1: {} + + playwright@1.59.1: + dependencies: + playwright-core: 1.59.1 + optionalDependencies: + fsevents: 2.3.2 + postcss@8.5.15: dependencies: nanoid: 3.3.12 diff --git a/frontend/style/uno.css b/frontend/style/uno.css index bf13064..914da53 100644 --- a/frontend/style/uno.css +++ b/frontend/style/uno.css @@ -1,5 +1,5 @@ /* layer: properties */ -@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*, ::before, ::after, ::backdrop{--un-translate-x:initial;--un-translate-y:initial;--un-translate-z:initial;--un-bg-opacity:100%;--un-border-opacity:100%;--un-text-opacity:100%;--un-from-opacity:100%;--un-to-opacity:100%;}} +@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*, ::before, ::after, ::backdrop{--un-translate-x:initial;--un-translate-y:initial;--un-translate-z:initial;--un-bg-opacity:100%;--un-text-opacity:100%;--un-from-opacity:100%;--un-to-opacity:100%;--un-border-opacity:100%;}} @property --un-text-opacity{syntax:"";inherits:false;initial-value:100%;} @property --un-border-opacity{syntax:"";inherits:false;initial-value:100%;} @property --un-bg-opacity{syntax:"";inherits:false;initial-value:100%;} @@ -52,11 +52,14 @@ --spacing: 0.25rem; --default-transition-timingFunction: cubic-bezier(0.4, 0, 0.2, 1); --default-transition-duration: 150ms; +--radius-none: 0; +--colors-white: #fff; --fontWeight-bold: 700; ---container-md: 28rem; --radius-DEFAULT: 0.25rem; ---colors-white: #fff; --colors-gray-200: oklch(92.8% 0.006 264.531); +--colors-black: #000; +--radius-sm: 0.25rem; +--container-md: 28rem; --colors-gray-700: oklch(37.3% 0.034 259.733); --colors-green-500: oklch(72.3% 0.219 149.579); --colors-red-500: oklch(63.7% 0.237 25.331); @@ -72,9 +75,6 @@ --colors-blue-700: oklch(48.8% 0.243 264.376); --text-4xl-fontSize: 2.25rem; --text-4xl-lineHeight: 2.5rem; ---radius-none: 0; ---colors-black: #000; ---radius-sm: 0.25rem; --colors-red-100: oklch(93.6% 0.032 17.717); --colors-red-700: oklch(50.5% 0.213 27.518); --font-sans: ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"; From 17497c9a6a2c3eab40c3a97ae1f98d066e0bc2d7 Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Fri, 29 May 2026 17:20:25 +0100 Subject: [PATCH 22/28] Stub map tiles in Playwright tests --- frontend/e2e/fixtures.js | 44 ++++++++++++++++++++++++++++++++++++++ frontend/e2e/smoke.spec.js | 19 +--------------- 2 files changed, 45 insertions(+), 18 deletions(-) create mode 100644 frontend/e2e/fixtures.js diff --git a/frontend/e2e/fixtures.js b/frontend/e2e/fixtures.js new file mode 100644 index 0000000..8b219d6 --- /dev/null +++ b/frontend/e2e/fixtures.js @@ -0,0 +1,44 @@ +const { expect, test: base } = require("@playwright/test"); + +const transparentPng = Buffer.from( + "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAFgwJ/lz7eSgAAAABJRU5ErkJggg==", + "base64", +); + +const test = base.extend({ + page: async ({ page }, use) => { + const consoleErrors = []; + const failedRequests = []; + + await page.route("https://tile.openstreetmap.org/**", async (route) => { + await route.fulfill({ + status: 200, + contentType: "image/png", + body: transparentPng, + }); + }); + + page.on("console", (message) => { + if (message.type() === "error") { + consoleErrors.push(message.text()); + } + }); + + page.on("requestfailed", (request) => { + const failure = request.failure(); + failedRequests.push( + `${request.method()} ${request.url()} ${failure?.errorText ?? "failed"}`, + ); + }); + + await use(page); + + expect(consoleErrors).toEqual([]); + expect(failedRequests).toEqual([]); + }, +}); + +module.exports = { + expect, + test, +}; diff --git a/frontend/e2e/smoke.spec.js b/frontend/e2e/smoke.spec.js index 861110b..796d7a1 100644 --- a/frontend/e2e/smoke.spec.js +++ b/frontend/e2e/smoke.spec.js @@ -1,26 +1,9 @@ -const { expect, test } = require("@playwright/test"); +const { expect, test } = require("./fixtures"); test("home page loads the map shell", async ({ page }) => { - const consoleErrors = []; - const failedRequests = []; - - page.on("console", (message) => { - if (message.type() === "error") { - consoleErrors.push(message.text()); - } - }); - - page.on("requestfailed", (request) => { - const failure = request.failure(); - failedRequests.push(`${request.method()} ${request.url()} ${failure?.errorText ?? "failed"}`); - }); - await page.goto("/"); await expect(page).toHaveTitle(/Memory Map/); await expect(page.locator(".leaflet-container")).toBeVisible(); await expect(page.getByRole("button", { name: "Open menu" })).toBeVisible(); - - expect(consoleErrors).toEqual([]); - expect(failedRequests).toEqual([]); }); From abc29c109cb3cb8b122a9d2046bf18afc23ae8c2 Mon Sep 17 00:00:00 2001 From: nothingnesses <18732253+nothingnesses@users.noreply.github.com> Date: Fri, 29 May 2026 18:11:19 +0100 Subject: [PATCH 23/28] Add headless E2E runner --- .gitignore | 1 + devenv/flake.nix | 10 +++- frontend/src/components/header.rs | 2 +- justfile | 94 ++++++++++++++++++++++++++++++- scripts/e2e-env.sh | 35 ++++++++++++ 5 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 scripts/e2e-env.sh diff --git a/.gitignore b/.gitignore index 8f3d70a..7787b7c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ frontend/public/config.json /result /result-* process-compose.log +e2e-logs/ frontend/playwright-report/ frontend/test-results/ frontend/blob-report/ diff --git a/devenv/flake.nix b/devenv/flake.nix index 2da73c6..695ce3e 100644 --- a/devenv/flake.nix +++ b/devenv/flake.nix @@ -93,7 +93,14 @@ in !(lib.hasPrefix "target/" rel) && !(lib.hasPrefix "data/" rel) - && !(lib.hasPrefix "frontend/node_modules/" rel); + && !(lib.hasPrefix "frontend/node_modules/" rel) + && !(lib.hasPrefix "frontend/dist/" rel) + && rel != "process-compose.log" + && rel != "frontend/public/config.json" + && !(lib.hasPrefix "e2e-logs/" rel) + && !(lib.hasPrefix "frontend/playwright-report/" rel) + && !(lib.hasPrefix "frontend/test-results/" rel) + && !(lib.hasPrefix "frontend/blob-report/" rel); }; rustfsPkgs = pkgs.extend (import inputs.rust-overlay); rustfsToolchain = rustfsPkgs.rust-bin.stable.latest.default.override { @@ -450,6 +457,7 @@ # Stable didn't yet have cargo-generate, so we're using unstable here pkgs.unstable.cargo-generate pkgs.just + pkgs.curl pkgs.pnpm pkgs.nodejs-slim pkgs.playwright-driver diff --git a/frontend/src/components/header.rs b/frontend/src/components/header.rs index ebf5f92..8414435 100644 --- a/frontend/src/components/header.rs +++ b/frontend/src/components/header.rs @@ -186,7 +186,7 @@ pub fn Header(#[prop(into)] menu_open: RwSignal) -> impl IntoView {