├── sample_apps └── rso_sample_apps │ ├── nodejs │ ├── .nvmrc │ ├── README.md │ ├── package.json │ ├── index.js │ └── package-lock.json │ ├── go │ ├── go.mod │ ├── go.sum │ ├── README.md │ └── main.go │ ├── rust │ ├── mock │ │ ├── Cargo.toml │ │ ├── .gitignore │ │ ├── src │ │ │ └── lib.rs │ │ └── Cargo.lock │ ├── rust-toolchain.toml │ ├── .gitignore │ ├── grcov.yml │ ├── templates │ │ ├── oauth.html │ │ ├── default.html │ │ └── data.html │ ├── Cargo.toml │ ├── Makefile │ ├── config │ │ └── example-config.yml │ ├── src │ │ ├── handlers │ │ │ ├── mod.rs │ │ │ ├── default.rs │ │ │ ├── oauth.rs │ │ │ └── data.rs │ │ ├── main.rs │ │ ├── service.rs │ │ └── config.rs │ └── README.md │ ├── python │ ├── README.md │ ├── pyproject.toml │ ├── main.py │ └── poetry.lock │ └── README.md ├── .gitignore ├── .github ├── pull_request_template.md ├── ISSUE_TEMPLATE │ ├── account_issue.md │ └── bug_report.md └── workflows │ └── rso_sample_apps.yml └── README.md /sample_apps/rso_sample_apps/nodejs/.nvmrc: -------------------------------------------------------------------------------- 1 | 18.9.0 2 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/go/go.mod: -------------------------------------------------------------------------------- 1 | module sample 2 | 3 | go 1.19 4 | 5 | require github.com/joho/godotenv v1.4.0 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # MacOS 2 | .DS_Store 3 | .idea 4 | # NodeJS 5 | node_modules 6 | 7 | # Python 8 | __pycache__/ 9 | *.py[cod] 10 | *$py.class 11 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/mock/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mock" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | httpmock = "0.7.0" 8 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/go/go.sum: -------------------------------------------------------------------------------- 1 | github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= 2 | github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= 3 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/nodejs/README.md: -------------------------------------------------------------------------------- 1 | # NodeJS Sample app 2 | 3 | ## Requirements 4 | 1. You need node installed in your machine 5 | 1. `npm install` 6 | 7 | ## Run 8 | Just execute: 9 | ``` 10 | node index.js 11 | ``` 12 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/python/README.md: -------------------------------------------------------------------------------- 1 | # Go Sample app 2 | 3 | ## Requirements 4 | 1. You need `python` 5 | 1. You need `poetry` 6 | 1. Run `poetry install` 7 | 8 | ## Run 9 | Just execute: 10 | ``` 11 | poetry run main.py 12 | ``` 13 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | # The default profile includes rustc, rust-std, cargo, rust-docs, rustfmt and clippy. 3 | # https://rust-lang.github.io/rustup/concepts/profiles.html 4 | profile = "default" 5 | channel = "1.78.0" -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled files 2 | /target 3 | 4 | # Configuration file 5 | /config.yml 6 | 7 | # TLS files 8 | *.cert 9 | *.key 10 | 11 | # Ignore IDE related files 12 | *.idea 13 | *.vscode 14 | 15 | # Ignore .DS_Store on macOS 16 | .DS_Store 17 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/mock/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled files 2 | /target 3 | 4 | # Configuration file 5 | /config.yml 6 | 7 | # TLS files 8 | *.cert 9 | *.key 10 | 11 | # Ignore IDE related files 12 | *.idea 13 | *.vscode 14 | 15 | # Ignore .DS_Store on macOS 16 | .DS_Store 17 | docs -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/go/README.md: -------------------------------------------------------------------------------- 1 | # Go Sample app 2 | 3 | ## Requirements 4 | 1. Make sure you have your `.env` in the root of the project: `sample_apps/rso_sample_apps/.env` 5 | 1. You need golang installed in your machine 6 | 1. `go mod tidy` 7 | 8 | ## Run 9 | Just execute: 10 | ``` 11 | go run main.go 12 | ``` 13 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/grcov.yml: -------------------------------------------------------------------------------- 1 | branch: false 2 | ignore-not-existing: true 3 | llvm: true 4 | filter: covered 5 | output-type: lcov 6 | ignore: 7 | - "*.cargo/*" 8 | excl-start: "grcov-excl-start" 9 | excl-stop: "grcov-excl-stop" 10 | excl-line: "grcov-excl-line|#\\[derive\\(|ensure!\\(|assert!\\(|/!|///" 11 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/templates/oauth.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Logging in... 7 | 8 | 9 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/python/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "python-rso-client" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["Teemo"] 6 | 7 | [tool.poetry.dependencies] 8 | python = "^3.10" 9 | fastapi = "^0.85.0" 10 | uvicorn = "^0.18.3" 11 | requests = {extras = ["security"], version = "^2.28.1"} 12 | python-dotenv = "^0.21.0" 13 | 14 | [tool.poetry.dev-dependencies] 15 | ipdb = "^0.13.9" 16 | 17 | [build-system] 18 | requires = ["poetry-core>=1.0.0"] 19 | build-backend = "poetry.core.masonry.api" 20 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/nodejs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rso-example-app", 3 | "version": "0.0.1", 4 | "description": "rso example app", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "author": "Riot Tuxedo", 11 | "license": "ISC", 12 | "dependencies": { 13 | "dotenv": "^16.0.2", 14 | "express": "^4.17.1", 15 | "node-fetch": "^3.2.10" 16 | }, 17 | "engines": { 18 | "node": ">=18 <19", 19 | "npm": ">=8 <9" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "riot_rso_sample_app" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dev-dependencies] 7 | mock = { path = "mock" } 8 | 9 | [dependencies] 10 | askama = { version = "0.12.1"} 11 | axum = { version = "0.7.5" } 12 | axum-server = { version = "0.6.0", features = ["tls-rustls"] } 13 | base64 = "0.22.1" 14 | clap = { version = "4.5.4", features = ["derive"] } 15 | config = "0.14.0" 16 | env_logger = "0.11.3" 17 | http-body-util = "0.1.1" 18 | log = "0.4.21" 19 | serde = { version = "1.0.203", features = ["derive"] } 20 | serde_derive = "1.0.203" 21 | serde_json = "1.0.117" 22 | tokio = { version = "1.37.0", features = ["full"] } 23 | tower = "0.4.13" 24 | ureq = { version = "2.9.7", features = ["json"] } 25 | url = "2.5.0" 26 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: build test clean all run docs fmt 2 | 3 | all: clean fmt build test docs 4 | 5 | build: 6 | @echo "👷🏽‍♀️building rust project..." 7 | cargo build 8 | 9 | test: 10 | @echo "👷🏽‍♀️running tests..." 11 | RUST_LOG=debug cargo test 12 | 13 | clean: 14 | @echo "👷🏽‍♀️cleaning up..." 15 | cargo clean 16 | 17 | run: 18 | @echo "👷🏽‍♀️running rust project..." 19 | RUST_LOG=info cargo run 20 | 21 | fmt: 22 | @echo "👷🏽‍♀️formatting the rust project..." 23 | cargo fmt --all 24 | 25 | docs: 26 | @echo "👷🏽‍♀️building project documentation..." 27 | cargo doc --no-deps 28 | open target/doc/riot_rso_sample_app/index.html 29 | 30 | debug: 31 | @echo "👷🏽‍♀️debugging rust project..." 32 | RUST_BACKTRACE=1 RUST_LOG=debug cargo run 33 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/config/example-config.yml: -------------------------------------------------------------------------------- 1 | server: # server configuration , 2 | addr: 0.0.0.0:443 # SERVER_ADDRESS - address to bind to 3 | tls: 4 | cert: # SERVER_TLS_CERT - tls certificate 5 | key: # SERVER_TLS_KEY - tls private key 6 | 7 | rso: 8 | base_url: "https://auth.riotgames.com" # RSO_BASE_URL - Riot Games oauth auth provider URL 9 | callback_host: "https://local.example.com" # RSO_CALLBACK_HOST - callback hostname 10 | client_id: "" # RSO_CLIENT_ID - oauth2 client id 11 | client_secret: "" # RSO_CLIENT_SECRET - oauth2 client secret 12 | 13 | api: 14 | token: "" # Riot Games API token - RGAPI_TOKEN 15 | urls: 16 | account_data: "https://americas.api.riotgames.com/riot/account/v1/accounts/me" # RGAPI_URL_ACCOUNT_DATA - Riot Games API account data URL 17 | champion_data: "https://na1.api.riotgames.com/lol/platform/v3/champion-rotations" # RGAPI_URL_CHAMPION_DATA - Riot Games API champion data URL 18 | 19 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | We accept pull requests for Bug Fixes and Features. 2 | 3 | 4 | 5 | ## Description 6 | 7 | 8 | ## Related Issue 9 | 10 | 11 | 12 | 13 | 14 | ## Motivation and Context 15 | 16 | 17 | 18 | ## How Has This Been Tested? 19 | 20 | 21 | 22 | 23 | ## Screenshots (if appropriate): 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/account_issue.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Account Issue 3 | about: Report an issue related to your Developer Portal account. 4 | title: "[Account] " 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Account Information** 11 | What's your summoner name (e.g., Tuxedo) or riot id (e.g., Tuxedo#AYAYA)? 12 | Have you played any of Riot's games or did you just create an account for the Developer Portal? 13 | 14 | **Issue Description** 15 | A clear and concise description of what the issue is. 16 | 17 | **What I've Tried** 18 | What steps have you tried to resolve the issue. 19 | 20 | - [x] Log out of the Developer Portal 21 | - [ ] Attempt to log in via "Incognito Mode" 22 | - [ ] Clear your browser cookies 23 | - [ ] Attempt to login via a secondary device (mobile or different computer) 24 | 25 | **Repro Steps** 26 | 27 | 1. Step 1 28 | 1. Step 2 29 | 30 | **Issue Context** 31 | Please add any additional context that is useful. 32 | -------------------------------------------------------------------------------- /.github/workflows/rso_sample_apps.yml: -------------------------------------------------------------------------------- 1 | on: [push, pull_request] 2 | 3 | name: rso_sample_apps_rust 4 | 5 | jobs: 6 | check: 7 | name: check 8 | runs-on: ubuntu-latest 9 | container: rust:latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | - uses: dtolnay/rust-toolchain@stable 13 | - run: cargo check 14 | working-directory: ./sample_apps/rso_sample_apps/rust 15 | 16 | test: 17 | name: test 18 | runs-on: ubuntu-latest 19 | container: rust:latest 20 | steps: 21 | - uses: actions/checkout@v4 22 | - uses: dtolnay/rust-toolchain@stable 23 | - run: cargo test 24 | working-directory: ./sample_apps/rso_sample_apps/rust 25 | 26 | fmt: 27 | name: fmt 28 | runs-on: ubuntu-latest 29 | container: rust:latest 30 | steps: 31 | - uses: actions/checkout@v4 32 | - uses: dtolnay/rust-toolchain@stable 33 | with: 34 | components: rustfmt 35 | - run: cargo fmt --all -- --check 36 | working-directory: ./sample_apps/rso_sample_apps/rust 37 | 38 | clippy: 39 | name: clippy 40 | runs-on: ubuntu-latest 41 | container: rust:latest 42 | steps: 43 | - uses: actions/checkout@v4 44 | - uses: dtolnay/rust-toolchain@stable 45 | with: 46 | components: clippy 47 | - run: cargo clippy -- -D warnings 48 | working-directory: ./sample_apps/rso_sample_apps/rust 49 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/src/handlers/mod.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | use axum::http::StatusCode; 3 | use axum::response::{Html, IntoResponse}; 4 | 5 | pub mod data; 6 | pub mod default; 7 | pub mod oauth; 8 | 9 | /// A wrapper struct for Askama templates to facilitate their conversion into Axum responses. 10 | /// 11 | /// This struct takes a generic type `T` which must implement the `Template` trait from the Askama crate. 12 | /// It provides a mechanism to convert a given template into an HTTP response that can be returned from an Axum handler. 13 | struct HtmlTemplate(T); 14 | 15 | impl IntoResponse for HtmlTemplate 16 | where 17 | T: Template, 18 | { 19 | /// Converts the contained Askama template into an Axum response. 20 | /// 21 | /// This method attempts to render the template into HTML. If successful, it returns an HTTP response 22 | /// with the rendered HTML. If the rendering process fails, it returns an HTTP 500 Internal Server Error 23 | /// response with the error message. 24 | /// 25 | /// # Returns 26 | /// An `axum::response::Response` that can be directly returned from an Axum route handler. 27 | fn into_response(self) -> axum::response::Response { 28 | match self.0.render() { 29 | Ok(html) => Html(html).into_response(), 30 | Err(err) => (StatusCode::INTERNAL_SERVER_ERROR, format!("{err}")).into_response(), 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/templates/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Login 7 | 8 | 32 | 33 | 34 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/src/handlers/default.rs: -------------------------------------------------------------------------------- 1 | use super::HtmlTemplate; 2 | use crate::config::Configuration; 3 | use askama::Template; 4 | use axum::extract::State; 5 | use axum::response::IntoResponse; 6 | 7 | /// Represents the server's response to a request with a sign-in URL. 8 | /// 9 | /// This struct is used to generate the HTML response for the client, directing them to the sign-in page. 10 | /// It leverages the Askama template engine to render the `default.html` template with the provided `sign_in_url`. 11 | #[derive(Template, Clone)] 12 | #[template(path = "default.html")] 13 | pub struct Response { 14 | /// The URL to which the user should be redirected for signing in. 15 | sign_in_url: String, 16 | } 17 | 18 | /// Handles requests by generating a response with a sign-in URL. 19 | /// 20 | /// This asynchronous function is an Axum handler that constructs a `Response` struct with the sign-in URL 21 | /// from the application configuration. It then wraps this `Response` in an `HtmlTemplate` to be rendered into HTML. 22 | /// The resulting HTML is sent back to the client, directing them to the sign-in page. 23 | /// 24 | /// # Arguments 25 | /// * `cfg` - The application configuration, containing the sign-in URL. 26 | /// 27 | /// # Returns 28 | /// An implementation of `IntoResponse`, which Axum can convert into an HTTP response to be sent to the client. 29 | pub async fn handle(State(cfg): State) -> impl IntoResponse { 30 | let res = Response { 31 | sign_in_url: cfg.sign_in_url(), 32 | }; 33 | 34 | HtmlTemplate(res) 35 | } 36 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/src/main.rs: -------------------------------------------------------------------------------- 1 | use clap::Parser; 2 | use log::{debug, info}; 3 | mod config; 4 | mod handlers; 5 | mod service; 6 | 7 | /// Struct containing the command line arguments. 8 | /// 9 | /// This struct is defined using the `clap` crate to parse command line arguments. It specifically looks for 10 | /// a configuration file path, which can be provided using `-c` or `--config` flags. If not provided, it defaults 11 | /// to `config.yml`. 12 | #[derive(Parser, Debug)] 13 | pub struct Args { 14 | /// Path to the configuration file. 15 | /// 16 | /// # Short and long options 17 | /// 18 | /// - `-c`, `--config` 19 | /// 20 | /// # Default value 21 | /// 22 | /// `config.yml` 23 | #[arg(short, long, default_value = "config.yml")] 24 | pub config: String, 25 | } 26 | 27 | /// The main entry point for the program. 28 | /// 29 | /// Initializes the logger, parses command line arguments using the `Args` struct, and attempts to parse 30 | /// the configuration file specified by the command line arguments. If successful, it starts the service 31 | /// with the parsed configuration. If the configuration file cannot be parsed, the application will panic. 32 | /// 33 | /// Utilizes the `tokio` runtime for asynchronous operations, allowing the service to perform non-blocking 34 | /// I/O operations. 35 | #[tokio::main] 36 | async fn main() { 37 | env_logger::init(); 38 | // Parse command line arguments. 39 | info!("😀 application started"); 40 | let args = Args::parse(); 41 | debug!("😀 parsed command line arguments: {args:?}"); 42 | match config::parse(args.config) { 43 | // If the configuration file is successfully parsed, start the service. 44 | Ok(cfg) => { 45 | service::listen(&cfg).await; 46 | } 47 | // If the configuration file is not successfully parsed, panic. 48 | Err(err) => { 49 | panic!("please check your configuration arguments, file and/or environment variables:\r\n{err}") 50 | } 51 | } 52 | info!("🥹riot rso example application completed successfully, goodbye."); 53 | } 54 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Create a report to help us improve. 4 | title: "[BUG] " 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Bug Description** 11 | A clear and concise description of what the bug is. 12 | 13 | **Problem Description** 14 | A clear and concise description of what the problem is. 15 | 16 | **Expected Result** 17 | What were you expecting to happen after you performed the above steps? Include screenshots, logs, or a description. 18 | 19 | **Actual Result** 20 | What actually happened after you performed the above steps? Include screenshots, logs, or a description. 21 | 22 | **Developer Impact** 23 | Describe how this affects you as a developer. Please include the frequency and severity of the issue. 24 | 25 | * Frequency: Every API call. Once every ~100 API calls. 26 | * Severity: When it happens, my whole website crashes. 27 | * Cost: Requires me to run X more servers to compensate for the issue costing me on average $200 of additional spend a month. 28 | * Efficiency: Requires me to make 10x more API calls than necessary to compensate for the issue. 29 | * User emails: I get frequent emails from users asking me about this issue. 30 | * Etc 31 | 32 | **Player Impact** 33 | Describe how this affects League of Legends players. Please include the frequency and severity of the issue. 34 | 35 | * Frequency: Every time the user visits the site, they experience this issue. Once every ~100 visits this issue occurs. 36 | * Severity: When this bug happens, a user is unable to use my site. I have 200 visits to my site each day, so it affects 50% of site visits. 37 | * Quantity: There are ~1k players that experience this issue. 38 | * Region: This affects players in NA and EUW. 39 | * Etc 40 | 41 | **Preconditions** 42 | What conditions must be met in order for this bug to occur? 43 | 44 | * First condition 45 | * Second condition 46 | 47 | **Repro Steps** 48 | Step by step, what do you need to do to cause the bug? Note that GitHub will automagically number each step if you prefix the line with "1. " 49 | 50 | 1. Step 1 51 | 1. Step 2 52 | 53 | **Issue Comments** 54 | Might want to leave this as instructions for any replies to your issue: 55 | 56 | If you're also experiencing this issue please add any additional context that is useful, the developer impact to yourself, and the player impact to your users. As an example, if spectator-v4 isn't working it might affect a scouting site, but it could also affect a mobile app or site to share replays. Give the context on how this issue affects your project. 57 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/README.md: -------------------------------------------------------------------------------- 1 | # samples 2 | The goal of this repository is to show you how quickly you can start creating your own backend service that implements your Riot approved app. 3 | 4 | This repo contains samples of the most popular programming languages: 5 | 6 | * python 🐍 7 | * nodejs 🐢 8 | * golang 🦫 9 | 10 | # ⚠️ Warning ⚠️ 11 | These samples are not suited for production environments, this samples are intended to show how RSO can be used to consume Riot API endpoints. 12 | 13 | # Requirements to run the samples ✅ 14 | * Get your secrets: 15 | * RSO_BASE_URL=https://auth.riotgames.com 16 | * RSO_CLIENT_ID= 17 | * RSO_CLIENT_SECRET= 18 | * DEPLOYMENT_API_KEY= 19 | * APP_BASE_URL=http:// 20 | * APP_CALLBACK_PATH= 21 | * RESPONSE_TYPE=code 22 | * SCOPE=openid 23 | * Make sure you have your `.env` in the root of the project: `sample_apps/rso_sample_apps/.env` env file is shared between sample apps (go, python, nodejs) 24 | * Add `127.0.0.1 local.exampleapp.com` to your hosts file. 25 | * MacOS/Linux 26 | * Append `127.0.0.1 local.exampleapp.com` to the file `/etc/hosts` 27 | * Windows 28 | * Append `127.0.0.1 local.exampleapp.com` to the file `C:\Windows\System32\Drivers\etc\hosts` 29 | * Follow the README.md inside every sample app, every sample app. 30 | * Once your app is up and running click the following link to visualize it: 31 | * http://local.exampleapp.com:3000 32 | 33 | # Environment variables ☀️ 34 | Sample apps use dotenv to load the variables specified in `.env` in your environment. 35 | 36 | If you dont want to use dotenv you can set your environment vars manually. 37 | 38 | Sample `.env` file 39 | ``` 40 | RSO_BASE_URL=https://auth.riotgames.com 41 | RSO_CLIENT_ID=riot-example-app 42 | RSO_CLIENT_SECRET=******************************* 43 | APP_BASE_URL=http://localhost.riotgames.com:3000 44 | APP_CALLBACK_PATH=/oauth-callback 45 | RESPONSE_TYPE=code 46 | SCOPE=openid 47 | ``` 48 | 57 | 58 | # FAQs 🤨❓ 59 | 1. How do I get my RSO_CLIENT_ID? 60 | 1. TBD 61 | 1. How do I get my RSO_CLIENT_SECRET? 62 | 1. TBD 63 | 1. How do I get my DEPLOYMENT_API_KEY? 64 | 1. TBD 65 | 1. How do I get my APP_BASE_URL? 66 | 1. TBD 67 | 1. How do I get my APP_CALLBACK_PATH? 68 | 1. TBD 69 | 1. Is RESPONSE_TYPE always the same? 70 | 1. TBD 71 | 1. Is SCOPE always the same? 72 | 1. TBD 73 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/README.md: -------------------------------------------------------------------------------- 1 | # RUST RSO Sample app 2 | 3 | #### Description 4 | 5 | ### Requirements 6 | 1. Make sure you have your `config.yml` in the root of the project [(_example_)](config/config.yml): `sample_apps/rso_sample_apps/rust/config.yml`. 7 | 1. You need rust 1.77.2 installed on your machine. You can install it from [here](https://www.rust-lang.org/tools/install). 8 | 9 | --- 10 | ### Configuration 11 | 12 | ```yaml 13 | server: # server configuration , 14 | addr: 0.0.0.0:443 # SERVER_ADDRESS - address to bind to 15 | tls: 16 | cert: # SERVER_TLS_CERT - tls certificate 17 | key: # SERVER_TLS_KEY - tls private key 18 | 19 | rso: 20 | base_url: "https://auth.riotgames.com" # RSO_BASE_URL - Riot Games oauth auth provider URL 21 | callback_host: "https://local.example.com" # RSO_CALLBACK_HOST - callback hostname 22 | client_id: "" # RSO_CLIENT_ID - oauth2 client id 23 | client_secret: "" # RSO_CLIENT_SECRET - oauth2 client secret 24 | 25 | api: 26 | token: "" # Riot Games API token - RGAPI_TOKEN 27 | urls: 28 | account_data: "https://americas.api.riotgames.com/riot/account/v1/accounts/me" # RGAPI_URL_ACCOUNT_DATA - Riot Games API account data URL 29 | champion_data: "https://na1.api.riotgames.com/lol/platform/v3/champion-rotations" # RGAPI_URL_CHAMPION_DATA - Riot Games API champion data URL 30 | ``` 31 | #### API Token 32 | _Used to access most of the Riot Games API endpoints. [More Information](https://developer.riotgames.com/docs/portal#web-apis_api-keys)_ 33 | 34 | - **api:** 35 | - **token:** Your Riot Games API Token 36 | 37 | #### OAuth/RSO Configuration 38 | _Used to authenticate users with the Riot Games services requiring OAuth2/RSO authentication. [More Information](https://developer.riotgames.com/docs/lol#rso-integration)._ 39 | 40 | - **rso:** 41 | - **client_id:** OAuth2 client id 42 | - **client_secret:** OAuth2 client secret 43 | 44 | --- 45 | ### Makefile 46 | 47 | This Makefile contains several commands that help with building, testing, cleaning, and running the Rust project. 48 | 49 | #### Commands 50 | 51 | - `make all`: This command first cleans up any previous build artifacts, then builds the project and runs the tests. It's a quick way to ensure everything is up to date and working correctly. 52 | 53 | - `make build`: This command builds the Rust project. It compiles the source code into an executable file. 54 | 55 | - `make test`: This command runs the tests for the Rust project. It ensures that all the functions in the project are working as expected. 56 | 57 | - `make clean`: This command cleans up any build artifacts from previous builds. It's a good practice to clean up before starting a new build. 58 | 59 | - `make run`: This command runs the Rust project. It starts the application. 60 | 61 | - `make debug` : This command runs the Rust project with debug logging enabled. It starts the application. 62 | 63 | To use these commands, open a terminal in the project's root directory and type the command you want to use. For example, to build the project, type `make build`. 64 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/mock/src/lib.rs: -------------------------------------------------------------------------------- 1 | use httpmock::prelude::*; 2 | 3 | /// Represents an authentication provider with a mock server for handling authentication requests. 4 | pub struct AuthProvider { 5 | pub server: MockServer, 6 | } 7 | 8 | impl AuthProvider { 9 | /// Creates a new `AuthProvider` instance with predefined mock behaviors for authentication requests. 10 | /// 11 | /// # Returns 12 | /// An `AuthProvider` instance with a running `MockServer`. 13 | /// 14 | /// # Examples 15 | /// ``` 16 | /// let auth_provider = mock::AuthProvider::new(); 17 | /// ``` 18 | pub fn new() -> Self { 19 | let server = MockServer::start(); 20 | 21 | server.mock(|when, then| { 22 | when.method(POST) 23 | .path("/token") 24 | .x_www_form_urlencoded_key_exists("code"); 25 | then.status(200) 26 | .header("content-type", "application/json") 27 | .body(r#"{"access_token": "xyz", "refresh_token": "abc", "scope": "def", "id_token": "ghi", "token_type": "jkl", "expires_in": 3600}"#); 28 | }); 29 | 30 | server.mock(|when, then| { 31 | when.method(POST).path("/token"); 32 | then.status(401) 33 | .header("content-type", "application/json") 34 | .body(r#"{}"#); 35 | }); 36 | 37 | AuthProvider { server } 38 | } 39 | } 40 | 41 | /// Represents an API provider with a mock server for handling API requests. 42 | pub struct ApiProvider { 43 | pub server: MockServer, 44 | } 45 | 46 | impl ApiProvider { 47 | /// Creates a new `ApiProvider` instance with predefined mock behaviors for API requests. 48 | /// 49 | /// # Returns 50 | /// An `ApiProvider` instance with a running `MockServer`. 51 | /// 52 | /// # Examples 53 | /// ``` 54 | /// let api_provider = mock::ApiProvider::new(); 55 | /// ``` 56 | pub fn new() -> Self { 57 | let server = MockServer::start(); 58 | 59 | server.mock(|when, then| { 60 | when.method(GET) 61 | .path("/riot/account/v1/accounts/me") 62 | .header("Authorization", "Bearer token"); 63 | then.status(200) 64 | .header("content-type", "application/json") 65 | .body(r#"{"puuid":"123","game_name":"user","tag_line":"tag"}"#); 66 | }); 67 | 68 | server.mock(|when, then| { 69 | when.method(GET).path("/riot/account/v1/accounts/me"); 70 | then.status(401) 71 | .header("content-type", "application/json") 72 | .body(r#"{}"#); 73 | }); 74 | 75 | server.mock(|when, then| { 76 | when.method(GET) 77 | .path("/lol/platform/v3/champion-rotations") 78 | .header("X-Riot-Token", "token"); 79 | then.status(200) 80 | .header("content-type", "application/json") 81 | .body(r#"{"free_champion_ids":[1,2,3],"free_champion_ids_for_new_players":[100,101,102],"max_new_player_level":10}"#); 82 | }); 83 | 84 | server.mock(|when, then| { 85 | when.method(GET).path("/lol/platform/v3/champion-rotations"); 86 | then.status(401) 87 | .header("content-type", "application/json") 88 | .body(r#"{}"#); 89 | }); 90 | 91 | ApiProvider { server } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/src/handlers/oauth.rs: -------------------------------------------------------------------------------- 1 | use super::HtmlTemplate; 2 | use crate::config::Configuration; 3 | use askama::Template; 4 | use axum::{ 5 | extract::{Query, State}, 6 | response::IntoResponse, 7 | }; 8 | use base64::prelude::*; 9 | use log::info; 10 | 11 | use serde::{Deserialize, Serialize}; 12 | 13 | /// Represents an OAuth request containing a code. 14 | /// 15 | /// This struct is used to deserialize the query parameters of an incoming OAuth request, 16 | /// specifically capturing the authorization code provided by the OAuth provider after 17 | /// user authentication. 18 | #[derive(Serialize, Deserialize, Clone, Debug)] 19 | pub struct Request { 20 | /// The authorization code provided by the OAuth provider. 21 | pub code: String, 22 | } 23 | 24 | /// Represents the OAuth2 response returned from the authorization server. 25 | /// 26 | /// This struct is used to serialize the OAuth2 tokens and related information received 27 | /// from the authorization server into a format that can be rendered into an HTML template. 28 | /// It includes access and refresh tokens, scope, ID token, token type, and expiration time. 29 | #[derive(Clone, Serialize, Deserialize, Debug, Template)] 30 | #[template(path = "oauth.html")] 31 | pub struct Response { 32 | /// The OAuth2 access token. 33 | pub access_token: String, 34 | /// The OAuth2 refresh token. 35 | pub refresh_token: String, 36 | /// The OAuth2 scope. 37 | pub scope: String, 38 | /// The OAuth2 ID token. 39 | pub id_token: String, 40 | /// The OAuth2 token type. 41 | pub token_type: String, 42 | /// The OAuth2 expiration time in seconds. 43 | pub expires_in: u32, 44 | } 45 | 46 | /// Handles incoming OAuth requests by exchanging the authorization code for tokens. 47 | /// 48 | /// This asynchronous function acts as an Axum handler for OAuth requests. It extracts the 49 | /// authorization code from the query parameters, constructs a request to the authorization 50 | /// server to exchange the code for an access token and other tokens, and then renders the 51 | /// response into an HTML template using the `HtmlTemplate` wrapper. 52 | /// 53 | /// # Arguments 54 | /// * `Query(query)` - The extracted query parameters containing the authorization code. 55 | /// * `State(cfg)` - The application configuration state, containing OAuth client credentials 56 | /// and endpoints. 57 | /// 58 | /// # Returns 59 | /// An implementation of `IntoResponse`, which can be converted into an HTTP response to be 60 | /// sent back to the client. This response includes the OAuth tokens rendered into an HTML 61 | /// template. 62 | pub async fn handle( 63 | Query(query): Query, 64 | State(cfg): State, 65 | ) -> impl IntoResponse { 66 | info!("✍️ handling oauth request"); 67 | let code = query.code; 68 | let form = [ 69 | ("grant_type", "authorization_code"), 70 | ("code", code.as_str()), 71 | ("redirect_uri", &cfg.callback_url()), 72 | ]; 73 | let auth = BASE64_STANDARD.encode(format!("{}:{}", cfg.rso.client_id, cfg.rso.client_secret)); 74 | let res: Response = ureq::post(cfg.token_url().as_str()) 75 | .set("Authorization", format!("Basic {auth}").as_str()) 76 | .send_form(&form) 77 | .expect("error sending token request") 78 | .into_json() 79 | .expect("error parsing oauth response"); 80 | info!("✍️ completed handling oauth request"); 81 | 82 | HtmlTemplate(res) 83 | } 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 2 | # Riot Games Developer Relations Repo 3 | 4 | Welcome to the Riot Games Developer Relations repo. The purpose of this repo is exclusively bug reporting for tools in the Riot Games Developer Ecosystem. 5 | 6 | Everything else can be found at the following links: 7 | 8 | - Riot Games Developer Portal: [https://developer.riotgames.com/](https://developer.riotgames.com/) 9 | - Riot Games DevRel Homepage: [https://www.riotgames.com/en/DevRel](https://www.riotgames.com/en/DevRel) 10 | - Twitter: [https://twitter.com/riotgamesdevrel](https://twitter.com/riotgamesdevrel) 11 | - Discord: [https://discord.gg/riotgamesdevrel](https://discord.gg/riotgamesdevrel) 12 | 13 | # Issue Reporting Guidelines 14 | 15 | The Riot Games Developer Relations team wants to address all issues in a timely manner and will inform the responsible teams of issues their products/services have. However, we cannot guarantee that issues will be resolved. 16 | 17 | Before creating an issue, please do the following: 18 | 19 | - Check the [Developer Documentation](https://developer.riotgames.com/) to make sure the behavior you are reporting is really a bug, not a feature. 20 | - Check the [existing issues](https://github.com/RiotGames/developer-relations/issues) to make sure you are not duplicating somebody's work. 21 | - Verify that the issue you are about to report relates to the Riot Games Developer Ecosystem and is not a game bug (for game bugs please go [here](https://support.riotgames.com/hc/en-us)). 22 | 23 | If you're sure that the problem you're experiencing is caused by a bug, follow the recommendations below to file a new issue in a Github issue tracker. 24 | 25 | **Issue Template** 26 | 27 | Please follow this section carefully, as it ensures we gather accurate information about any issues. 28 | 29 | Note that higher levels of detail in the report increases the chance that someone will be able to reproduce the issue. 30 | 31 | **Issue Format:** 32 | 33 | Preconditions 34 | 35 | 1. 36 | 2. 37 | 38 | Steps to Reproduce 39 | 40 | 1. 41 | 2. 42 | 3. 43 | 44 | Expected Result 45 | 46 | 1. [Screenshots, logs or description] 47 | 48 | Actual Result 49 | 50 | 1. [Screenshots, logs or description] 51 | 52 | # Title 53 | 54 | The title is a vital part of a bug report that allows the developer and triager to quickly identify a unique issue. A well-written title should contain a clear, brief explanation of the issue, emphasizing the most important points. 55 | 56 | Clear example: Attack speed in Data Dragon is missing as of the last update 57 | 58 | Unclear example: DDragon Wrong 59 | 60 | # Description 61 | 62 | **Preconditions** 63 | 64 | Describing preconditions is a great start. Be sure to provide information on system configuration, project type, and languages used. Basically, we need everything that could help us set up the same environment you have. 65 | 66 | **Steps to Reproduce** 67 | 68 | This is the most important part of a bug report, as we'll use this information to reproduce the issue. The issue is more likely to be fixed if it can be reproduced. 69 | 70 | Describe each step you have taken to reproduce the issue. Try to include as much information as possible—sometimes even minor differences can be crucial. 71 | 72 | **Actual and Expected Results** 73 | 74 | These sections will help us make sure that everybody involved in the fix is on the same page. Describe the result you expected to get and the result you actually observed after performing the steps. 75 | 76 | **Additional Information** 77 | 78 | Additional information is often requested when the bug report is processed. You can save time by providing browser logs, screenshots, or any other artifacts related to the issue as needed. 79 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/templates/data.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Account and Champion Data 7 | 8 | 45 | 46 | 47 |
48 |
49 |
50 |

Account Data Queried Using RSO Access Token

51 |
52 |
53 |

{{account_data}}

54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 |
KeyValue
PUUID{{account.puuid}}
Game Name{{account.game_name}}
Tag Line{{account.tag_line}}
76 |
77 |
78 | 79 |
80 |
81 |

Champion Rotation Data Queried Using RGAPI Token

82 |
83 |
84 |

{{champion_rotation_data}}

85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 |
KeyValue
Free Champion IDs{{format!("{:?}", self.champion_rotation.free_champion_ids)}}
Free Champion IDs for New Players{{format!("{:?}", self.champion_rotation.free_champion_ids)}}
Max New Player Level{{format!("{:?}", self.champion_rotation.max_new_player_level)}}
107 |
108 |
109 | 110 |
111 | Logout 112 |
113 |
114 | 115 | 116 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/nodejs/index.js: -------------------------------------------------------------------------------- 1 | import dotenv from 'dotenv'; 2 | import express from 'express'; 3 | import fetch from 'node-fetch'; 4 | import url from 'url'; 5 | 6 | const app = express(); 7 | const port = 3000; 8 | 9 | dotenv.config({ path: '../.env' }); 10 | 11 | const TIMEOUT = 10 12 | var CONFIG = { 13 | RSO_BASE_URL: process.env.RSO_BASE_URL, 14 | RSO_CLIENT_ID: process.env.RSO_CLIENT_ID, 15 | RSO_CLIENT_SECRET: process.env.RSO_CLIENT_SECRET, 16 | APP_BASE_URL: process.env.APP_BASE_URL, 17 | APP_CALLBACK_PATH: process.env.APP_CALLBACK_PATH, 18 | CLIENT_ID: process.env.CLIENT_ID, 19 | RESPONSE_TYPE: process.env.RESPONSE_TYPE, 20 | SCOPE: process.env.SCOPE, 21 | RGAPI_TOKEN: process.env.RGAPI_TOKEN 22 | } 23 | 24 | CONFIG['TOKEN_URL'] = `${CONFIG.RSO_BASE_URL}/token` 25 | CONFIG['APP_CALLBACK_URL'] = `${CONFIG.APP_BASE_URL}${CONFIG.APP_CALLBACK_PATH}` 26 | CONFIG['AUTHORIZE_URL'] = `${CONFIG.RSO_BASE_URL}/authorize` 27 | 28 | CONFIG['SIGN_IN_URL'] = `${CONFIG.AUTHORIZE_URL}` 29 | CONFIG['SIGN_IN_URL'] += `?redirect_uri=${CONFIG.APP_CALLBACK_URL}` 30 | CONFIG['SIGN_IN_URL'] += `&client_id=${CONFIG.RSO_CLIENT_ID}` 31 | CONFIG['SIGN_IN_URL'] += `&response_type=${CONFIG.RESPONSE_TYPE}` 32 | CONFIG['SIGN_IN_URL'] += `&scope=${CONFIG.SCOPE} ` 33 | 34 | app.get('/', function (req, res) { 35 | res.send(` 36 |

login

37 | Sign In-- > ${CONFIG.SIGN_IN_URL} ` 38 | ); 39 | }); 40 | 41 | app.get(CONFIG.APP_CALLBACK_PATH, async function (req, res) { 42 | var code = req.query.code; 43 | 44 | const params = new URLSearchParams(); 45 | params.append("grant_type", "authorization_code"); 46 | params.append("code", code); 47 | params.append("redirect_uri", CONFIG.APP_CALLBACK_URL); 48 | 49 | const response = await fetch(CONFIG.TOKEN_URL, { 50 | method: "POST", 51 | headers: { 52 | Authorization: 'Basic ' + Buffer.from(CONFIG.RSO_CLIENT_ID + ":" + CONFIG.RSO_CLIENT_SECRET).toString('base64') 53 | }, 54 | body: params 55 | } 56 | ); 57 | 58 | const data = await response.json(); 59 | var query_string = new URLSearchParams(data).toString(); 60 | res.send(``); 61 | }); 62 | 63 | app.get("/show-data", async function (req, res) { 64 | const access_token = url.parse(req.url, true).query.access_token; 65 | 66 | var account_data = await get_account_data(access_token); 67 | var account_html = ` 68 |

account data queried using RSO Access Token:

69 |

${json2table(account_data)}

70 | ` 71 | 72 | var champion_rotation_data = await get_champion_rotation_data(CONFIG.RGAPI_TOKEN); 73 | var champion_rotation_html = ` 74 |

champion rotation data queried using RGAPI token

75 |

${json2table(champion_rotation_data)}

76 | ` 77 | res.send(` 78 | ${account_html} 79 | ${champion_rotation_html} 80 | `) 81 | }); 82 | 83 | async function get_champion_rotation_data(token) { 84 | const response = await fetch('https://na1.api.riotgames.com/lol/platform/v3/champion-rotations', 85 | { 86 | method: "GET", 87 | headers: { 88 | "X-Riot-Token": token 89 | } 90 | 91 | }); 92 | const data = await response.json(); 93 | return data; 94 | } 95 | 96 | async function get_account_data(access_token) { 97 | const response = await fetch('https://americas.api.riotgames.com/riot/account/v1/accounts/me', 98 | { 99 | method: "GET", 100 | headers: { 101 | Authorization: `Bearer ${access_token}` 102 | } 103 | 104 | }); 105 | const data = await response.json(); 106 | return data; 107 | } 108 | 109 | function json2table(json) { 110 | const style = ` 111 | `; 119 | 120 | var html = ` 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | `; 130 | 131 | for (const [key, value] of Object.entries(json)) { 132 | html += ` 133 | 134 | 135 | 136 | ` 137 | } 138 | 139 | html += ` 140 | 141 |
keyvalue
${key}${value}
142 | ` 143 | 144 | return style + html; 145 | 146 | } 147 | app.listen(port, () => console.log(`Example app listening on post ${port}!`)); 148 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/python/main.py: -------------------------------------------------------------------------------- 1 | """ 2 | FastAPI app for showing how to implement your own RSO client, 3 | get an access token and make requests on behalf a user. 4 | """ 5 | import os 6 | 7 | import requests 8 | import uvicorn 9 | from dotenv import load_dotenv 10 | from fastapi import FastAPI 11 | from fastapi.responses import HTMLResponse 12 | from requests.auth import HTTPBasicAuth 13 | 14 | load_dotenv('../.env') 15 | 16 | app = FastAPI() 17 | 18 | TIMEOUT = 10 19 | CONFIG = { 20 | "RSO_BASE_URL": os.getenv("RSO_BASE_URL"), 21 | "RSO_CLIENT_ID": os.getenv("RSO_CLIENT_ID"), 22 | "RSO_CLIENT_SECRET": os.getenv("RSO_CLIENT_SECRET"), 23 | "APP_BASE_URL": os.getenv("APP_BASE_URL"), 24 | "APP_CALLBACK_PATH": os.getenv("APP_CALLBACK_PATH"), 25 | "CLIENT_ID": os.getenv("CLIENT_ID"), 26 | "RESPONSE_TYPE": os.getenv("RESPONSE_TYPE"), 27 | "SCOPE": os.getenv("SCOPE"), 28 | "RGAPI_TOKEN": os.getenv("RGAPI_TOKEN") 29 | } 30 | CONFIG['TOKEN_URL'] = f"{CONFIG['RSO_BASE_URL']}/token" 31 | CONFIG["APP_CALLBACK_URL"] = f"{CONFIG['APP_BASE_URL']}{CONFIG['APP_CALLBACK_PATH']}" 32 | CONFIG["AUTHORIZE_URL"] = f"{CONFIG['RSO_BASE_URL']}/authorize" 33 | 34 | CONFIG["SIGN_IN_URL"] = f"{CONFIG['AUTHORIZE_URL']}" 35 | CONFIG["SIGN_IN_URL"] += f"?redirect_uri={CONFIG['APP_CALLBACK_URL']}" 36 | CONFIG["SIGN_IN_URL"] += f"&client_id={CONFIG['RSO_CLIENT_ID']}" 37 | CONFIG["SIGN_IN_URL"] += f"&response_type={CONFIG['RESPONSE_TYPE']}" 38 | CONFIG["SIGN_IN_URL"] += f"&scope={CONFIG['SCOPE']}" 39 | 40 | 41 | @app.get("/", response_class=HTMLResponse) 42 | def login(): 43 | return f""" 44 |

login

45 | Sign In --> {CONFIG["SIGN_IN_URL"]} 46 | """ 47 | 48 | 49 | @app.get(CONFIG["APP_CALLBACK_PATH"], response_class=HTMLResponse) 50 | def oauth_callback(code: str): 51 | resp = requests.post(CONFIG['TOKEN_URL'], 52 | auth=HTTPBasicAuth(CONFIG["RSO_CLIENT_ID"], 53 | CONFIG["RSO_CLIENT_SECRET"]), 54 | data={ 55 | "grant_type": "authorization_code", 56 | "code": code, 57 | "redirect_uri": CONFIG["APP_CALLBACK_URL"] 58 | }, 59 | timeout=TIMEOUT 60 | ) 61 | 62 | query_string = "" 63 | 64 | if resp.json() is not None: 65 | for k, v in resp.json().items(): 66 | query_string += f'{k}={v}&' 67 | 68 | return f"""""" 69 | 70 | 71 | def json2table(json): 72 | style = """ 73 | """ 81 | 82 | html = """ 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | """ 92 | 93 | for key, value in json.items(): 94 | html += f""" 95 | 96 | 97 | 98 | """ 99 | 100 | html += """ 101 | 102 |
keyvalue
{key}{value}
103 | """ 104 | 105 | return style + html 106 | 107 | 108 | @app.get("/show-data/", response_class=HTMLResponse) 109 | def show_data(access_token: str): 110 | """ 111 | tBD 112 | """ 113 | account_data = get_account_data(access_token) 114 | account_html = f""" 115 |

account data queried using RSO Access Token:

116 |

{json2table(json=account_data)}

117 | """ 118 | 119 | champion_rotation_data = get_champion_rotation_data(CONFIG["RGAPI_TOKEN"]) 120 | champion_rotation_html = f""" 121 |

champion rotation data queried using RGAPI token

122 |

{json2table(json=champion_rotation_data)}

123 | """ 124 | 125 | return f""" 126 | {account_html} 127 | {champion_rotation_html} 128 | """ 129 | 130 | 131 | def get_account_data(access_token): 132 | resp = requests.get( 133 | "https://americas.api.riotgames.com/riot/account/v1/accounts/me", 134 | headers={ 135 | "Authorization": f"Bearer {access_token}" 136 | }, 137 | timeout=TIMEOUT 138 | ) 139 | return resp.json() 140 | 141 | 142 | def get_champion_rotation_data(token: str): 143 | resp = requests.get( 144 | "https://na1.api.riotgames.com/lol/platform/v3/champion-rotations", 145 | headers={ 146 | "X-Riot-Token": token 147 | }, 148 | timeout=TIMEOUT 149 | ) 150 | return resp.json() 151 | 152 | 153 | if __name__ == "__main__": 154 | uvicorn.run("main:app", 155 | host="localhost", 156 | port=3000, 157 | log_level="debug", 158 | reload=True 159 | ) 160 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/src/service.rs: -------------------------------------------------------------------------------- 1 | use crate::config::Configuration; 2 | use crate::{config, handlers}; 3 | use axum::{routing::get, Router}; 4 | use axum_server::tls_rustls::RustlsConfig; 5 | use log::{debug, info}; 6 | 7 | /// Creates an instance of `Router` configured with routes and application state. 8 | /// 9 | /// This function sets up the application's routes by associating URL paths with their respective handler functions. 10 | /// It also attaches the application configuration to the state of the router, making it accessible to the handlers. 11 | /// 12 | /// # Arguments 13 | /// * `cfg` - A reference to the application's configuration. 14 | /// 15 | /// # Returns 16 | /// 17 | /// Returns an instance of `Router` configured with the application's routes and state. 18 | fn create_app(cfg: &Configuration) -> Router { 19 | Router::new() 20 | .route("/data", get(handlers::data::handle)) 21 | .route("/oauth", get(handlers::oauth::handle)) 22 | .route("/", get(handlers::default::handle)) 23 | .with_state(cfg.clone()) 24 | } 25 | 26 | /// Starts the web service with the provided configuration. 27 | /// 28 | /// This asynchronous function attempts to parse the server address from the configuration and start the server. 29 | /// If TLS configuration is provided, it starts a TLS server; otherwise, it starts a regular HTTP server. 30 | /// It logs the server's start-up and panics if the server address is invalid or if there are issues starting the server. 31 | /// 32 | /// # Arguments 33 | /// * `cfg` - A reference to the configuration to use for the service. 34 | /// 35 | /// # Panics 36 | /// 37 | /// Panics if the host address is invalid or if there are issues starting the server. 38 | pub(crate) async fn listen(cfg: &config::Configuration) { 39 | match cfg.server.addr.parse::() { 40 | Ok(addr) => { 41 | let app = create_app(cfg); 42 | match cfg.clone().server.tls { 43 | Some(tls) => { 44 | let config = RustlsConfig::from_pem_file(tls.cert, tls.key) 45 | .await 46 | .unwrap(); 47 | info!("☁️ starting server with tls @ {addr}"); 48 | axum_server::bind_rustls(addr, config) 49 | .serve(app.into_make_service()) 50 | .await 51 | .unwrap(); 52 | } 53 | None => { 54 | debug!("☁️ starting server @ {addr}"); 55 | axum_server::bind(addr) 56 | .serve(app.into_make_service()) 57 | .await 58 | .unwrap(); 59 | } 60 | } 61 | } 62 | Err(e) => { 63 | panic!("{e}"); 64 | } 65 | } 66 | } 67 | 68 | #[cfg(test)] 69 | mod tests { 70 | use super::*; 71 | use crate::config::{Api, Rso, Tls, Urls}; 72 | use axum::body::Body; 73 | use axum::http::{Request, StatusCode}; 74 | use mock::AuthProvider; 75 | use tower::ServiceExt; 76 | 77 | fn configuration(auth: &AuthProvider) -> Configuration { 78 | Configuration { 79 | server: crate::config::Server { 80 | addr: "0.0.0.0:443".to_string(), 81 | tls: Some(Tls { 82 | cert: "cert".to_string(), 83 | key: "key".to_string(), 84 | }), 85 | }, 86 | api: Api { 87 | token: "token".to_string(), 88 | urls: Urls { 89 | account_data: auth.server.url("/riot/account/v1/accounts/me"), 90 | champion_data: auth.server.url("/lol/platform/v3/champion-rotations"), 91 | }, 92 | }, 93 | rso: Rso { 94 | base_url: auth.server.url("").to_string(), 95 | callback_host: "local.example.com:8080".to_string(), 96 | client_id: "client_id".to_string(), 97 | client_secret: "client_secret".to_string(), 98 | }, 99 | } 100 | } 101 | 102 | #[tokio::test] 103 | async fn default() { 104 | let prov = mock::AuthProvider::new(); 105 | let cfg = configuration(&prov); 106 | let app = create_app(&cfg); 107 | let response = app 108 | .oneshot(Request::builder().uri("/").body(Body::empty()).unwrap()) 109 | .await 110 | .unwrap(); 111 | 112 | assert_eq!(response.status(), StatusCode::OK); 113 | } 114 | 115 | #[tokio::test] 116 | async fn oauth_no_code() { 117 | let prov = mock::AuthProvider::new(); 118 | let cfg = configuration(&prov); 119 | let app = create_app(&cfg); 120 | let response = app 121 | .oneshot( 122 | Request::builder() 123 | .uri("/oauth") 124 | .body(Body::empty()) 125 | .unwrap(), 126 | ) 127 | .await 128 | .unwrap(); 129 | 130 | assert_eq!(response.status(), StatusCode::BAD_REQUEST); 131 | } 132 | 133 | #[tokio::test] 134 | async fn oauth_code() { 135 | let prov = mock::AuthProvider::new(); 136 | let cfg = configuration(&prov); 137 | let app = create_app(&cfg); 138 | 139 | let response = app 140 | .oneshot( 141 | Request::builder() 142 | .uri("/oauth?code=200") 143 | .body(Body::empty()) 144 | .unwrap(), 145 | ) 146 | .await 147 | .unwrap(); 148 | 149 | assert_eq!(response.status(), StatusCode::OK); 150 | } 151 | 152 | #[tokio::test] 153 | async fn data_returns_expected_result() { 154 | let prov = mock::AuthProvider::new(); 155 | let cfg = configuration(&prov); 156 | let app = create_app(&cfg); 157 | 158 | let response = app 159 | .oneshot( 160 | Request::builder() 161 | .uri("/data?access_token=200") 162 | .body(Body::empty()) 163 | .unwrap(), 164 | ) 165 | .await 166 | .unwrap(); 167 | 168 | assert_eq!(response.status(), StatusCode::OK); 169 | } 170 | 171 | #[tokio::test] 172 | async fn data_returns_unauthorized_when_no_access_token() { 173 | let prov = mock::AuthProvider::new(); 174 | let cfg = configuration(&prov); 175 | let app = create_app(&cfg); 176 | 177 | let response = app 178 | .oneshot(Request::builder().uri("/data").body(Body::empty()).unwrap()) 179 | .await 180 | .unwrap(); 181 | 182 | assert_eq!(response.status(), StatusCode::BAD_REQUEST); 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "log" 8 | "net/http" 9 | "net/url" 10 | "os" 11 | "path/filepath" 12 | "strings" 13 | 14 | "github.com/joho/godotenv" 15 | ) 16 | 17 | var CONFIG map[string]string 18 | 19 | func loadConfig() { 20 | wd, err := os.Getwd() 21 | if err != nil { 22 | panic(err) 23 | } 24 | parent := filepath.Dir(wd) 25 | 26 | err = godotenv.Load(filepath.Join(parent, ".env")) 27 | if err != nil { 28 | log.Fatal("Error loading .env file") 29 | } 30 | 31 | CONFIG = make(map[string]string) 32 | 33 | CONFIG["RSO_BASE_URL"] = os.Getenv("RSO_BASE_URL") 34 | CONFIG["RSO_CLIENT_ID"] = os.Getenv("RSO_CLIENT_ID") 35 | CONFIG["RSO_CLIENT_SECRET"] = os.Getenv("RSO_CLIENT_SECRET") 36 | CONFIG["APP_BASE_URL"] = os.Getenv("APP_BASE_URL") 37 | CONFIG["APP_CALLBACK_PATH"] = os.Getenv("APP_CALLBACK_PATH") 38 | CONFIG["CLIENT_ID"] = os.Getenv("CLIENT_ID") 39 | CONFIG["RESPONSE_TYPE"] = os.Getenv("RESPONSE_TYPE") 40 | CONFIG["SCOPE"] = os.Getenv("SCOPE") 41 | CONFIG["RGAPI_TOKEN"] = os.Getenv("RGAPI_TOKEN") 42 | 43 | CONFIG["TOKEN_URL"] = fmt.Sprintf("%s/token", CONFIG["RSO_BASE_URL"]) 44 | CONFIG["APP_CALLBACK_URL"] = fmt.Sprintf("%s%s", CONFIG["APP_BASE_URL"], CONFIG["APP_CALLBACK_PATH"]) 45 | CONFIG["AUTHORIZE_URL"] = fmt.Sprintf("%s/authorize", CONFIG["RSO_BASE_URL"]) 46 | 47 | CONFIG["SIGN_IN_URL"] = CONFIG["AUTHORIZE_URL"] 48 | CONFIG["SIGN_IN_URL"] += fmt.Sprintf("?redirect_uri=%s", CONFIG["APP_CALLBACK_URL"]) 49 | CONFIG["SIGN_IN_URL"] += fmt.Sprintf("&client_id=%s", CONFIG["RSO_CLIENT_ID"]) 50 | CONFIG["SIGN_IN_URL"] += fmt.Sprintf("&response_type=%s", CONFIG["RESPONSE_TYPE"]) 51 | CONFIG["SIGN_IN_URL"] += fmt.Sprintf("&scope=%s", CONFIG["SCOPE"]) 52 | } 53 | 54 | func login(w http.ResponseWriter, req *http.Request) { 55 | fmt.Println("login") 56 | html := fmt.Sprintf( 57 | "

login

Sign In --> %s", 58 | CONFIG["SIGN_IN_URL"], CONFIG["SIGN_IN_URL"]) 59 | 60 | w.Header().Set("Content-Type", "text/html; charset=utf-8") 61 | w.Write([]byte(html)) 62 | } 63 | 64 | func oauthCallback(w http.ResponseWriter, req *http.Request) { 65 | type TokenURLResponse struct { 66 | AccessToken string `json:"access_token"` 67 | RefreshToken string `json:"refresh_token"` 68 | Scope string `json:"scope"` 69 | IDToken string `json:"id_token"` 70 | TokenType string `json:"token_type"` 71 | ExpiresIn int `json:"expires_in"` 72 | } 73 | 74 | code := req.URL.Query().Get("code") 75 | 76 | form := url.Values{} 77 | form.Add("grant_type", "authorization_code") 78 | form.Add("code", code) 79 | form.Add("redirect_uri", CONFIG["APP_CALLBACK_URL"]) 80 | 81 | postReq, _ := http.NewRequest( 82 | "POST", 83 | CONFIG["TOKEN_URL"], 84 | strings.NewReader(form.Encode()), 85 | ) 86 | postReq.SetBasicAuth(CONFIG["RSO_CLIENT_ID"], CONFIG["RSO_CLIENT_SECRET"]) 87 | postReq.Header.Set("Content-Type", "application/x-www-form-urlencoded") 88 | 89 | postRes, _ := http.DefaultClient.Do(postReq) 90 | defer postRes.Body.Close() 91 | 92 | body, _ := ioutil.ReadAll(postRes.Body) 93 | 94 | var tokenURLResponse TokenURLResponse 95 | json.Unmarshal(body, &tokenURLResponse) 96 | 97 | queryString := fmt.Sprintf("access_token=%s", tokenURLResponse.AccessToken) 98 | 99 | html := fmt.Sprintf( 100 | "", 101 | queryString) 102 | w.Write([]byte(html)) 103 | } 104 | 105 | func showData(w http.ResponseWriter, req *http.Request) { 106 | accessToken := req.URL.Query().Get("access_token") 107 | 108 | accountData := getAccountData(accessToken) 109 | accountHTML := fmt.Sprintf( 110 | "

account data queried using RSO Access Token:

%v

", 111 | accountData) 112 | 113 | championRotationData := getChampionRotationData(CONFIG["RGAPI_TOKEN"]) 114 | championRotationHTML := fmt.Sprintf( 115 | "

champion rotation data queried using RGAPI token

%v

", 116 | championRotationData) 117 | 118 | html := fmt.Sprintf("%s %s", accountHTML, championRotationHTML) 119 | w.Header().Set("Content-Type", "text/html; charset=utf-8") 120 | w.Write([]byte(html)) 121 | } 122 | 123 | func getAccountData(accessToken string) string { 124 | type AccountData struct { 125 | Puuid string `html:"l=Puuid,e=span,c=puuid"` 126 | GameName string `html:"l=GameName,e=span,c=gamename"` 127 | TagLine string `html:"l=TagLine,e=span,c=tagline"` 128 | } 129 | 130 | req, _ := http.NewRequest( 131 | "GET", 132 | "https://americas.api.riotgames.com/riot/account/v1/accounts/me", 133 | nil, 134 | ) 135 | req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", accessToken)) 136 | res, _ := http.DefaultClient.Do(req) 137 | defer res.Body.Close() 138 | 139 | body, _ := ioutil.ReadAll(res.Body) 140 | 141 | var accountData AccountData 142 | json.Unmarshal(body, &accountData) 143 | 144 | html, _ := structToHTML(map[string]string{ 145 | "puuid": fmt.Sprint(accountData.Puuid), 146 | "gameName": fmt.Sprint(accountData.GameName), 147 | "tagLine": fmt.Sprint(accountData.TagLine), 148 | }) 149 | 150 | return html 151 | } 152 | 153 | func getChampionRotationData(token string) string { 154 | type ChampionRotationData struct { 155 | FreeChampionIds []int 156 | FreeChampionIdsForNewPlayers []int 157 | MaxNewPlayerLevel int 158 | } 159 | 160 | req, _ := http.NewRequest( 161 | "GET", 162 | "https://na1.api.riotgames.com/lol/platform/v3/champion-rotations", 163 | nil, 164 | ) 165 | req.Header.Add("X-Riot-Token", token) 166 | res, _ := http.DefaultClient.Do(req) 167 | defer res.Body.Close() 168 | 169 | body, _ := ioutil.ReadAll(res.Body) 170 | 171 | var championRotationData ChampionRotationData 172 | json.Unmarshal(body, &championRotationData) 173 | 174 | html, _ := structToHTML(map[string]string{ 175 | "freeChampionIds": fmt.Sprint(championRotationData.FreeChampionIds), 176 | "freeChampionIdsForNewPlayers": fmt.Sprint(championRotationData.FreeChampionIdsForNewPlayers), 177 | "maxNewPlayerLevel": fmt.Sprint(championRotationData.MaxNewPlayerLevel), 178 | }) 179 | 180 | return html 181 | } 182 | 183 | func structToHTML(data map[string]string) (string, error) { 184 | style := ` 185 | ` 193 | html := ` 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | ` 203 | 204 | for key, value := range data { 205 | html += fmt.Sprintf(` 206 | 207 | 208 | 209 | `, key, value) 210 | } 211 | 212 | html += ` 213 | 214 |
keyvalue
%s%s
215 | ` 216 | 217 | return style + html, nil 218 | } 219 | 220 | func main() { 221 | loadConfig() 222 | 223 | http.HandleFunc("/", login) 224 | http.HandleFunc(CONFIG["APP_CALLBACK_PATH"], oauthCallback) 225 | http.HandleFunc("/show-data/", showData) 226 | 227 | http.ListenAndServe(":3000", nil) 228 | } 229 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/src/config.rs: -------------------------------------------------------------------------------- 1 | use config::{Config, Environment, File}; 2 | use log::debug; 3 | use serde_derive::{Deserialize, Serialize}; 4 | 5 | /// Represents the TLS configuration for the server. 6 | #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] 7 | pub struct Tls { 8 | /// The TLS certificate 9 | pub cert: String, 10 | /// The TLS key 11 | pub key: String, 12 | } 13 | 14 | /// Configuration for the server, including address and optional TLS settings. 15 | #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] 16 | pub struct Server { 17 | /// The server's address in the format `ip:port`. 18 | pub addr: String, 19 | /// Optional TLS configuration for secure connections. 20 | pub tls: Option, 21 | } 22 | 23 | /// Main configuration structure for the application. 24 | /// 25 | /// Holds configurations for the server, OAuth client, and API endpoints. 26 | #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] 27 | pub struct Configuration { 28 | /// Server configuration, including address and TLS settings. 29 | pub server: Server, 30 | /// OAuth client configuration. 31 | pub rso: Rso, 32 | /// API endpoint configurations. 33 | pub api: Api, 34 | } 35 | 36 | impl From for Configuration { 37 | fn from(cfg: config::Config) -> Self { 38 | Configuration { 39 | server: Server { 40 | addr: cfg.get::("SERVER_ADDRESS").unwrap_or_default(), 41 | tls: cfg.get::>("SERVER_TLS").unwrap_or(None), 42 | }, 43 | rso: Rso { 44 | base_url: cfg.get::("RSO_BASE_URL").unwrap_or_default(), 45 | callback_host: cfg.get::("RSO_CALLBACK_HOST").unwrap_or_default(), 46 | client_id: cfg.get::("RSO_CLIENT_ID").unwrap_or_default(), 47 | client_secret: cfg.get::("RSO_CLIENT_SECRET").unwrap_or_default(), 48 | }, 49 | api: Api { 50 | token: cfg.get::("RGAPI_TOKEN").unwrap_or_default(), 51 | urls: Urls { 52 | account_data: cfg 53 | .get::("RGAPI_URL_ACCOUNT_DATA") 54 | .unwrap_or_default(), 55 | champion_data: cfg 56 | .get::("RGAPI_URL_CHAMPION_DATA") 57 | .unwrap_or_default(), 58 | }, 59 | }, 60 | } 61 | } 62 | } 63 | 64 | /// OAuth client configuration. 65 | #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] 66 | pub struct Rso { 67 | /// Base URL for the OAuth provider. 68 | pub base_url: String, 69 | /// Host to which the OAuth provider will redirect after authentication. 70 | pub callback_host: String, 71 | /// Client ID for OAuth authentication. 72 | pub client_id: String, 73 | /// Client secret for OAuth authentication. 74 | pub client_secret: String, 75 | } 76 | 77 | /// Configuration for API endpoints. 78 | #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] 79 | pub struct Api { 80 | /// Token for API authentication. 81 | pub token: String, 82 | /// URLs for different API endpoints. 83 | pub urls: Urls, 84 | } 85 | 86 | /// URLs for the API endpoints. 87 | #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] 88 | pub struct Urls { 89 | /// Endpoint for retrieving account data. 90 | pub account_data: String, 91 | /// Endpoint for retrieving champion data. 92 | pub champion_data: String, 93 | } 94 | 95 | impl Configuration { 96 | /// Constructs the callback URL for OAuth provider redirection. 97 | /// 98 | /// # Returns 99 | /// A `String` representing the full callback URL. 100 | pub fn callback_url(&self) -> String { 101 | let protocol = match self.server.tls { 102 | Some(_) => "https://", 103 | None => "http://", 104 | }; 105 | format!("{}{}/oauth", protocol, self.rso.callback_host) 106 | } 107 | 108 | /// Constructs the token endpoint URL. 109 | /// 110 | /// # Returns 111 | /// A `String` representing the full token endpoint URL. 112 | pub fn token_url(&self) -> String { 113 | format!("{}/token", self.rso.base_url) 114 | } 115 | 116 | /// Constructs the authorization endpoint URL. 117 | /// 118 | /// # Returns 119 | /// A `String` representing the full authorization endpoint URL. 120 | pub fn authorize_url(&self) -> String { 121 | format!("{}/authorize", self.rso.base_url) 122 | } 123 | 124 | /// Constructs the sign-in URL with query parameters for OAuth authentication. 125 | /// 126 | /// # Returns 127 | /// A `String` representing the full sign-in URL. 128 | pub fn sign_in_url(&self) -> String { 129 | format!( 130 | "{}?redirect_uri={}&client_id={}&response_type=code&scope=openid", 131 | self.authorize_url(), 132 | self.callback_url(), 133 | self.rso.client_id, 134 | ) 135 | } 136 | } 137 | 138 | /// Parses the application configuration from a file and environment variables. 139 | /// 140 | /// # Arguments 141 | /// * `filepath` - The path to the configuration file. 142 | /// 143 | /// # Returns 144 | /// A `Result` which is `Ok` with the `Configuration` if parsing and deserialization are successful, 145 | /// or an `Err` with a string message indicating the error. 146 | pub(crate) fn parse(filepath: String) -> Result { 147 | let cfg = match Config::builder() 148 | .add_source(File::with_name(&filepath).required(false)) 149 | .add_source(Environment::default()) 150 | .build() 151 | { 152 | Ok(cfg) => cfg, 153 | Err(e) => { 154 | return Err(format!("error parsing configuration - {e}")); 155 | } 156 | }; 157 | 158 | match cfg.try_deserialize() { 159 | Ok(cfg) => { 160 | debug!("📄 parsed configuration successfully"); 161 | Ok(cfg) 162 | } 163 | Err(e) => Err(format!("error deserializing configuration - {e}")), 164 | } 165 | } 166 | 167 | #[cfg(test)] 168 | mod tests { 169 | use super::*; 170 | use crate::config; 171 | use crate::config::Tls; 172 | use std::collections::HashMap; 173 | 174 | fn create_cfg() -> Configuration { 175 | Configuration { 176 | server: config::Server { 177 | addr: "0.0.0.0:443".to_string(), 178 | tls: None, 179 | }, 180 | api: Api { 181 | token: "token".to_string(), 182 | urls: Urls { 183 | account_data: "account_data".to_string(), 184 | champion_data: "champion_data".to_string(), 185 | }, 186 | }, 187 | rso: Rso { 188 | base_url: "base_url".to_string(), 189 | callback_host: "local.example.com:8080".to_string(), 190 | client_id: "client_id".to_string(), 191 | client_secret: "client_secret".to_string(), 192 | }, 193 | } 194 | } 195 | 196 | fn create_cfg_tls() -> Configuration { 197 | Configuration { 198 | server: config::Server { 199 | addr: "0.0.0.0:443".to_string(), 200 | tls: Some(Tls { 201 | cert: "cert".to_string(), 202 | key: "key".to_string(), 203 | }), 204 | }, 205 | api: Api { 206 | token: "token".to_string(), 207 | urls: Urls { 208 | account_data: "account_data".to_string(), 209 | champion_data: "champion_data".to_string(), 210 | }, 211 | }, 212 | rso: Rso { 213 | base_url: "base_url".to_string(), 214 | callback_host: "local.example.com:8080".to_string(), 215 | client_id: "client_id".to_string(), 216 | client_secret: "client_secret".to_string(), 217 | }, 218 | } 219 | } 220 | 221 | #[test] 222 | fn test_config_env() { 223 | let mut env = HashMap::new(); 224 | let keys_and_values = [ 225 | ("SERVER_ADDRESS", "SERVER_ADDRESS"), 226 | ("SERVER_TLS_CERT", "SERVER_TLS_CERT"), 227 | ("SERVER_TLS_KEY", "SERVER_TLS_KEY"), 228 | ("RSO_BASE_URL", "RSO_BASE_URL"), 229 | ("RSO_CALLBACK_HOST", "RSO_CALLBACK_HOST"), 230 | ("RSO_CLIENT_ID", "RSO_CLIENT_ID"), 231 | ("RSO_CLIENT_SECRET", "RSO_CLIENT_SECRET"), 232 | ("RGAPI_TOKEN", "RGAPI_TOKEN"), 233 | ("RGAPI_URL_ACCOUNT_DATA", "RGAPI_URL_ACCOUNT_DATA"), 234 | ("RGAPI_URL_CHAMPION_DATA", "RGAPI_URL_CHAMPION_DATA"), 235 | ]; 236 | 237 | for (key, value) in keys_and_values.iter() { 238 | env.insert((*key).into(), (*value).into()); 239 | } 240 | 241 | let source = Environment::default().source(Some(env)); 242 | let c: Configuration = Config::builder() 243 | .add_source(source) 244 | .build() 245 | .unwrap() 246 | .try_into() 247 | .unwrap(); 248 | assert_eq!(c.server.addr, "SERVER_ADDRESS"); 249 | assert_eq!(c.rso.base_url, "RSO_BASE_URL"); 250 | assert_eq!(c.rso.callback_host, "RSO_CALLBACK_HOST"); 251 | assert_eq!(c.rso.client_id, "RSO_CLIENT_ID"); 252 | assert_eq!(c.rso.client_secret, "RSO_CLIENT_SECRET"); 253 | assert_eq!(c.api.token, "RGAPI_TOKEN"); 254 | assert_eq!(c.api.urls.account_data, "RGAPI_URL_ACCOUNT_DATA"); 255 | assert_eq!(c.api.urls.champion_data, "RGAPI_URL_CHAMPION_DATA"); 256 | } 257 | 258 | #[test] 259 | fn test_sign_in_url() { 260 | let config = create_cfg(); 261 | assert_eq!( 262 | config.sign_in_url(), 263 | "base_url/authorize?redirect_uri=http://local.example.com:8080/oauth&client_id=client_id&response_type=code&scope=openid", 264 | ); 265 | } 266 | 267 | #[test] 268 | fn test_sign_in_url_tls() { 269 | let config = create_cfg_tls(); 270 | assert_eq!( 271 | config.sign_in_url(), 272 | "base_url/authorize?redirect_uri=https://local.example.com:8080/oauth&client_id=client_id&response_type=code&scope=openid", 273 | ); 274 | } 275 | 276 | #[test] 277 | fn test_callback_url() { 278 | let config = create_cfg(); 279 | assert_eq!(config.callback_url(), "http://local.example.com:8080/oauth"); 280 | } 281 | 282 | #[test] 283 | fn test_callback_url_tls() { 284 | let config = create_cfg_tls(); 285 | assert_eq!( 286 | config.callback_url(), 287 | "https://local.example.com:8080/oauth" 288 | ); 289 | } 290 | 291 | #[test] 292 | fn test_token_url() { 293 | let config = create_cfg(); 294 | assert_eq!(config.token_url(), "base_url/token"); 295 | } 296 | 297 | #[test] 298 | fn test_authorize_url() { 299 | let config = create_cfg(); 300 | assert_eq!(config.authorize_url(), "base_url/authorize"); 301 | } 302 | 303 | #[test] 304 | fn server_with_tls() { 305 | let server = Server { 306 | addr: "0.0.0.0:443".to_string(), 307 | tls: Some(Tls { 308 | cert: "cert".to_string(), 309 | key: "key".to_string(), 310 | }), 311 | }; 312 | 313 | assert!(server.tls.is_some()); 314 | } 315 | 316 | #[test] 317 | fn server_without_tls() { 318 | let server = Server { 319 | addr: "0.0.0.0:443".to_string(), 320 | tls: None, 321 | }; 322 | 323 | assert!(server.tls.is_none()); 324 | } 325 | 326 | #[test] 327 | fn tls_struct_holds_certificate_and_key() { 328 | let tls = Tls { 329 | cert: "certificate".to_string(), 330 | key: "key".to_string(), 331 | }; 332 | 333 | assert_eq!(tls.cert, "certificate"); 334 | assert_eq!(tls.key, "key"); 335 | } 336 | } 337 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/src/handlers/data.rs: -------------------------------------------------------------------------------- 1 | use super::HtmlTemplate; 2 | use crate::config::Configuration; 3 | use askama::Template; 4 | use axum::extract::{Query, State}; 5 | use axum::response::IntoResponse; 6 | use log::{debug, error, info}; 7 | use serde_derive::{Deserialize, Serialize}; 8 | 9 | /// AccountData represents the account data of a user 10 | #[derive(Serialize, Deserialize, Debug, Clone)] 11 | pub struct AccountData { 12 | pub puuid: String, 13 | #[serde(alias = "gameName")] 14 | pub game_name: String, 15 | #[serde(alias = "tagLine")] 16 | pub tag_line: String, 17 | } 18 | 19 | /// Implement the Display trait for AccountData 20 | /// This allows us to print the AccountData struct in a readable format 21 | impl std::fmt::Display for AccountData { 22 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 23 | let j = serde_json::to_string(&self).expect("error serializing json"); 24 | write!(f, "{}", j) 25 | } 26 | } 27 | 28 | /// This ChampionRotationData struct represents the champion rotation data 29 | #[derive(Serialize, Deserialize, Debug, Clone)] 30 | pub struct ChampionRotationData { 31 | #[serde(alias = "freeChampionIds")] 32 | pub free_champion_ids: Vec, 33 | #[serde(alias = "freeChampionIdsForNewPlayers")] 34 | pub free_champion_ids_for_new_players: Vec, 35 | #[serde(alias = "maxNewPlayerLevel")] 36 | pub max_new_player_level: usize, 37 | } 38 | 39 | /// Implement the Display trait for ChampionRotationData 40 | /// This allows us to print the ChampionRotationData struct in a readable format (JSON) 41 | impl std::fmt::Display for ChampionRotationData { 42 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 43 | let j = serde_json::to_string(&self).expect("error serializing json"); 44 | write!(f, "{}", j) 45 | } 46 | } 47 | 48 | /// Fetches the account data for a user. 49 | /// 50 | /// This function sends a GET request to the provided URL with the provided token as the Authorization header. 51 | /// If the request is successful, it deserializes the response into an `AccountData` struct and returns it. 52 | /// If the request fails, it logs the error and returns a string describing the error. 53 | /// 54 | /// # Arguments 55 | /// * `url` - A string slice that holds the URL for the request. 56 | /// * `token` - A string slice that holds the Authorization token for the request. 57 | /// 58 | /// # Returns 59 | /// This function returns a `Result` that contains an `AccountData` struct if the request is successful, 60 | /// or a string describing the error if the request fails. 61 | /// 62 | /// # Example 63 | /// ``` 64 | /// let url = "https://americas.api.riotgames.com/riot/account/v1/accounts/me"; 65 | /// let token = "my_token"; 66 | /// let account_data = account_data(url, token); 67 | /// match account_data { 68 | /// Ok(data) => println!("Account data: {:?}", data), 69 | /// Err(e) => println!("An error occurred: {}", e), 70 | /// } 71 | /// ``` 72 | fn account_data(url: &str, token: &str) -> core::result::Result { 73 | debug!("requesting account data"); 74 | match ureq::get(url) 75 | .set("Authorization", format!("Bearer {token}").as_str()) 76 | .call() 77 | { 78 | Ok(res) => { 79 | debug!("successfully requested account data"); 80 | Ok(serde_json::from_str(res.into_string().unwrap().as_mut_str()).unwrap()) 81 | } 82 | Err(e) => { 83 | error!("error getting account data: {e}"); 84 | Err(e.to_string()) 85 | } 86 | } 87 | } 88 | 89 | /// Fetches the champion rotation data. 90 | /// 91 | /// This function sends a GET request to the provided URL with the provided token as the `X-Riot-Token` header. 92 | /// If the request is successful, it deserializes the response into a `ChampionRotationData` struct and returns it. 93 | /// If the request fails, it logs the error and returns a string describing the error. 94 | /// 95 | /// # Arguments 96 | /// * `url` - A `String` that holds the URL for the request. 97 | /// * `token` - A `String` that holds the `X-Riot-Token` for the request. 98 | /// 99 | /// # Returns 100 | /// This function returns a `Result` that contains a `ChampionRotationData` struct if the request is successful, 101 | /// or a `String` describing the error if the request fails. 102 | /// 103 | /// # Example 104 | /// ``` 105 | /// let url = "https://na1.api.riotgames.com/lol/platform/v3/champion-rotations"; 106 | /// let token = "my_token"; 107 | /// let champion_rotation_data = champion_rotation_data(url, token); 108 | /// match champion_rotation_data { 109 | /// Ok(data) => println!("Champion rotation data: {:?}", data), 110 | /// Err(e) => println!("An error occurred: {}", e), 111 | /// } 112 | /// ``` 113 | fn champion_rotation_data( 114 | url: &str, 115 | token: &str, 116 | ) -> core::result::Result { 117 | debug!("requesting champion rotation data"); 118 | match ureq::get(url).set("X-Riot-Token", token).call() { 119 | Ok(res) => { 120 | debug!("successfully requested champion rotation data"); 121 | Ok(serde_json::from_str(res.into_string().unwrap().as_mut_str()).unwrap()) 122 | } 123 | Err(e) => { 124 | error!("error getting champion data: {e}"); 125 | Err(e.to_string()) 126 | } 127 | } 128 | } 129 | 130 | /// Represents a request containing an access token. 131 | /// 132 | /// This struct is used to deserialize requests where the client provides an access token 133 | /// obtained after authenticating with an OAuth provider. The access token is then used 134 | /// to authorize requests to protected resources. 135 | #[derive(Serialize, Deserialize, Clone, Debug)] 136 | pub struct Request { 137 | /// The access token that was given to us after the user authenticated with the 138 | /// provider. This token is used to authenticate requests made to the API. 139 | pub access_token: String, 140 | } 141 | 142 | /// Represents the response sent to the client for data requests. 143 | /// 144 | /// This struct contains both account data and champion rotation data, serialized into JSON 145 | /// before being returned to the client. It is used as the response body for requests to the 146 | /// data endpoint, providing the client with the requested information in a structured format. 147 | #[derive(Serialize, Deserialize, Template, Clone)] 148 | #[template(path = "data.html")] 149 | pub struct Response { 150 | /// The account data retrieved for the user. 151 | /// Contains information such as the player's unique identifier, game name, and tag line. 152 | pub account: AccountData, 153 | /// A serialized JSON string of the account data. 154 | /// This is a string representation of the `account` field, provided for convenience. 155 | pub account_data: String, 156 | /// The champion rotation data retrieved from the game server. 157 | /// Contains information about the current set of champions available for free play. 158 | pub champion_rotation: ChampionRotationData, 159 | /// A serialized JSON string of the champion rotation data. 160 | /// This is a string representation of the `champion_rotation` field, provided for convenience. 161 | pub champion_rotation_data: String, 162 | /// An optional message that can be included in the response. 163 | /// This field can be used to convey additional information to the client, such as error messages or notices. 164 | pub message: String, 165 | } 166 | 167 | /// Handles data requests by fetching account and champion rotation data. 168 | /// 169 | /// This asynchronous function acts as a handler for incoming data requests. It first checks if the provided 170 | /// access token is empty, returning an error if so. If the access token is present, it proceeds to fetch 171 | /// both account data and champion rotation data using the provided access token and configuration settings. 172 | /// Upon successful retrieval of both data sets, it constructs a `Response` object containing the fetched data 173 | /// and returns it wrapped in an `HtmlTemplate` for rendering. 174 | /// 175 | /// # Arguments 176 | /// * `query` - Extracted query parameters from the request, containing the access token. 177 | /// * `cfg` - Application configuration state, containing URLs and tokens for data fetching. 178 | /// 179 | /// # Returns 180 | /// A result wrapped in `impl IntoResponse`, which on success contains an `HtmlTemplate` with the fetched data, 181 | /// or an error string if the access token is missing or data fetching fails. 182 | /// 183 | /// # Errors 184 | /// Returns an error if the access token is empty or if there is an issue fetching the account or champion rotation data. 185 | /// 186 | pub async fn handle( 187 | Query(query): Query, 188 | State(cfg): State, 189 | ) -> impl IntoResponse { 190 | if query.access_token.is_empty() { 191 | return Err("unauthorized".to_string()); 192 | } 193 | 194 | info!("☁️ handling data request"); 195 | 196 | // Fetch champion rotation data using the provided access token. This operation may block the thread. 197 | let champion_data = champion_rotation_data(&cfg.api.urls.champion_data, &cfg.api.token) 198 | .map_err(|e| format!("{:?}", e))?; 199 | 200 | // Fetch account data using the provided access token. This operation may block the thread. 201 | let acct_data = account_data(&cfg.api.urls.account_data, &query.access_token) 202 | .map_err(|e| format!("{:?}", e))?; 203 | 204 | info!("☁️ completed handling data request"); 205 | 206 | // Create a `Response` object with the account and champion rotation data. 207 | Ok(HtmlTemplate(Response { 208 | account: acct_data.clone(), 209 | account_data: acct_data.clone().to_string(), 210 | champion_rotation: champion_data.clone(), 211 | champion_rotation_data: champion_data.clone().to_string(), 212 | message: "".to_string(), 213 | })) 214 | } 215 | 216 | #[cfg(test)] 217 | mod tests { 218 | use crate::config::{Api, Configuration, Rso, Tls, Urls}; 219 | use crate::handlers::data::{account_data, champion_rotation_data}; 220 | 221 | fn create_cfg_api_url(url: String) -> Configuration { 222 | Configuration { 223 | server: crate::config::Server { 224 | addr: "0.0.0.0:443".to_string(), 225 | tls: Some(Tls { 226 | cert: "cert".to_string(), 227 | key: "key".to_string(), 228 | }), 229 | }, 230 | api: Api { 231 | token: "token".to_string(), 232 | urls: Urls { 233 | account_data: url.clone(), 234 | champion_data: url.clone(), 235 | }, 236 | }, 237 | rso: Rso { 238 | base_url: "base_url".to_string(), 239 | callback_host: "local.example.com:8080".to_string(), 240 | client_id: "client_id".to_string(), 241 | client_secret: "client_secret".to_string(), 242 | }, 243 | } 244 | } 245 | 246 | #[test] 247 | fn account_data_returns_expected_result() { 248 | let api = mock::ApiProvider::new(); 249 | let cfg = create_cfg_api_url(api.server.url("/riot/account/v1/accounts/me").to_string()); 250 | let res = account_data(&cfg.api.urls.account_data, "token"); 251 | assert_eq!(false, res.is_err()); 252 | } 253 | 254 | #[test] 255 | fn account_data_handles_error() { 256 | let api = mock::ApiProvider::new(); 257 | let cfg = create_cfg_api_url(api.server.url("/riot/account/v1/accounts/me").to_string()); 258 | let res = account_data(&cfg.api.urls.account_data, ""); 259 | 260 | assert_eq!(true, res.is_err()); 261 | } 262 | 263 | #[tokio::test] 264 | async fn champion_rotation_data_returns_expected_result() { 265 | let api = mock::ApiProvider::new(); 266 | let cfg = create_cfg_api_url( 267 | api.server 268 | .url("/lol/platform/v3/champion-rotations") 269 | .to_string(), 270 | ); 271 | let res = champion_rotation_data(&cfg.api.urls.champion_data, "token"); 272 | assert_eq!(false, res.is_err()); 273 | } 274 | 275 | #[tokio::test] 276 | async fn champion_rotation_data_handles_error() { 277 | let api = mock::ApiProvider::new(); 278 | let cfg = create_cfg_api_url( 279 | api.server 280 | .url("/lol/platform/v3/champion-rotations") 281 | .to_string(), 282 | ); 283 | let res = champion_rotation_data(&cfg.api.urls.champion_data, ""); 284 | assert_eq!(true, res.is_err()); 285 | } 286 | } 287 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/python/poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "anyio" 3 | version = "3.6.1" 4 | description = "High level compatibility layer for multiple asynchronous event loop implementations" 5 | category = "main" 6 | optional = false 7 | python-versions = ">=3.6.2" 8 | 9 | [package.dependencies] 10 | idna = ">=2.8" 11 | sniffio = ">=1.1" 12 | 13 | [package.extras] 14 | doc = ["packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] 15 | test = ["contextlib2", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (<0.15)", "uvloop (>=0.15)"] 16 | trio = ["trio (>=0.16)"] 17 | 18 | [[package]] 19 | name = "appnope" 20 | version = "0.1.3" 21 | description = "Disable App Nap on macOS >= 10.9" 22 | category = "dev" 23 | optional = false 24 | python-versions = "*" 25 | 26 | [[package]] 27 | name = "asttokens" 28 | version = "2.0.8" 29 | description = "Annotate AST trees with source code positions" 30 | category = "dev" 31 | optional = false 32 | python-versions = "*" 33 | 34 | [package.dependencies] 35 | six = "*" 36 | 37 | [package.extras] 38 | test = ["astroid (<=2.5.3)", "pytest"] 39 | 40 | [[package]] 41 | name = "backcall" 42 | version = "0.2.0" 43 | description = "Specifications for callback functions passed in to an API" 44 | category = "dev" 45 | optional = false 46 | python-versions = "*" 47 | 48 | [[package]] 49 | name = "certifi" 50 | version = "2022.9.14" 51 | description = "Python package for providing Mozilla's CA Bundle." 52 | category = "main" 53 | optional = false 54 | python-versions = ">=3.6" 55 | 56 | [[package]] 57 | name = "charset-normalizer" 58 | version = "2.1.1" 59 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 60 | category = "main" 61 | optional = false 62 | python-versions = ">=3.6.0" 63 | 64 | [package.extras] 65 | unicode_backport = ["unicodedata2"] 66 | 67 | [[package]] 68 | name = "click" 69 | version = "8.1.3" 70 | description = "Composable command line interface toolkit" 71 | category = "main" 72 | optional = false 73 | python-versions = ">=3.7" 74 | 75 | [package.dependencies] 76 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 77 | 78 | [[package]] 79 | name = "colorama" 80 | version = "0.4.5" 81 | description = "Cross-platform colored terminal text." 82 | category = "main" 83 | optional = false 84 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 85 | 86 | [[package]] 87 | name = "decorator" 88 | version = "5.1.1" 89 | description = "Decorators for Humans" 90 | category = "dev" 91 | optional = false 92 | python-versions = ">=3.5" 93 | 94 | [[package]] 95 | name = "executing" 96 | version = "1.0.0" 97 | description = "Get the currently executing AST node of a frame, and other information" 98 | category = "dev" 99 | optional = false 100 | python-versions = "*" 101 | 102 | [[package]] 103 | name = "fastapi" 104 | version = "0.85.0" 105 | description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" 106 | category = "main" 107 | optional = false 108 | python-versions = ">=3.7" 109 | 110 | [package.dependencies] 111 | pydantic = ">=1.6.2,<1.7 || >1.7,<1.7.1 || >1.7.1,<1.7.2 || >1.7.2,<1.7.3 || >1.7.3,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0" 112 | starlette = "0.20.4" 113 | 114 | [package.extras] 115 | all = ["email-validator (>=1.1.1,<2.0.0)", "itsdangerous (>=1.1.0,<3.0.0)", "jinja2 (>=2.11.2,<4.0.0)", "orjson (>=3.2.1,<4.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "pyyaml (>=5.3.1,<7.0.0)", "requests (>=2.24.0,<3.0.0)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)", "uvicorn[standard] (>=0.12.0,<0.19.0)"] 116 | dev = ["autoflake (>=1.4.0,<2.0.0)", "flake8 (>=3.8.3,<6.0.0)", "pre-commit (>=2.17.0,<3.0.0)", "uvicorn[standard] (>=0.12.0,<0.19.0)"] 117 | doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pyyaml (>=5.3.1,<7.0.0)", "typer (>=0.4.1,<0.7.0)"] 118 | test = ["anyio[trio] (>=3.2.1,<4.0.0)", "black (==22.8.0)", "databases[sqlite] (>=0.3.2,<0.7.0)", "email-validator (>=1.1.1,<2.0.0)", "flake8 (>=3.8.3,<6.0.0)", "flask (>=1.1.2,<3.0.0)", "httpx (>=0.23.0,<0.24.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.971)", "orjson (>=3.2.1,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "peewee (>=3.13.3,<4.0.0)", "pytest (>=7.1.3,<8.0.0)", "pytest-cov (>=2.12.0,<4.0.0)", "python-jose[cryptography] (>=3.3.0,<4.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "pyyaml (>=5.3.1,<7.0.0)", "requests (>=2.24.0,<3.0.0)", "sqlalchemy (>=1.3.18,<1.5.0)", "types-orjson (==3.6.2)", "types-ujson (==5.4.0)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)"] 119 | 120 | [[package]] 121 | name = "h11" 122 | version = "0.13.0" 123 | description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" 124 | category = "main" 125 | optional = false 126 | python-versions = ">=3.6" 127 | 128 | [[package]] 129 | name = "idna" 130 | version = "3.4" 131 | description = "Internationalized Domain Names in Applications (IDNA)" 132 | category = "main" 133 | optional = false 134 | python-versions = ">=3.5" 135 | 136 | [[package]] 137 | name = "ipdb" 138 | version = "0.13.9" 139 | description = "IPython-enabled pdb" 140 | category = "dev" 141 | optional = false 142 | python-versions = ">=2.7" 143 | 144 | [package.dependencies] 145 | decorator = {version = "*", markers = "python_version > \"3.6\""} 146 | ipython = {version = ">=7.17.0", markers = "python_version > \"3.6\""} 147 | toml = {version = ">=0.10.2", markers = "python_version > \"3.6\""} 148 | 149 | [[package]] 150 | name = "ipython" 151 | version = "8.5.0" 152 | description = "IPython: Productive Interactive Computing" 153 | category = "dev" 154 | optional = false 155 | python-versions = ">=3.8" 156 | 157 | [package.dependencies] 158 | appnope = {version = "*", markers = "sys_platform == \"darwin\""} 159 | backcall = "*" 160 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 161 | decorator = "*" 162 | jedi = ">=0.16" 163 | matplotlib-inline = "*" 164 | pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} 165 | pickleshare = "*" 166 | prompt-toolkit = ">3.0.1,<3.1.0" 167 | pygments = ">=2.4.0" 168 | stack-data = "*" 169 | traitlets = ">=5" 170 | 171 | [package.extras] 172 | all = ["Sphinx (>=1.3)", "black", "curio", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.19)", "pandas", "pytest (<7.1)", "pytest-asyncio", "qtconsole", "testpath", "trio"] 173 | black = ["black"] 174 | doc = ["Sphinx (>=1.3)"] 175 | kernel = ["ipykernel"] 176 | nbconvert = ["nbconvert"] 177 | nbformat = ["nbformat"] 178 | notebook = ["ipywidgets", "notebook"] 179 | parallel = ["ipyparallel"] 180 | qtconsole = ["qtconsole"] 181 | test = ["pytest (<7.1)", "pytest-asyncio", "testpath"] 182 | test_extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.19)", "pandas", "pytest (<7.1)", "pytest-asyncio", "testpath", "trio"] 183 | 184 | [[package]] 185 | name = "jedi" 186 | version = "0.18.1" 187 | description = "An autocompletion tool for Python that can be used for text editors." 188 | category = "dev" 189 | optional = false 190 | python-versions = ">=3.6" 191 | 192 | [package.dependencies] 193 | parso = ">=0.8.0,<0.9.0" 194 | 195 | [package.extras] 196 | qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] 197 | testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<7.0.0)"] 198 | 199 | [[package]] 200 | name = "matplotlib-inline" 201 | version = "0.1.6" 202 | description = "Inline Matplotlib backend for Jupyter" 203 | category = "dev" 204 | optional = false 205 | python-versions = ">=3.5" 206 | 207 | [package.dependencies] 208 | traitlets = "*" 209 | 210 | [[package]] 211 | name = "parso" 212 | version = "0.8.3" 213 | description = "A Python Parser" 214 | category = "dev" 215 | optional = false 216 | python-versions = ">=3.6" 217 | 218 | [package.extras] 219 | qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] 220 | testing = ["docopt", "pytest (<6.0.0)"] 221 | 222 | [[package]] 223 | name = "pexpect" 224 | version = "4.8.0" 225 | description = "Pexpect allows easy control of interactive console applications." 226 | category = "dev" 227 | optional = false 228 | python-versions = "*" 229 | 230 | [package.dependencies] 231 | ptyprocess = ">=0.5" 232 | 233 | [[package]] 234 | name = "pickleshare" 235 | version = "0.7.5" 236 | description = "Tiny 'shelve'-like database with concurrency support" 237 | category = "dev" 238 | optional = false 239 | python-versions = "*" 240 | 241 | [[package]] 242 | name = "prompt-toolkit" 243 | version = "3.0.31" 244 | description = "Library for building powerful interactive command lines in Python" 245 | category = "dev" 246 | optional = false 247 | python-versions = ">=3.6.2" 248 | 249 | [package.dependencies] 250 | wcwidth = "*" 251 | 252 | [[package]] 253 | name = "ptyprocess" 254 | version = "0.7.0" 255 | description = "Run a subprocess in a pseudo terminal" 256 | category = "dev" 257 | optional = false 258 | python-versions = "*" 259 | 260 | [[package]] 261 | name = "pure-eval" 262 | version = "0.2.2" 263 | description = "Safely evaluate AST nodes without side effects" 264 | category = "dev" 265 | optional = false 266 | python-versions = "*" 267 | 268 | [package.extras] 269 | tests = ["pytest"] 270 | 271 | [[package]] 272 | name = "pydantic" 273 | version = "1.10.2" 274 | description = "Data validation and settings management using python type hints" 275 | category = "main" 276 | optional = false 277 | python-versions = ">=3.7" 278 | 279 | [package.dependencies] 280 | typing-extensions = ">=4.1.0" 281 | 282 | [package.extras] 283 | dotenv = ["python-dotenv (>=0.10.4)"] 284 | email = ["email-validator (>=1.0.3)"] 285 | 286 | [[package]] 287 | name = "pygments" 288 | version = "2.13.0" 289 | description = "Pygments is a syntax highlighting package written in Python." 290 | category = "dev" 291 | optional = false 292 | python-versions = ">=3.6" 293 | 294 | [package.extras] 295 | plugins = ["importlib-metadata"] 296 | 297 | [[package]] 298 | name = "python-dotenv" 299 | version = "0.21.0" 300 | description = "Read key-value pairs from a .env file and set them as environment variables" 301 | category = "main" 302 | optional = false 303 | python-versions = ">=3.7" 304 | 305 | [package.extras] 306 | cli = ["click (>=5.0)"] 307 | 308 | [[package]] 309 | name = "requests" 310 | version = "2.28.1" 311 | description = "Python HTTP for Humans." 312 | category = "main" 313 | optional = false 314 | python-versions = ">=3.7, <4" 315 | 316 | [package.dependencies] 317 | certifi = ">=2017.4.17" 318 | charset-normalizer = ">=2,<3" 319 | idna = ">=2.5,<4" 320 | urllib3 = ">=1.21.1,<1.27" 321 | 322 | [package.extras] 323 | socks = ["PySocks (>=1.5.6,!=1.5.7)"] 324 | use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] 325 | 326 | [[package]] 327 | name = "six" 328 | version = "1.16.0" 329 | description = "Python 2 and 3 compatibility utilities" 330 | category = "dev" 331 | optional = false 332 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 333 | 334 | [[package]] 335 | name = "sniffio" 336 | version = "1.3.0" 337 | description = "Sniff out which async library your code is running under" 338 | category = "main" 339 | optional = false 340 | python-versions = ">=3.7" 341 | 342 | [[package]] 343 | name = "stack-data" 344 | version = "0.5.0" 345 | description = "Extract data from python stack frames and tracebacks for informative displays" 346 | category = "dev" 347 | optional = false 348 | python-versions = "*" 349 | 350 | [package.dependencies] 351 | asttokens = "*" 352 | executing = "*" 353 | pure-eval = "*" 354 | 355 | [package.extras] 356 | tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] 357 | 358 | [[package]] 359 | name = "starlette" 360 | version = "0.20.4" 361 | description = "The little ASGI library that shines." 362 | category = "main" 363 | optional = false 364 | python-versions = ">=3.7" 365 | 366 | [package.dependencies] 367 | anyio = ">=3.4.0,<5" 368 | 369 | [package.extras] 370 | full = ["itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests"] 371 | 372 | [[package]] 373 | name = "toml" 374 | version = "0.10.2" 375 | description = "Python Library for Tom's Obvious, Minimal Language" 376 | category = "dev" 377 | optional = false 378 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 379 | 380 | [[package]] 381 | name = "traitlets" 382 | version = "5.4.0" 383 | description = "" 384 | category = "dev" 385 | optional = false 386 | python-versions = ">=3.7" 387 | 388 | [package.extras] 389 | test = ["pre-commit", "pytest"] 390 | 391 | [[package]] 392 | name = "typing-extensions" 393 | version = "4.3.0" 394 | description = "Backported and Experimental Type Hints for Python 3.7+" 395 | category = "main" 396 | optional = false 397 | python-versions = ">=3.7" 398 | 399 | [[package]] 400 | name = "urllib3" 401 | version = "1.26.12" 402 | description = "HTTP library with thread-safe connection pooling, file post, and more." 403 | category = "main" 404 | optional = false 405 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" 406 | 407 | [package.extras] 408 | brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] 409 | secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] 410 | socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] 411 | 412 | [[package]] 413 | name = "uvicorn" 414 | version = "0.18.3" 415 | description = "The lightning-fast ASGI server." 416 | category = "main" 417 | optional = false 418 | python-versions = ">=3.7" 419 | 420 | [package.dependencies] 421 | click = ">=7.0" 422 | h11 = ">=0.8" 423 | 424 | [package.extras] 425 | standard = ["colorama (>=0.4)", "httptools (>=0.4.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.0)"] 426 | 427 | [[package]] 428 | name = "wcwidth" 429 | version = "0.2.5" 430 | description = "Measures the displayed width of unicode strings in a terminal" 431 | category = "dev" 432 | optional = false 433 | python-versions = "*" 434 | 435 | [metadata] 436 | lock-version = "1.1" 437 | python-versions = "^3.10" 438 | content-hash = "bdbfa53c82795389c479f684538eb241eee9b0b0b48874bfd87224e193ff0891" 439 | 440 | [metadata.files] 441 | anyio = [ 442 | {file = "anyio-3.6.1-py3-none-any.whl", hash = "sha256:cb29b9c70620506a9a8f87a309591713446953302d7d995344d0d7c6c0c9a7be"}, 443 | {file = "anyio-3.6.1.tar.gz", hash = "sha256:413adf95f93886e442aea925f3ee43baa5a765a64a0f52c6081894f9992fdd0b"}, 444 | ] 445 | appnope = [ 446 | {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"}, 447 | {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"}, 448 | ] 449 | asttokens = [ 450 | {file = "asttokens-2.0.8-py2.py3-none-any.whl", hash = "sha256:e3305297c744ae53ffa032c45dc347286165e4ffce6875dc662b205db0623d86"}, 451 | {file = "asttokens-2.0.8.tar.gz", hash = "sha256:c61e16246ecfb2cde2958406b4c8ebc043c9e6d73aaa83c941673b35e5d3a76b"}, 452 | ] 453 | backcall = [ 454 | {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, 455 | {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, 456 | ] 457 | certifi = [ 458 | {file = "certifi-2022.9.14-py3-none-any.whl", hash = "sha256:e232343de1ab72c2aa521b625c80f699e356830fd0e2c620b465b304b17b0516"}, 459 | {file = "certifi-2022.9.14.tar.gz", hash = "sha256:36973885b9542e6bd01dea287b2b4b3b21236307c56324fcc3f1160f2d655ed5"}, 460 | ] 461 | charset-normalizer = [ 462 | {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, 463 | {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, 464 | ] 465 | click = [ 466 | {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, 467 | {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, 468 | ] 469 | colorama = [ 470 | {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, 471 | {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, 472 | ] 473 | decorator = [ 474 | {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, 475 | {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, 476 | ] 477 | executing = [ 478 | {file = "executing-1.0.0-py2.py3-none-any.whl", hash = "sha256:550d581b497228b572235e633599133eeee67073c65914ca346100ad56775349"}, 479 | {file = "executing-1.0.0.tar.gz", hash = "sha256:98daefa9d1916a4f0d944880d5aeaf079e05585689bebd9ff9b32e31dd5e1017"}, 480 | ] 481 | fastapi = [ 482 | {file = "fastapi-0.85.0-py3-none-any.whl", hash = "sha256:1803d962f169dc9f8dde54a64b22eb16f6d81573f54401971f90f0a67234a8b4"}, 483 | {file = "fastapi-0.85.0.tar.gz", hash = "sha256:bb219cfafd0d2ccf8f32310c9a257a06b0210bd8e2a03706a6f5a9f9f1416878"}, 484 | ] 485 | h11 = [ 486 | {file = "h11-0.13.0-py3-none-any.whl", hash = "sha256:8ddd78563b633ca55346c8cd41ec0af27d3c79931828beffb46ce70a379e7442"}, 487 | {file = "h11-0.13.0.tar.gz", hash = "sha256:70813c1135087a248a4d38cc0e1a0181ffab2188141a93eaf567940c3957ff06"}, 488 | ] 489 | idna = [ 490 | {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, 491 | {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, 492 | ] 493 | ipdb = [ 494 | {file = "ipdb-0.13.9.tar.gz", hash = "sha256:951bd9a64731c444fd907a5ce268543020086a697f6be08f7cc2c9a752a278c5"}, 495 | ] 496 | ipython = [ 497 | {file = "ipython-8.5.0-py3-none-any.whl", hash = "sha256:6f090e29ab8ef8643e521763a4f1f39dc3914db643122b1e9d3328ff2e43ada2"}, 498 | {file = "ipython-8.5.0.tar.gz", hash = "sha256:097bdf5cd87576fd066179c9f7f208004f7a6864ee1b20f37d346c0bcb099f84"}, 499 | ] 500 | jedi = [ 501 | {file = "jedi-0.18.1-py2.py3-none-any.whl", hash = "sha256:637c9635fcf47945ceb91cd7f320234a7be540ded6f3e99a50cb6febdfd1ba8d"}, 502 | {file = "jedi-0.18.1.tar.gz", hash = "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab"}, 503 | ] 504 | matplotlib-inline = [ 505 | {file = "matplotlib-inline-0.1.6.tar.gz", hash = "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304"}, 506 | {file = "matplotlib_inline-0.1.6-py3-none-any.whl", hash = "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311"}, 507 | ] 508 | parso = [ 509 | {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, 510 | {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, 511 | ] 512 | pexpect = [ 513 | {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, 514 | {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, 515 | ] 516 | pickleshare = [ 517 | {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, 518 | {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, 519 | ] 520 | prompt-toolkit = [ 521 | {file = "prompt_toolkit-3.0.31-py3-none-any.whl", hash = "sha256:9696f386133df0fc8ca5af4895afe5d78f5fcfe5258111c2a79a1c3e41ffa96d"}, 522 | {file = "prompt_toolkit-3.0.31.tar.gz", hash = "sha256:9ada952c9d1787f52ff6d5f3484d0b4df8952787c087edf6a1f7c2cb1ea88148"}, 523 | ] 524 | ptyprocess = [ 525 | {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, 526 | {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, 527 | ] 528 | pure-eval = [ 529 | {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, 530 | {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, 531 | ] 532 | pydantic = [ 533 | {file = "pydantic-1.10.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb6ad4489af1bac6955d38ebcb95079a836af31e4c4f74aba1ca05bb9f6027bd"}, 534 | {file = "pydantic-1.10.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a1f5a63a6dfe19d719b1b6e6106561869d2efaca6167f84f5ab9347887d78b98"}, 535 | {file = "pydantic-1.10.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:352aedb1d71b8b0736c6d56ad2bd34c6982720644b0624462059ab29bd6e5912"}, 536 | {file = "pydantic-1.10.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19b3b9ccf97af2b7519c42032441a891a5e05c68368f40865a90eb88833c2559"}, 537 | {file = "pydantic-1.10.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e9069e1b01525a96e6ff49e25876d90d5a563bc31c658289a8772ae186552236"}, 538 | {file = "pydantic-1.10.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:355639d9afc76bcb9b0c3000ddcd08472ae75318a6eb67a15866b87e2efa168c"}, 539 | {file = "pydantic-1.10.2-cp310-cp310-win_amd64.whl", hash = "sha256:ae544c47bec47a86bc7d350f965d8b15540e27e5aa4f55170ac6a75e5f73b644"}, 540 | {file = "pydantic-1.10.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a4c805731c33a8db4b6ace45ce440c4ef5336e712508b4d9e1aafa617dc9907f"}, 541 | {file = "pydantic-1.10.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d49f3db871575e0426b12e2f32fdb25e579dea16486a26e5a0474af87cb1ab0a"}, 542 | {file = "pydantic-1.10.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37c90345ec7dd2f1bcef82ce49b6235b40f282b94d3eec47e801baf864d15525"}, 543 | {file = "pydantic-1.10.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b5ba54d026c2bd2cb769d3468885f23f43710f651688e91f5fb1edcf0ee9283"}, 544 | {file = "pydantic-1.10.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:05e00dbebbe810b33c7a7362f231893183bcc4251f3f2ff991c31d5c08240c42"}, 545 | {file = "pydantic-1.10.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2d0567e60eb01bccda3a4df01df677adf6b437958d35c12a3ac3e0f078b0ee52"}, 546 | {file = "pydantic-1.10.2-cp311-cp311-win_amd64.whl", hash = "sha256:c6f981882aea41e021f72779ce2a4e87267458cc4d39ea990729e21ef18f0f8c"}, 547 | {file = "pydantic-1.10.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4aac8e7103bf598373208f6299fa9a5cfd1fc571f2d40bf1dd1955a63d6eeb5"}, 548 | {file = "pydantic-1.10.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a7b66c3f499108b448f3f004801fcd7d7165fb4200acb03f1c2402da73ce4c"}, 549 | {file = "pydantic-1.10.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bedf309630209e78582ffacda64a21f96f3ed2e51fbf3962d4d488e503420254"}, 550 | {file = "pydantic-1.10.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9300fcbebf85f6339a02c6994b2eb3ff1b9c8c14f502058b5bf349d42447dcf5"}, 551 | {file = "pydantic-1.10.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:216f3bcbf19c726b1cc22b099dd409aa371f55c08800bcea4c44c8f74b73478d"}, 552 | {file = "pydantic-1.10.2-cp37-cp37m-win_amd64.whl", hash = "sha256:dd3f9a40c16daf323cf913593083698caee97df2804aa36c4b3175d5ac1b92a2"}, 553 | {file = "pydantic-1.10.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b97890e56a694486f772d36efd2ba31612739bc6f3caeee50e9e7e3ebd2fdd13"}, 554 | {file = "pydantic-1.10.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9cabf4a7f05a776e7793e72793cd92cc865ea0e83a819f9ae4ecccb1b8aa6116"}, 555 | {file = "pydantic-1.10.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06094d18dd5e6f2bbf93efa54991c3240964bb663b87729ac340eb5014310624"}, 556 | {file = "pydantic-1.10.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc78cc83110d2f275ec1970e7a831f4e371ee92405332ebfe9860a715f8336e1"}, 557 | {file = "pydantic-1.10.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ee433e274268a4b0c8fde7ad9d58ecba12b069a033ecc4645bb6303c062d2e9"}, 558 | {file = "pydantic-1.10.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7c2abc4393dea97a4ccbb4ec7d8658d4e22c4765b7b9b9445588f16c71ad9965"}, 559 | {file = "pydantic-1.10.2-cp38-cp38-win_amd64.whl", hash = "sha256:0b959f4d8211fc964772b595ebb25f7652da3f22322c007b6fed26846a40685e"}, 560 | {file = "pydantic-1.10.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c33602f93bfb67779f9c507e4d69451664524389546bacfe1bee13cae6dc7488"}, 561 | {file = "pydantic-1.10.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5760e164b807a48a8f25f8aa1a6d857e6ce62e7ec83ea5d5c5a802eac81bad41"}, 562 | {file = "pydantic-1.10.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6eb843dcc411b6a2237a694f5e1d649fc66c6064d02b204a7e9d194dff81eb4b"}, 563 | {file = "pydantic-1.10.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b8795290deaae348c4eba0cebb196e1c6b98bdbe7f50b2d0d9a4a99716342fe"}, 564 | {file = "pydantic-1.10.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e0bedafe4bc165ad0a56ac0bd7695df25c50f76961da29c050712596cf092d6d"}, 565 | {file = "pydantic-1.10.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2e05aed07fa02231dbf03d0adb1be1d79cabb09025dd45aa094aa8b4e7b9dcda"}, 566 | {file = "pydantic-1.10.2-cp39-cp39-win_amd64.whl", hash = "sha256:c1ba1afb396148bbc70e9eaa8c06c1716fdddabaf86e7027c5988bae2a829ab6"}, 567 | {file = "pydantic-1.10.2-py3-none-any.whl", hash = "sha256:1b6ee725bd6e83ec78b1aa32c5b1fa67a3a65badddde3976bca5fe4568f27709"}, 568 | {file = "pydantic-1.10.2.tar.gz", hash = "sha256:91b8e218852ef6007c2b98cd861601c6a09f1aa32bbbb74fab5b1c33d4a1e410"}, 569 | ] 570 | pygments = [ 571 | {file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"}, 572 | {file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"}, 573 | ] 574 | python-dotenv = [ 575 | {file = "python-dotenv-0.21.0.tar.gz", hash = "sha256:b77d08274639e3d34145dfa6c7008e66df0f04b7be7a75fd0d5292c191d79045"}, 576 | {file = "python_dotenv-0.21.0-py3-none-any.whl", hash = "sha256:1684eb44636dd462b66c3ee016599815514527ad99965de77f43e0944634a7e5"}, 577 | ] 578 | requests = [ 579 | {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, 580 | {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, 581 | ] 582 | six = [ 583 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, 584 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, 585 | ] 586 | sniffio = [ 587 | {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, 588 | {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, 589 | ] 590 | stack-data = [ 591 | {file = "stack_data-0.5.0-py3-none-any.whl", hash = "sha256:66d2ebd3d7f29047612ead465b6cae5371006a71f45037c7e2507d01367bce3b"}, 592 | {file = "stack_data-0.5.0.tar.gz", hash = "sha256:715c8855fbf5c43587b141e46cc9d9339cc0d1f8d6e0f98ed0d01c6cb974e29f"}, 593 | ] 594 | starlette = [ 595 | {file = "starlette-0.20.4-py3-none-any.whl", hash = "sha256:c0414d5a56297d37f3db96a84034d61ce29889b9eaccf65eb98a0b39441fcaa3"}, 596 | {file = "starlette-0.20.4.tar.gz", hash = "sha256:42fcf3122f998fefce3e2c5ad7e5edbf0f02cf685d646a83a08d404726af5084"}, 597 | ] 598 | toml = [ 599 | {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, 600 | {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, 601 | ] 602 | traitlets = [ 603 | {file = "traitlets-5.4.0-py3-none-any.whl", hash = "sha256:93663cc8236093d48150e2af5e2ed30fc7904a11a6195e21bab0408af4e6d6c8"}, 604 | {file = "traitlets-5.4.0.tar.gz", hash = "sha256:3f2c4e435e271592fe4390f1746ea56836e3a080f84e7833f0f801d9613fec39"}, 605 | ] 606 | typing-extensions = [ 607 | {file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"}, 608 | {file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"}, 609 | ] 610 | urllib3 = [ 611 | {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, 612 | {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"}, 613 | ] 614 | uvicorn = [ 615 | {file = "uvicorn-0.18.3-py3-none-any.whl", hash = "sha256:0abd429ebb41e604ed8d2be6c60530de3408f250e8d2d84967d85ba9e86fe3af"}, 616 | {file = "uvicorn-0.18.3.tar.gz", hash = "sha256:9a66e7c42a2a95222f76ec24a4b754c158261c4696e683b9dadc72b590e0311b"}, 617 | ] 618 | wcwidth = [ 619 | {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, 620 | {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, 621 | ] 622 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/nodejs/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rso-example-app", 3 | "version": "0.0.1", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "rso-example-app", 9 | "version": "0.0.1", 10 | "license": "ISC", 11 | "dependencies": { 12 | "dotenv": "^16.0.2", 13 | "express": "^4.17.1", 14 | "node-fetch": "^3.2.10" 15 | } 16 | }, 17 | "node_modules/accepts": { 18 | "version": "1.3.8", 19 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 20 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 21 | "dependencies": { 22 | "mime-types": "~2.1.34", 23 | "negotiator": "0.6.3" 24 | }, 25 | "engines": { 26 | "node": ">= 0.6" 27 | } 28 | }, 29 | "node_modules/array-flatten": { 30 | "version": "1.1.1", 31 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 32 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 33 | }, 34 | "node_modules/body-parser": { 35 | "version": "1.20.0", 36 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", 37 | "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", 38 | "dependencies": { 39 | "bytes": "3.1.2", 40 | "content-type": "~1.0.4", 41 | "debug": "2.6.9", 42 | "depd": "2.0.0", 43 | "destroy": "1.2.0", 44 | "http-errors": "2.0.0", 45 | "iconv-lite": "0.4.24", 46 | "on-finished": "2.4.1", 47 | "qs": "6.10.3", 48 | "raw-body": "2.5.1", 49 | "type-is": "~1.6.18", 50 | "unpipe": "1.0.0" 51 | }, 52 | "engines": { 53 | "node": ">= 0.8", 54 | "npm": "1.2.8000 || >= 1.4.16" 55 | } 56 | }, 57 | "node_modules/bytes": { 58 | "version": "3.1.2", 59 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 60 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 61 | "engines": { 62 | "node": ">= 0.8" 63 | } 64 | }, 65 | "node_modules/call-bind": { 66 | "version": "1.0.2", 67 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 68 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 69 | "dependencies": { 70 | "function-bind": "^1.1.1", 71 | "get-intrinsic": "^1.0.2" 72 | }, 73 | "funding": { 74 | "url": "https://github.com/sponsors/ljharb" 75 | } 76 | }, 77 | "node_modules/content-disposition": { 78 | "version": "0.5.4", 79 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 80 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 81 | "dependencies": { 82 | "safe-buffer": "5.2.1" 83 | }, 84 | "engines": { 85 | "node": ">= 0.6" 86 | } 87 | }, 88 | "node_modules/content-type": { 89 | "version": "1.0.4", 90 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 91 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", 92 | "engines": { 93 | "node": ">= 0.6" 94 | } 95 | }, 96 | "node_modules/cookie": { 97 | "version": "0.5.0", 98 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", 99 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", 100 | "engines": { 101 | "node": ">= 0.6" 102 | } 103 | }, 104 | "node_modules/cookie-signature": { 105 | "version": "1.0.6", 106 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 107 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 108 | }, 109 | "node_modules/data-uri-to-buffer": { 110 | "version": "4.0.0", 111 | "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", 112 | "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==", 113 | "engines": { 114 | "node": ">= 12" 115 | } 116 | }, 117 | "node_modules/debug": { 118 | "version": "2.6.9", 119 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 120 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 121 | "dependencies": { 122 | "ms": "2.0.0" 123 | } 124 | }, 125 | "node_modules/depd": { 126 | "version": "2.0.0", 127 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 128 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 129 | "engines": { 130 | "node": ">= 0.8" 131 | } 132 | }, 133 | "node_modules/destroy": { 134 | "version": "1.2.0", 135 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 136 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 137 | "engines": { 138 | "node": ">= 0.8", 139 | "npm": "1.2.8000 || >= 1.4.16" 140 | } 141 | }, 142 | "node_modules/dotenv": { 143 | "version": "16.0.2", 144 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.2.tgz", 145 | "integrity": "sha512-JvpYKUmzQhYoIFgK2MOnF3bciIZoItIIoryihy0rIA+H4Jy0FmgyKYAHCTN98P5ybGSJcIFbh6QKeJdtZd1qhA==", 146 | "engines": { 147 | "node": ">=12" 148 | } 149 | }, 150 | "node_modules/ee-first": { 151 | "version": "1.1.1", 152 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 153 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 154 | }, 155 | "node_modules/encodeurl": { 156 | "version": "1.0.2", 157 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 158 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 159 | "engines": { 160 | "node": ">= 0.8" 161 | } 162 | }, 163 | "node_modules/escape-html": { 164 | "version": "1.0.3", 165 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 166 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 167 | }, 168 | "node_modules/etag": { 169 | "version": "1.8.1", 170 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 171 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 172 | "engines": { 173 | "node": ">= 0.6" 174 | } 175 | }, 176 | "node_modules/express": { 177 | "version": "4.18.1", 178 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", 179 | "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", 180 | "dependencies": { 181 | "accepts": "~1.3.8", 182 | "array-flatten": "1.1.1", 183 | "body-parser": "1.20.0", 184 | "content-disposition": "0.5.4", 185 | "content-type": "~1.0.4", 186 | "cookie": "0.5.0", 187 | "cookie-signature": "1.0.6", 188 | "debug": "2.6.9", 189 | "depd": "2.0.0", 190 | "encodeurl": "~1.0.2", 191 | "escape-html": "~1.0.3", 192 | "etag": "~1.8.1", 193 | "finalhandler": "1.2.0", 194 | "fresh": "0.5.2", 195 | "http-errors": "2.0.0", 196 | "merge-descriptors": "1.0.1", 197 | "methods": "~1.1.2", 198 | "on-finished": "2.4.1", 199 | "parseurl": "~1.3.3", 200 | "path-to-regexp": "0.1.7", 201 | "proxy-addr": "~2.0.7", 202 | "qs": "6.10.3", 203 | "range-parser": "~1.2.1", 204 | "safe-buffer": "5.2.1", 205 | "send": "0.18.0", 206 | "serve-static": "1.15.0", 207 | "setprototypeof": "1.2.0", 208 | "statuses": "2.0.1", 209 | "type-is": "~1.6.18", 210 | "utils-merge": "1.0.1", 211 | "vary": "~1.1.2" 212 | }, 213 | "engines": { 214 | "node": ">= 0.10.0" 215 | } 216 | }, 217 | "node_modules/fetch-blob": { 218 | "version": "3.2.0", 219 | "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", 220 | "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", 221 | "funding": [ 222 | { 223 | "type": "github", 224 | "url": "https://github.com/sponsors/jimmywarting" 225 | }, 226 | { 227 | "type": "paypal", 228 | "url": "https://paypal.me/jimmywarting" 229 | } 230 | ], 231 | "dependencies": { 232 | "node-domexception": "^1.0.0", 233 | "web-streams-polyfill": "^3.0.3" 234 | }, 235 | "engines": { 236 | "node": "^12.20 || >= 14.13" 237 | } 238 | }, 239 | "node_modules/finalhandler": { 240 | "version": "1.2.0", 241 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 242 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 243 | "dependencies": { 244 | "debug": "2.6.9", 245 | "encodeurl": "~1.0.2", 246 | "escape-html": "~1.0.3", 247 | "on-finished": "2.4.1", 248 | "parseurl": "~1.3.3", 249 | "statuses": "2.0.1", 250 | "unpipe": "~1.0.0" 251 | }, 252 | "engines": { 253 | "node": ">= 0.8" 254 | } 255 | }, 256 | "node_modules/formdata-polyfill": { 257 | "version": "4.0.10", 258 | "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", 259 | "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", 260 | "dependencies": { 261 | "fetch-blob": "^3.1.2" 262 | }, 263 | "engines": { 264 | "node": ">=12.20.0" 265 | } 266 | }, 267 | "node_modules/forwarded": { 268 | "version": "0.2.0", 269 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 270 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 271 | "engines": { 272 | "node": ">= 0.6" 273 | } 274 | }, 275 | "node_modules/fresh": { 276 | "version": "0.5.2", 277 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 278 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 279 | "engines": { 280 | "node": ">= 0.6" 281 | } 282 | }, 283 | "node_modules/function-bind": { 284 | "version": "1.1.1", 285 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 286 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 287 | }, 288 | "node_modules/get-intrinsic": { 289 | "version": "1.1.3", 290 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", 291 | "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", 292 | "dependencies": { 293 | "function-bind": "^1.1.1", 294 | "has": "^1.0.3", 295 | "has-symbols": "^1.0.3" 296 | }, 297 | "funding": { 298 | "url": "https://github.com/sponsors/ljharb" 299 | } 300 | }, 301 | "node_modules/has": { 302 | "version": "1.0.3", 303 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 304 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 305 | "dependencies": { 306 | "function-bind": "^1.1.1" 307 | }, 308 | "engines": { 309 | "node": ">= 0.4.0" 310 | } 311 | }, 312 | "node_modules/has-symbols": { 313 | "version": "1.0.3", 314 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 315 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 316 | "engines": { 317 | "node": ">= 0.4" 318 | }, 319 | "funding": { 320 | "url": "https://github.com/sponsors/ljharb" 321 | } 322 | }, 323 | "node_modules/http-errors": { 324 | "version": "2.0.0", 325 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 326 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 327 | "dependencies": { 328 | "depd": "2.0.0", 329 | "inherits": "2.0.4", 330 | "setprototypeof": "1.2.0", 331 | "statuses": "2.0.1", 332 | "toidentifier": "1.0.1" 333 | }, 334 | "engines": { 335 | "node": ">= 0.8" 336 | } 337 | }, 338 | "node_modules/iconv-lite": { 339 | "version": "0.4.24", 340 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 341 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 342 | "dependencies": { 343 | "safer-buffer": ">= 2.1.2 < 3" 344 | }, 345 | "engines": { 346 | "node": ">=0.10.0" 347 | } 348 | }, 349 | "node_modules/inherits": { 350 | "version": "2.0.4", 351 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 352 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 353 | }, 354 | "node_modules/ipaddr.js": { 355 | "version": "1.9.1", 356 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 357 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 358 | "engines": { 359 | "node": ">= 0.10" 360 | } 361 | }, 362 | "node_modules/media-typer": { 363 | "version": "0.3.0", 364 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 365 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 366 | "engines": { 367 | "node": ">= 0.6" 368 | } 369 | }, 370 | "node_modules/merge-descriptors": { 371 | "version": "1.0.1", 372 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 373 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" 374 | }, 375 | "node_modules/methods": { 376 | "version": "1.1.2", 377 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 378 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 379 | "engines": { 380 | "node": ">= 0.6" 381 | } 382 | }, 383 | "node_modules/mime": { 384 | "version": "1.6.0", 385 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 386 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 387 | "bin": { 388 | "mime": "cli.js" 389 | }, 390 | "engines": { 391 | "node": ">=4" 392 | } 393 | }, 394 | "node_modules/mime-db": { 395 | "version": "1.52.0", 396 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 397 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 398 | "engines": { 399 | "node": ">= 0.6" 400 | } 401 | }, 402 | "node_modules/mime-types": { 403 | "version": "2.1.35", 404 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 405 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 406 | "dependencies": { 407 | "mime-db": "1.52.0" 408 | }, 409 | "engines": { 410 | "node": ">= 0.6" 411 | } 412 | }, 413 | "node_modules/ms": { 414 | "version": "2.0.0", 415 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 416 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 417 | }, 418 | "node_modules/negotiator": { 419 | "version": "0.6.3", 420 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 421 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 422 | "engines": { 423 | "node": ">= 0.6" 424 | } 425 | }, 426 | "node_modules/node-domexception": { 427 | "version": "1.0.0", 428 | "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", 429 | "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", 430 | "funding": [ 431 | { 432 | "type": "github", 433 | "url": "https://github.com/sponsors/jimmywarting" 434 | }, 435 | { 436 | "type": "github", 437 | "url": "https://paypal.me/jimmywarting" 438 | } 439 | ], 440 | "engines": { 441 | "node": ">=10.5.0" 442 | } 443 | }, 444 | "node_modules/node-fetch": { 445 | "version": "3.2.10", 446 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.2.10.tgz", 447 | "integrity": "sha512-MhuzNwdURnZ1Cp4XTazr69K0BTizsBroX7Zx3UgDSVcZYKF/6p0CBe4EUb/hLqmzVhl0UpYfgRljQ4yxE+iCxA==", 448 | "dependencies": { 449 | "data-uri-to-buffer": "^4.0.0", 450 | "fetch-blob": "^3.1.4", 451 | "formdata-polyfill": "^4.0.10" 452 | }, 453 | "engines": { 454 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 455 | }, 456 | "funding": { 457 | "type": "opencollective", 458 | "url": "https://opencollective.com/node-fetch" 459 | } 460 | }, 461 | "node_modules/object-inspect": { 462 | "version": "1.12.2", 463 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", 464 | "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", 465 | "funding": { 466 | "url": "https://github.com/sponsors/ljharb" 467 | } 468 | }, 469 | "node_modules/on-finished": { 470 | "version": "2.4.1", 471 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 472 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 473 | "dependencies": { 474 | "ee-first": "1.1.1" 475 | }, 476 | "engines": { 477 | "node": ">= 0.8" 478 | } 479 | }, 480 | "node_modules/parseurl": { 481 | "version": "1.3.3", 482 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 483 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 484 | "engines": { 485 | "node": ">= 0.8" 486 | } 487 | }, 488 | "node_modules/path-to-regexp": { 489 | "version": "0.1.7", 490 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 491 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" 492 | }, 493 | "node_modules/proxy-addr": { 494 | "version": "2.0.7", 495 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 496 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 497 | "dependencies": { 498 | "forwarded": "0.2.0", 499 | "ipaddr.js": "1.9.1" 500 | }, 501 | "engines": { 502 | "node": ">= 0.10" 503 | } 504 | }, 505 | "node_modules/qs": { 506 | "version": "6.10.3", 507 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", 508 | "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", 509 | "dependencies": { 510 | "side-channel": "^1.0.4" 511 | }, 512 | "engines": { 513 | "node": ">=0.6" 514 | }, 515 | "funding": { 516 | "url": "https://github.com/sponsors/ljharb" 517 | } 518 | }, 519 | "node_modules/range-parser": { 520 | "version": "1.2.1", 521 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 522 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 523 | "engines": { 524 | "node": ">= 0.6" 525 | } 526 | }, 527 | "node_modules/raw-body": { 528 | "version": "2.5.1", 529 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", 530 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", 531 | "dependencies": { 532 | "bytes": "3.1.2", 533 | "http-errors": "2.0.0", 534 | "iconv-lite": "0.4.24", 535 | "unpipe": "1.0.0" 536 | }, 537 | "engines": { 538 | "node": ">= 0.8" 539 | } 540 | }, 541 | "node_modules/safe-buffer": { 542 | "version": "5.2.1", 543 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 544 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 545 | "funding": [ 546 | { 547 | "type": "github", 548 | "url": "https://github.com/sponsors/feross" 549 | }, 550 | { 551 | "type": "patreon", 552 | "url": "https://www.patreon.com/feross" 553 | }, 554 | { 555 | "type": "consulting", 556 | "url": "https://feross.org/support" 557 | } 558 | ] 559 | }, 560 | "node_modules/safer-buffer": { 561 | "version": "2.1.2", 562 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 563 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 564 | }, 565 | "node_modules/send": { 566 | "version": "0.18.0", 567 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 568 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 569 | "dependencies": { 570 | "debug": "2.6.9", 571 | "depd": "2.0.0", 572 | "destroy": "1.2.0", 573 | "encodeurl": "~1.0.2", 574 | "escape-html": "~1.0.3", 575 | "etag": "~1.8.1", 576 | "fresh": "0.5.2", 577 | "http-errors": "2.0.0", 578 | "mime": "1.6.0", 579 | "ms": "2.1.3", 580 | "on-finished": "2.4.1", 581 | "range-parser": "~1.2.1", 582 | "statuses": "2.0.1" 583 | }, 584 | "engines": { 585 | "node": ">= 0.8.0" 586 | } 587 | }, 588 | "node_modules/send/node_modules/ms": { 589 | "version": "2.1.3", 590 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 591 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 592 | }, 593 | "node_modules/serve-static": { 594 | "version": "1.15.0", 595 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", 596 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", 597 | "dependencies": { 598 | "encodeurl": "~1.0.2", 599 | "escape-html": "~1.0.3", 600 | "parseurl": "~1.3.3", 601 | "send": "0.18.0" 602 | }, 603 | "engines": { 604 | "node": ">= 0.8.0" 605 | } 606 | }, 607 | "node_modules/setprototypeof": { 608 | "version": "1.2.0", 609 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 610 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 611 | }, 612 | "node_modules/side-channel": { 613 | "version": "1.0.4", 614 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 615 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 616 | "dependencies": { 617 | "call-bind": "^1.0.0", 618 | "get-intrinsic": "^1.0.2", 619 | "object-inspect": "^1.9.0" 620 | }, 621 | "funding": { 622 | "url": "https://github.com/sponsors/ljharb" 623 | } 624 | }, 625 | "node_modules/statuses": { 626 | "version": "2.0.1", 627 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 628 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 629 | "engines": { 630 | "node": ">= 0.8" 631 | } 632 | }, 633 | "node_modules/toidentifier": { 634 | "version": "1.0.1", 635 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 636 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 637 | "engines": { 638 | "node": ">=0.6" 639 | } 640 | }, 641 | "node_modules/type-is": { 642 | "version": "1.6.18", 643 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 644 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 645 | "dependencies": { 646 | "media-typer": "0.3.0", 647 | "mime-types": "~2.1.24" 648 | }, 649 | "engines": { 650 | "node": ">= 0.6" 651 | } 652 | }, 653 | "node_modules/unpipe": { 654 | "version": "1.0.0", 655 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 656 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 657 | "engines": { 658 | "node": ">= 0.8" 659 | } 660 | }, 661 | "node_modules/utils-merge": { 662 | "version": "1.0.1", 663 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 664 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", 665 | "engines": { 666 | "node": ">= 0.4.0" 667 | } 668 | }, 669 | "node_modules/vary": { 670 | "version": "1.1.2", 671 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 672 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 673 | "engines": { 674 | "node": ">= 0.8" 675 | } 676 | }, 677 | "node_modules/web-streams-polyfill": { 678 | "version": "3.2.1", 679 | "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", 680 | "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", 681 | "engines": { 682 | "node": ">= 8" 683 | } 684 | } 685 | }, 686 | "dependencies": { 687 | "accepts": { 688 | "version": "1.3.8", 689 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 690 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 691 | "requires": { 692 | "mime-types": "~2.1.34", 693 | "negotiator": "0.6.3" 694 | } 695 | }, 696 | "array-flatten": { 697 | "version": "1.1.1", 698 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 699 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 700 | }, 701 | "body-parser": { 702 | "version": "1.20.0", 703 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", 704 | "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", 705 | "requires": { 706 | "bytes": "3.1.2", 707 | "content-type": "~1.0.4", 708 | "debug": "2.6.9", 709 | "depd": "2.0.0", 710 | "destroy": "1.2.0", 711 | "http-errors": "2.0.0", 712 | "iconv-lite": "0.4.24", 713 | "on-finished": "2.4.1", 714 | "qs": "6.10.3", 715 | "raw-body": "2.5.1", 716 | "type-is": "~1.6.18", 717 | "unpipe": "1.0.0" 718 | } 719 | }, 720 | "bytes": { 721 | "version": "3.1.2", 722 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 723 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" 724 | }, 725 | "call-bind": { 726 | "version": "1.0.2", 727 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 728 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 729 | "requires": { 730 | "function-bind": "^1.1.1", 731 | "get-intrinsic": "^1.0.2" 732 | } 733 | }, 734 | "content-disposition": { 735 | "version": "0.5.4", 736 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 737 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 738 | "requires": { 739 | "safe-buffer": "5.2.1" 740 | } 741 | }, 742 | "content-type": { 743 | "version": "1.0.4", 744 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 745 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 746 | }, 747 | "cookie": { 748 | "version": "0.5.0", 749 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", 750 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" 751 | }, 752 | "cookie-signature": { 753 | "version": "1.0.6", 754 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 755 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 756 | }, 757 | "data-uri-to-buffer": { 758 | "version": "4.0.0", 759 | "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", 760 | "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==" 761 | }, 762 | "debug": { 763 | "version": "2.6.9", 764 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 765 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 766 | "requires": { 767 | "ms": "2.0.0" 768 | } 769 | }, 770 | "depd": { 771 | "version": "2.0.0", 772 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 773 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" 774 | }, 775 | "destroy": { 776 | "version": "1.2.0", 777 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 778 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" 779 | }, 780 | "dotenv": { 781 | "version": "16.0.2", 782 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.2.tgz", 783 | "integrity": "sha512-JvpYKUmzQhYoIFgK2MOnF3bciIZoItIIoryihy0rIA+H4Jy0FmgyKYAHCTN98P5ybGSJcIFbh6QKeJdtZd1qhA==" 784 | }, 785 | "ee-first": { 786 | "version": "1.1.1", 787 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 788 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 789 | }, 790 | "encodeurl": { 791 | "version": "1.0.2", 792 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 793 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" 794 | }, 795 | "escape-html": { 796 | "version": "1.0.3", 797 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 798 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 799 | }, 800 | "etag": { 801 | "version": "1.8.1", 802 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 803 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" 804 | }, 805 | "express": { 806 | "version": "4.18.1", 807 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", 808 | "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", 809 | "requires": { 810 | "accepts": "~1.3.8", 811 | "array-flatten": "1.1.1", 812 | "body-parser": "1.20.0", 813 | "content-disposition": "0.5.4", 814 | "content-type": "~1.0.4", 815 | "cookie": "0.5.0", 816 | "cookie-signature": "1.0.6", 817 | "debug": "2.6.9", 818 | "depd": "2.0.0", 819 | "encodeurl": "~1.0.2", 820 | "escape-html": "~1.0.3", 821 | "etag": "~1.8.1", 822 | "finalhandler": "1.2.0", 823 | "fresh": "0.5.2", 824 | "http-errors": "2.0.0", 825 | "merge-descriptors": "1.0.1", 826 | "methods": "~1.1.2", 827 | "on-finished": "2.4.1", 828 | "parseurl": "~1.3.3", 829 | "path-to-regexp": "0.1.7", 830 | "proxy-addr": "~2.0.7", 831 | "qs": "6.10.3", 832 | "range-parser": "~1.2.1", 833 | "safe-buffer": "5.2.1", 834 | "send": "0.18.0", 835 | "serve-static": "1.15.0", 836 | "setprototypeof": "1.2.0", 837 | "statuses": "2.0.1", 838 | "type-is": "~1.6.18", 839 | "utils-merge": "1.0.1", 840 | "vary": "~1.1.2" 841 | } 842 | }, 843 | "fetch-blob": { 844 | "version": "3.2.0", 845 | "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", 846 | "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", 847 | "requires": { 848 | "node-domexception": "^1.0.0", 849 | "web-streams-polyfill": "^3.0.3" 850 | } 851 | }, 852 | "finalhandler": { 853 | "version": "1.2.0", 854 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 855 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 856 | "requires": { 857 | "debug": "2.6.9", 858 | "encodeurl": "~1.0.2", 859 | "escape-html": "~1.0.3", 860 | "on-finished": "2.4.1", 861 | "parseurl": "~1.3.3", 862 | "statuses": "2.0.1", 863 | "unpipe": "~1.0.0" 864 | } 865 | }, 866 | "formdata-polyfill": { 867 | "version": "4.0.10", 868 | "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", 869 | "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", 870 | "requires": { 871 | "fetch-blob": "^3.1.2" 872 | } 873 | }, 874 | "forwarded": { 875 | "version": "0.2.0", 876 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 877 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" 878 | }, 879 | "fresh": { 880 | "version": "0.5.2", 881 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 882 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" 883 | }, 884 | "function-bind": { 885 | "version": "1.1.1", 886 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 887 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 888 | }, 889 | "get-intrinsic": { 890 | "version": "1.1.3", 891 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", 892 | "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", 893 | "requires": { 894 | "function-bind": "^1.1.1", 895 | "has": "^1.0.3", 896 | "has-symbols": "^1.0.3" 897 | } 898 | }, 899 | "has": { 900 | "version": "1.0.3", 901 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 902 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 903 | "requires": { 904 | "function-bind": "^1.1.1" 905 | } 906 | }, 907 | "has-symbols": { 908 | "version": "1.0.3", 909 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 910 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" 911 | }, 912 | "http-errors": { 913 | "version": "2.0.0", 914 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 915 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 916 | "requires": { 917 | "depd": "2.0.0", 918 | "inherits": "2.0.4", 919 | "setprototypeof": "1.2.0", 920 | "statuses": "2.0.1", 921 | "toidentifier": "1.0.1" 922 | } 923 | }, 924 | "iconv-lite": { 925 | "version": "0.4.24", 926 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 927 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 928 | "requires": { 929 | "safer-buffer": ">= 2.1.2 < 3" 930 | } 931 | }, 932 | "inherits": { 933 | "version": "2.0.4", 934 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 935 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 936 | }, 937 | "ipaddr.js": { 938 | "version": "1.9.1", 939 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 940 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 941 | }, 942 | "media-typer": { 943 | "version": "0.3.0", 944 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 945 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" 946 | }, 947 | "merge-descriptors": { 948 | "version": "1.0.1", 949 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 950 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" 951 | }, 952 | "methods": { 953 | "version": "1.1.2", 954 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 955 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" 956 | }, 957 | "mime": { 958 | "version": "1.6.0", 959 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 960 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 961 | }, 962 | "mime-db": { 963 | "version": "1.52.0", 964 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 965 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" 966 | }, 967 | "mime-types": { 968 | "version": "2.1.35", 969 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 970 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 971 | "requires": { 972 | "mime-db": "1.52.0" 973 | } 974 | }, 975 | "ms": { 976 | "version": "2.0.0", 977 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 978 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 979 | }, 980 | "negotiator": { 981 | "version": "0.6.3", 982 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 983 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" 984 | }, 985 | "node-domexception": { 986 | "version": "1.0.0", 987 | "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", 988 | "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" 989 | }, 990 | "node-fetch": { 991 | "version": "3.2.10", 992 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.2.10.tgz", 993 | "integrity": "sha512-MhuzNwdURnZ1Cp4XTazr69K0BTizsBroX7Zx3UgDSVcZYKF/6p0CBe4EUb/hLqmzVhl0UpYfgRljQ4yxE+iCxA==", 994 | "requires": { 995 | "data-uri-to-buffer": "^4.0.0", 996 | "fetch-blob": "^3.1.4", 997 | "formdata-polyfill": "^4.0.10" 998 | } 999 | }, 1000 | "object-inspect": { 1001 | "version": "1.12.2", 1002 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", 1003 | "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" 1004 | }, 1005 | "on-finished": { 1006 | "version": "2.4.1", 1007 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 1008 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 1009 | "requires": { 1010 | "ee-first": "1.1.1" 1011 | } 1012 | }, 1013 | "parseurl": { 1014 | "version": "1.3.3", 1015 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1016 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 1017 | }, 1018 | "path-to-regexp": { 1019 | "version": "0.1.7", 1020 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 1021 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" 1022 | }, 1023 | "proxy-addr": { 1024 | "version": "2.0.7", 1025 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 1026 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 1027 | "requires": { 1028 | "forwarded": "0.2.0", 1029 | "ipaddr.js": "1.9.1" 1030 | } 1031 | }, 1032 | "qs": { 1033 | "version": "6.10.3", 1034 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", 1035 | "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", 1036 | "requires": { 1037 | "side-channel": "^1.0.4" 1038 | } 1039 | }, 1040 | "range-parser": { 1041 | "version": "1.2.1", 1042 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1043 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 1044 | }, 1045 | "raw-body": { 1046 | "version": "2.5.1", 1047 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", 1048 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", 1049 | "requires": { 1050 | "bytes": "3.1.2", 1051 | "http-errors": "2.0.0", 1052 | "iconv-lite": "0.4.24", 1053 | "unpipe": "1.0.0" 1054 | } 1055 | }, 1056 | "safe-buffer": { 1057 | "version": "5.2.1", 1058 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1059 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 1060 | }, 1061 | "safer-buffer": { 1062 | "version": "2.1.2", 1063 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1064 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1065 | }, 1066 | "send": { 1067 | "version": "0.18.0", 1068 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 1069 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 1070 | "requires": { 1071 | "debug": "2.6.9", 1072 | "depd": "2.0.0", 1073 | "destroy": "1.2.0", 1074 | "encodeurl": "~1.0.2", 1075 | "escape-html": "~1.0.3", 1076 | "etag": "~1.8.1", 1077 | "fresh": "0.5.2", 1078 | "http-errors": "2.0.0", 1079 | "mime": "1.6.0", 1080 | "ms": "2.1.3", 1081 | "on-finished": "2.4.1", 1082 | "range-parser": "~1.2.1", 1083 | "statuses": "2.0.1" 1084 | }, 1085 | "dependencies": { 1086 | "ms": { 1087 | "version": "2.1.3", 1088 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1089 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 1090 | } 1091 | } 1092 | }, 1093 | "serve-static": { 1094 | "version": "1.15.0", 1095 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", 1096 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", 1097 | "requires": { 1098 | "encodeurl": "~1.0.2", 1099 | "escape-html": "~1.0.3", 1100 | "parseurl": "~1.3.3", 1101 | "send": "0.18.0" 1102 | } 1103 | }, 1104 | "setprototypeof": { 1105 | "version": "1.2.0", 1106 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 1107 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 1108 | }, 1109 | "side-channel": { 1110 | "version": "1.0.4", 1111 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 1112 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 1113 | "requires": { 1114 | "call-bind": "^1.0.0", 1115 | "get-intrinsic": "^1.0.2", 1116 | "object-inspect": "^1.9.0" 1117 | } 1118 | }, 1119 | "statuses": { 1120 | "version": "2.0.1", 1121 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 1122 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" 1123 | }, 1124 | "toidentifier": { 1125 | "version": "1.0.1", 1126 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1127 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" 1128 | }, 1129 | "type-is": { 1130 | "version": "1.6.18", 1131 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1132 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1133 | "requires": { 1134 | "media-typer": "0.3.0", 1135 | "mime-types": "~2.1.24" 1136 | } 1137 | }, 1138 | "unpipe": { 1139 | "version": "1.0.0", 1140 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1141 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" 1142 | }, 1143 | "utils-merge": { 1144 | "version": "1.0.1", 1145 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1146 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" 1147 | }, 1148 | "vary": { 1149 | "version": "1.1.2", 1150 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1151 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" 1152 | }, 1153 | "web-streams-polyfill": { 1154 | "version": "3.2.1", 1155 | "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", 1156 | "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==" 1157 | } 1158 | } 1159 | } 1160 | -------------------------------------------------------------------------------- /sample_apps/rso_sample_apps/rust/mock/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.21.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "aho-corasick" 22 | version = "1.1.3" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 25 | dependencies = [ 26 | "memchr", 27 | ] 28 | 29 | [[package]] 30 | name = "ascii-canvas" 31 | version = "3.0.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" 34 | dependencies = [ 35 | "term", 36 | ] 37 | 38 | [[package]] 39 | name = "assert-json-diff" 40 | version = "2.0.2" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12" 43 | dependencies = [ 44 | "serde", 45 | "serde_json", 46 | ] 47 | 48 | [[package]] 49 | name = "async-attributes" 50 | version = "1.1.2" 51 | source = "registry+https://github.com/rust-lang/crates.io-index" 52 | checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" 53 | dependencies = [ 54 | "quote", 55 | "syn 1.0.109", 56 | ] 57 | 58 | [[package]] 59 | name = "async-channel" 60 | version = "1.9.0" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" 63 | dependencies = [ 64 | "concurrent-queue", 65 | "event-listener 2.5.3", 66 | "futures-core", 67 | ] 68 | 69 | [[package]] 70 | name = "async-channel" 71 | version = "2.3.1" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" 74 | dependencies = [ 75 | "concurrent-queue", 76 | "event-listener-strategy 0.5.2", 77 | "futures-core", 78 | "pin-project-lite", 79 | ] 80 | 81 | [[package]] 82 | name = "async-executor" 83 | version = "1.11.0" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | checksum = "b10202063978b3351199d68f8b22c4e47e4b1b822f8d43fd862d5ea8c006b29a" 86 | dependencies = [ 87 | "async-task", 88 | "concurrent-queue", 89 | "fastrand 2.1.0", 90 | "futures-lite 2.3.0", 91 | "slab", 92 | ] 93 | 94 | [[package]] 95 | name = "async-global-executor" 96 | version = "2.4.1" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" 99 | dependencies = [ 100 | "async-channel 2.3.1", 101 | "async-executor", 102 | "async-io 2.3.2", 103 | "async-lock 3.3.0", 104 | "blocking", 105 | "futures-lite 2.3.0", 106 | "once_cell", 107 | ] 108 | 109 | [[package]] 110 | name = "async-io" 111 | version = "1.13.0" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" 114 | dependencies = [ 115 | "async-lock 2.8.0", 116 | "autocfg", 117 | "cfg-if", 118 | "concurrent-queue", 119 | "futures-lite 1.13.0", 120 | "log", 121 | "parking", 122 | "polling 2.8.0", 123 | "rustix 0.37.27", 124 | "slab", 125 | "socket2 0.4.10", 126 | "waker-fn", 127 | ] 128 | 129 | [[package]] 130 | name = "async-io" 131 | version = "2.3.2" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" 134 | dependencies = [ 135 | "async-lock 3.3.0", 136 | "cfg-if", 137 | "concurrent-queue", 138 | "futures-io", 139 | "futures-lite 2.3.0", 140 | "parking", 141 | "polling 3.7.0", 142 | "rustix 0.38.34", 143 | "slab", 144 | "tracing", 145 | "windows-sys 0.52.0", 146 | ] 147 | 148 | [[package]] 149 | name = "async-lock" 150 | version = "2.8.0" 151 | source = "registry+https://github.com/rust-lang/crates.io-index" 152 | checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" 153 | dependencies = [ 154 | "event-listener 2.5.3", 155 | ] 156 | 157 | [[package]] 158 | name = "async-lock" 159 | version = "3.3.0" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" 162 | dependencies = [ 163 | "event-listener 4.0.3", 164 | "event-listener-strategy 0.4.0", 165 | "pin-project-lite", 166 | ] 167 | 168 | [[package]] 169 | name = "async-object-pool" 170 | version = "0.1.4" 171 | source = "registry+https://github.com/rust-lang/crates.io-index" 172 | checksum = "aeb901c30ebc2fc4ab46395bbfbdba9542c16559d853645d75190c3056caf3bc" 173 | dependencies = [ 174 | "async-std", 175 | ] 176 | 177 | [[package]] 178 | name = "async-process" 179 | version = "1.8.1" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" 182 | dependencies = [ 183 | "async-io 1.13.0", 184 | "async-lock 2.8.0", 185 | "async-signal", 186 | "blocking", 187 | "cfg-if", 188 | "event-listener 3.1.0", 189 | "futures-lite 1.13.0", 190 | "rustix 0.38.34", 191 | "windows-sys 0.48.0", 192 | ] 193 | 194 | [[package]] 195 | name = "async-signal" 196 | version = "0.2.6" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "afe66191c335039c7bb78f99dc7520b0cbb166b3a1cb33a03f53d8a1c6f2afda" 199 | dependencies = [ 200 | "async-io 2.3.2", 201 | "async-lock 3.3.0", 202 | "atomic-waker", 203 | "cfg-if", 204 | "futures-core", 205 | "futures-io", 206 | "rustix 0.38.34", 207 | "signal-hook-registry", 208 | "slab", 209 | "windows-sys 0.52.0", 210 | ] 211 | 212 | [[package]] 213 | name = "async-std" 214 | version = "1.12.0" 215 | source = "registry+https://github.com/rust-lang/crates.io-index" 216 | checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" 217 | dependencies = [ 218 | "async-attributes", 219 | "async-channel 1.9.0", 220 | "async-global-executor", 221 | "async-io 1.13.0", 222 | "async-lock 2.8.0", 223 | "async-process", 224 | "crossbeam-utils", 225 | "futures-channel", 226 | "futures-core", 227 | "futures-io", 228 | "futures-lite 1.13.0", 229 | "gloo-timers", 230 | "kv-log-macro", 231 | "log", 232 | "memchr", 233 | "once_cell", 234 | "pin-project-lite", 235 | "pin-utils", 236 | "slab", 237 | "wasm-bindgen-futures", 238 | ] 239 | 240 | [[package]] 241 | name = "async-task" 242 | version = "4.7.1" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" 245 | 246 | [[package]] 247 | name = "async-trait" 248 | version = "0.1.80" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" 251 | dependencies = [ 252 | "proc-macro2", 253 | "quote", 254 | "syn 2.0.66", 255 | ] 256 | 257 | [[package]] 258 | name = "atomic-waker" 259 | version = "1.1.2" 260 | source = "registry+https://github.com/rust-lang/crates.io-index" 261 | checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" 262 | 263 | [[package]] 264 | name = "autocfg" 265 | version = "1.3.0" 266 | source = "registry+https://github.com/rust-lang/crates.io-index" 267 | checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" 268 | 269 | [[package]] 270 | name = "backtrace" 271 | version = "0.3.71" 272 | source = "registry+https://github.com/rust-lang/crates.io-index" 273 | checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" 274 | dependencies = [ 275 | "addr2line", 276 | "cc", 277 | "cfg-if", 278 | "libc", 279 | "miniz_oxide", 280 | "object", 281 | "rustc-demangle", 282 | ] 283 | 284 | [[package]] 285 | name = "base64" 286 | version = "0.21.7" 287 | source = "registry+https://github.com/rust-lang/crates.io-index" 288 | checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" 289 | 290 | [[package]] 291 | name = "basic-cookies" 292 | version = "0.1.5" 293 | source = "registry+https://github.com/rust-lang/crates.io-index" 294 | checksum = "67bd8fd42c16bdb08688243dc5f0cc117a3ca9efeeaba3a345a18a6159ad96f7" 295 | dependencies = [ 296 | "lalrpop", 297 | "lalrpop-util", 298 | "regex", 299 | ] 300 | 301 | [[package]] 302 | name = "bit-set" 303 | version = "0.5.3" 304 | source = "registry+https://github.com/rust-lang/crates.io-index" 305 | checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" 306 | dependencies = [ 307 | "bit-vec", 308 | ] 309 | 310 | [[package]] 311 | name = "bit-vec" 312 | version = "0.6.3" 313 | source = "registry+https://github.com/rust-lang/crates.io-index" 314 | checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" 315 | 316 | [[package]] 317 | name = "bitflags" 318 | version = "1.3.2" 319 | source = "registry+https://github.com/rust-lang/crates.io-index" 320 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 321 | 322 | [[package]] 323 | name = "bitflags" 324 | version = "2.5.0" 325 | source = "registry+https://github.com/rust-lang/crates.io-index" 326 | checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" 327 | 328 | [[package]] 329 | name = "blocking" 330 | version = "1.6.0" 331 | source = "registry+https://github.com/rust-lang/crates.io-index" 332 | checksum = "495f7104e962b7356f0aeb34247aca1fe7d2e783b346582db7f2904cb5717e88" 333 | dependencies = [ 334 | "async-channel 2.3.1", 335 | "async-lock 3.3.0", 336 | "async-task", 337 | "futures-io", 338 | "futures-lite 2.3.0", 339 | "piper", 340 | ] 341 | 342 | [[package]] 343 | name = "bumpalo" 344 | version = "3.16.0" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" 347 | 348 | [[package]] 349 | name = "bytes" 350 | version = "1.6.0" 351 | source = "registry+https://github.com/rust-lang/crates.io-index" 352 | checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" 353 | 354 | [[package]] 355 | name = "cc" 356 | version = "1.0.98" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" 359 | 360 | [[package]] 361 | name = "cfg-if" 362 | version = "1.0.0" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 365 | 366 | [[package]] 367 | name = "concurrent-queue" 368 | version = "2.5.0" 369 | source = "registry+https://github.com/rust-lang/crates.io-index" 370 | checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" 371 | dependencies = [ 372 | "crossbeam-utils", 373 | ] 374 | 375 | [[package]] 376 | name = "crossbeam-utils" 377 | version = "0.8.20" 378 | source = "registry+https://github.com/rust-lang/crates.io-index" 379 | checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" 380 | 381 | [[package]] 382 | name = "crunchy" 383 | version = "0.2.2" 384 | source = "registry+https://github.com/rust-lang/crates.io-index" 385 | checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" 386 | 387 | [[package]] 388 | name = "dirs-next" 389 | version = "2.0.0" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" 392 | dependencies = [ 393 | "cfg-if", 394 | "dirs-sys-next", 395 | ] 396 | 397 | [[package]] 398 | name = "dirs-sys-next" 399 | version = "0.1.2" 400 | source = "registry+https://github.com/rust-lang/crates.io-index" 401 | checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" 402 | dependencies = [ 403 | "libc", 404 | "redox_users", 405 | "winapi", 406 | ] 407 | 408 | [[package]] 409 | name = "either" 410 | version = "1.12.0" 411 | source = "registry+https://github.com/rust-lang/crates.io-index" 412 | checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" 413 | 414 | [[package]] 415 | name = "ena" 416 | version = "0.14.3" 417 | source = "registry+https://github.com/rust-lang/crates.io-index" 418 | checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" 419 | dependencies = [ 420 | "log", 421 | ] 422 | 423 | [[package]] 424 | name = "equivalent" 425 | version = "1.0.1" 426 | source = "registry+https://github.com/rust-lang/crates.io-index" 427 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 428 | 429 | [[package]] 430 | name = "errno" 431 | version = "0.3.9" 432 | source = "registry+https://github.com/rust-lang/crates.io-index" 433 | checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" 434 | dependencies = [ 435 | "libc", 436 | "windows-sys 0.52.0", 437 | ] 438 | 439 | [[package]] 440 | name = "event-listener" 441 | version = "2.5.3" 442 | source = "registry+https://github.com/rust-lang/crates.io-index" 443 | checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" 444 | 445 | [[package]] 446 | name = "event-listener" 447 | version = "3.1.0" 448 | source = "registry+https://github.com/rust-lang/crates.io-index" 449 | checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" 450 | dependencies = [ 451 | "concurrent-queue", 452 | "parking", 453 | "pin-project-lite", 454 | ] 455 | 456 | [[package]] 457 | name = "event-listener" 458 | version = "4.0.3" 459 | source = "registry+https://github.com/rust-lang/crates.io-index" 460 | checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" 461 | dependencies = [ 462 | "concurrent-queue", 463 | "parking", 464 | "pin-project-lite", 465 | ] 466 | 467 | [[package]] 468 | name = "event-listener" 469 | version = "5.3.0" 470 | source = "registry+https://github.com/rust-lang/crates.io-index" 471 | checksum = "6d9944b8ca13534cdfb2800775f8dd4902ff3fc75a50101466decadfdf322a24" 472 | dependencies = [ 473 | "concurrent-queue", 474 | "parking", 475 | "pin-project-lite", 476 | ] 477 | 478 | [[package]] 479 | name = "event-listener-strategy" 480 | version = "0.4.0" 481 | source = "registry+https://github.com/rust-lang/crates.io-index" 482 | checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" 483 | dependencies = [ 484 | "event-listener 4.0.3", 485 | "pin-project-lite", 486 | ] 487 | 488 | [[package]] 489 | name = "event-listener-strategy" 490 | version = "0.5.2" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" 493 | dependencies = [ 494 | "event-listener 5.3.0", 495 | "pin-project-lite", 496 | ] 497 | 498 | [[package]] 499 | name = "fastrand" 500 | version = "1.9.0" 501 | source = "registry+https://github.com/rust-lang/crates.io-index" 502 | checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" 503 | dependencies = [ 504 | "instant", 505 | ] 506 | 507 | [[package]] 508 | name = "fastrand" 509 | version = "2.1.0" 510 | source = "registry+https://github.com/rust-lang/crates.io-index" 511 | checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" 512 | 513 | [[package]] 514 | name = "fixedbitset" 515 | version = "0.4.2" 516 | source = "registry+https://github.com/rust-lang/crates.io-index" 517 | checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" 518 | 519 | [[package]] 520 | name = "fnv" 521 | version = "1.0.7" 522 | source = "registry+https://github.com/rust-lang/crates.io-index" 523 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 524 | 525 | [[package]] 526 | name = "form_urlencoded" 527 | version = "1.2.1" 528 | source = "registry+https://github.com/rust-lang/crates.io-index" 529 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 530 | dependencies = [ 531 | "percent-encoding", 532 | ] 533 | 534 | [[package]] 535 | name = "futures-channel" 536 | version = "0.3.30" 537 | source = "registry+https://github.com/rust-lang/crates.io-index" 538 | checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" 539 | dependencies = [ 540 | "futures-core", 541 | ] 542 | 543 | [[package]] 544 | name = "futures-core" 545 | version = "0.3.30" 546 | source = "registry+https://github.com/rust-lang/crates.io-index" 547 | checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" 548 | 549 | [[package]] 550 | name = "futures-io" 551 | version = "0.3.30" 552 | source = "registry+https://github.com/rust-lang/crates.io-index" 553 | checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" 554 | 555 | [[package]] 556 | name = "futures-lite" 557 | version = "1.13.0" 558 | source = "registry+https://github.com/rust-lang/crates.io-index" 559 | checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" 560 | dependencies = [ 561 | "fastrand 1.9.0", 562 | "futures-core", 563 | "futures-io", 564 | "memchr", 565 | "parking", 566 | "pin-project-lite", 567 | "waker-fn", 568 | ] 569 | 570 | [[package]] 571 | name = "futures-lite" 572 | version = "2.3.0" 573 | source = "registry+https://github.com/rust-lang/crates.io-index" 574 | checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" 575 | dependencies = [ 576 | "fastrand 2.1.0", 577 | "futures-core", 578 | "futures-io", 579 | "parking", 580 | "pin-project-lite", 581 | ] 582 | 583 | [[package]] 584 | name = "futures-macro" 585 | version = "0.3.30" 586 | source = "registry+https://github.com/rust-lang/crates.io-index" 587 | checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" 588 | dependencies = [ 589 | "proc-macro2", 590 | "quote", 591 | "syn 2.0.66", 592 | ] 593 | 594 | [[package]] 595 | name = "futures-task" 596 | version = "0.3.30" 597 | source = "registry+https://github.com/rust-lang/crates.io-index" 598 | checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" 599 | 600 | [[package]] 601 | name = "futures-util" 602 | version = "0.3.30" 603 | source = "registry+https://github.com/rust-lang/crates.io-index" 604 | checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" 605 | dependencies = [ 606 | "futures-core", 607 | "futures-macro", 608 | "futures-task", 609 | "pin-project-lite", 610 | "pin-utils", 611 | "slab", 612 | ] 613 | 614 | [[package]] 615 | name = "getrandom" 616 | version = "0.2.15" 617 | source = "registry+https://github.com/rust-lang/crates.io-index" 618 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 619 | dependencies = [ 620 | "cfg-if", 621 | "libc", 622 | "wasi", 623 | ] 624 | 625 | [[package]] 626 | name = "gimli" 627 | version = "0.28.1" 628 | source = "registry+https://github.com/rust-lang/crates.io-index" 629 | checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" 630 | 631 | [[package]] 632 | name = "gloo-timers" 633 | version = "0.2.6" 634 | source = "registry+https://github.com/rust-lang/crates.io-index" 635 | checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" 636 | dependencies = [ 637 | "futures-channel", 638 | "futures-core", 639 | "js-sys", 640 | "wasm-bindgen", 641 | ] 642 | 643 | [[package]] 644 | name = "hashbrown" 645 | version = "0.14.5" 646 | source = "registry+https://github.com/rust-lang/crates.io-index" 647 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 648 | 649 | [[package]] 650 | name = "hermit-abi" 651 | version = "0.3.9" 652 | source = "registry+https://github.com/rust-lang/crates.io-index" 653 | checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" 654 | 655 | [[package]] 656 | name = "http" 657 | version = "0.2.12" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" 660 | dependencies = [ 661 | "bytes", 662 | "fnv", 663 | "itoa", 664 | ] 665 | 666 | [[package]] 667 | name = "http-body" 668 | version = "0.4.6" 669 | source = "registry+https://github.com/rust-lang/crates.io-index" 670 | checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" 671 | dependencies = [ 672 | "bytes", 673 | "http", 674 | "pin-project-lite", 675 | ] 676 | 677 | [[package]] 678 | name = "httparse" 679 | version = "1.8.0" 680 | source = "registry+https://github.com/rust-lang/crates.io-index" 681 | checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" 682 | 683 | [[package]] 684 | name = "httpdate" 685 | version = "1.0.3" 686 | source = "registry+https://github.com/rust-lang/crates.io-index" 687 | checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 688 | 689 | [[package]] 690 | name = "httpmock" 691 | version = "0.7.0" 692 | source = "registry+https://github.com/rust-lang/crates.io-index" 693 | checksum = "08ec9586ee0910472dec1a1f0f8acf52f0fdde93aea74d70d4a3107b4be0fd5b" 694 | dependencies = [ 695 | "assert-json-diff", 696 | "async-object-pool", 697 | "async-std", 698 | "async-trait", 699 | "base64", 700 | "basic-cookies", 701 | "crossbeam-utils", 702 | "form_urlencoded", 703 | "futures-util", 704 | "hyper", 705 | "lazy_static", 706 | "levenshtein", 707 | "log", 708 | "regex", 709 | "serde", 710 | "serde_json", 711 | "serde_regex", 712 | "similar", 713 | "tokio", 714 | "url", 715 | ] 716 | 717 | [[package]] 718 | name = "hyper" 719 | version = "0.14.28" 720 | source = "registry+https://github.com/rust-lang/crates.io-index" 721 | checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" 722 | dependencies = [ 723 | "bytes", 724 | "futures-channel", 725 | "futures-core", 726 | "futures-util", 727 | "http", 728 | "http-body", 729 | "httparse", 730 | "httpdate", 731 | "itoa", 732 | "pin-project-lite", 733 | "socket2 0.5.7", 734 | "tokio", 735 | "tower-service", 736 | "tracing", 737 | "want", 738 | ] 739 | 740 | [[package]] 741 | name = "idna" 742 | version = "0.5.0" 743 | source = "registry+https://github.com/rust-lang/crates.io-index" 744 | checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" 745 | dependencies = [ 746 | "unicode-bidi", 747 | "unicode-normalization", 748 | ] 749 | 750 | [[package]] 751 | name = "indexmap" 752 | version = "2.2.6" 753 | source = "registry+https://github.com/rust-lang/crates.io-index" 754 | checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" 755 | dependencies = [ 756 | "equivalent", 757 | "hashbrown", 758 | ] 759 | 760 | [[package]] 761 | name = "instant" 762 | version = "0.1.13" 763 | source = "registry+https://github.com/rust-lang/crates.io-index" 764 | checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" 765 | dependencies = [ 766 | "cfg-if", 767 | ] 768 | 769 | [[package]] 770 | name = "io-lifetimes" 771 | version = "1.0.11" 772 | source = "registry+https://github.com/rust-lang/crates.io-index" 773 | checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" 774 | dependencies = [ 775 | "hermit-abi", 776 | "libc", 777 | "windows-sys 0.48.0", 778 | ] 779 | 780 | [[package]] 781 | name = "itertools" 782 | version = "0.11.0" 783 | source = "registry+https://github.com/rust-lang/crates.io-index" 784 | checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" 785 | dependencies = [ 786 | "either", 787 | ] 788 | 789 | [[package]] 790 | name = "itoa" 791 | version = "1.0.11" 792 | source = "registry+https://github.com/rust-lang/crates.io-index" 793 | checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" 794 | 795 | [[package]] 796 | name = "js-sys" 797 | version = "0.3.69" 798 | source = "registry+https://github.com/rust-lang/crates.io-index" 799 | checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" 800 | dependencies = [ 801 | "wasm-bindgen", 802 | ] 803 | 804 | [[package]] 805 | name = "kv-log-macro" 806 | version = "1.0.7" 807 | source = "registry+https://github.com/rust-lang/crates.io-index" 808 | checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" 809 | dependencies = [ 810 | "log", 811 | ] 812 | 813 | [[package]] 814 | name = "lalrpop" 815 | version = "0.20.2" 816 | source = "registry+https://github.com/rust-lang/crates.io-index" 817 | checksum = "55cb077ad656299f160924eb2912aa147d7339ea7d69e1b5517326fdcec3c1ca" 818 | dependencies = [ 819 | "ascii-canvas", 820 | "bit-set", 821 | "ena", 822 | "itertools", 823 | "lalrpop-util", 824 | "petgraph", 825 | "pico-args", 826 | "regex", 827 | "regex-syntax", 828 | "string_cache", 829 | "term", 830 | "tiny-keccak", 831 | "unicode-xid", 832 | "walkdir", 833 | ] 834 | 835 | [[package]] 836 | name = "lalrpop-util" 837 | version = "0.20.2" 838 | source = "registry+https://github.com/rust-lang/crates.io-index" 839 | checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" 840 | dependencies = [ 841 | "regex-automata", 842 | ] 843 | 844 | [[package]] 845 | name = "lazy_static" 846 | version = "1.4.0" 847 | source = "registry+https://github.com/rust-lang/crates.io-index" 848 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 849 | 850 | [[package]] 851 | name = "levenshtein" 852 | version = "1.0.5" 853 | source = "registry+https://github.com/rust-lang/crates.io-index" 854 | checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" 855 | 856 | [[package]] 857 | name = "libc" 858 | version = "0.2.155" 859 | source = "registry+https://github.com/rust-lang/crates.io-index" 860 | checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" 861 | 862 | [[package]] 863 | name = "libredox" 864 | version = "0.1.3" 865 | source = "registry+https://github.com/rust-lang/crates.io-index" 866 | checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" 867 | dependencies = [ 868 | "bitflags 2.5.0", 869 | "libc", 870 | ] 871 | 872 | [[package]] 873 | name = "linux-raw-sys" 874 | version = "0.3.8" 875 | source = "registry+https://github.com/rust-lang/crates.io-index" 876 | checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" 877 | 878 | [[package]] 879 | name = "linux-raw-sys" 880 | version = "0.4.14" 881 | source = "registry+https://github.com/rust-lang/crates.io-index" 882 | checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" 883 | 884 | [[package]] 885 | name = "lock_api" 886 | version = "0.4.12" 887 | source = "registry+https://github.com/rust-lang/crates.io-index" 888 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" 889 | dependencies = [ 890 | "autocfg", 891 | "scopeguard", 892 | ] 893 | 894 | [[package]] 895 | name = "log" 896 | version = "0.4.21" 897 | source = "registry+https://github.com/rust-lang/crates.io-index" 898 | checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" 899 | dependencies = [ 900 | "value-bag", 901 | ] 902 | 903 | [[package]] 904 | name = "memchr" 905 | version = "2.7.2" 906 | source = "registry+https://github.com/rust-lang/crates.io-index" 907 | checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" 908 | 909 | [[package]] 910 | name = "miniz_oxide" 911 | version = "0.7.3" 912 | source = "registry+https://github.com/rust-lang/crates.io-index" 913 | checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" 914 | dependencies = [ 915 | "adler", 916 | ] 917 | 918 | [[package]] 919 | name = "mio" 920 | version = "0.8.11" 921 | source = "registry+https://github.com/rust-lang/crates.io-index" 922 | checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" 923 | dependencies = [ 924 | "libc", 925 | "wasi", 926 | "windows-sys 0.48.0", 927 | ] 928 | 929 | [[package]] 930 | name = "mock" 931 | version = "0.1.0" 932 | dependencies = [ 933 | "httpmock", 934 | ] 935 | 936 | [[package]] 937 | name = "new_debug_unreachable" 938 | version = "1.0.6" 939 | source = "registry+https://github.com/rust-lang/crates.io-index" 940 | checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" 941 | 942 | [[package]] 943 | name = "num_cpus" 944 | version = "1.16.0" 945 | source = "registry+https://github.com/rust-lang/crates.io-index" 946 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" 947 | dependencies = [ 948 | "hermit-abi", 949 | "libc", 950 | ] 951 | 952 | [[package]] 953 | name = "object" 954 | version = "0.32.2" 955 | source = "registry+https://github.com/rust-lang/crates.io-index" 956 | checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" 957 | dependencies = [ 958 | "memchr", 959 | ] 960 | 961 | [[package]] 962 | name = "once_cell" 963 | version = "1.19.0" 964 | source = "registry+https://github.com/rust-lang/crates.io-index" 965 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 966 | 967 | [[package]] 968 | name = "parking" 969 | version = "2.2.0" 970 | source = "registry+https://github.com/rust-lang/crates.io-index" 971 | checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" 972 | 973 | [[package]] 974 | name = "parking_lot" 975 | version = "0.12.3" 976 | source = "registry+https://github.com/rust-lang/crates.io-index" 977 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" 978 | dependencies = [ 979 | "lock_api", 980 | "parking_lot_core", 981 | ] 982 | 983 | [[package]] 984 | name = "parking_lot_core" 985 | version = "0.9.10" 986 | source = "registry+https://github.com/rust-lang/crates.io-index" 987 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" 988 | dependencies = [ 989 | "cfg-if", 990 | "libc", 991 | "redox_syscall", 992 | "smallvec", 993 | "windows-targets 0.52.5", 994 | ] 995 | 996 | [[package]] 997 | name = "percent-encoding" 998 | version = "2.3.1" 999 | source = "registry+https://github.com/rust-lang/crates.io-index" 1000 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 1001 | 1002 | [[package]] 1003 | name = "petgraph" 1004 | version = "0.6.5" 1005 | source = "registry+https://github.com/rust-lang/crates.io-index" 1006 | checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" 1007 | dependencies = [ 1008 | "fixedbitset", 1009 | "indexmap", 1010 | ] 1011 | 1012 | [[package]] 1013 | name = "phf_shared" 1014 | version = "0.10.0" 1015 | source = "registry+https://github.com/rust-lang/crates.io-index" 1016 | checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" 1017 | dependencies = [ 1018 | "siphasher", 1019 | ] 1020 | 1021 | [[package]] 1022 | name = "pico-args" 1023 | version = "0.5.0" 1024 | source = "registry+https://github.com/rust-lang/crates.io-index" 1025 | checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" 1026 | 1027 | [[package]] 1028 | name = "pin-project-lite" 1029 | version = "0.2.14" 1030 | source = "registry+https://github.com/rust-lang/crates.io-index" 1031 | checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" 1032 | 1033 | [[package]] 1034 | name = "pin-utils" 1035 | version = "0.1.0" 1036 | source = "registry+https://github.com/rust-lang/crates.io-index" 1037 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1038 | 1039 | [[package]] 1040 | name = "piper" 1041 | version = "0.2.2" 1042 | source = "registry+https://github.com/rust-lang/crates.io-index" 1043 | checksum = "464db0c665917b13ebb5d453ccdec4add5658ee1adc7affc7677615356a8afaf" 1044 | dependencies = [ 1045 | "atomic-waker", 1046 | "fastrand 2.1.0", 1047 | "futures-io", 1048 | ] 1049 | 1050 | [[package]] 1051 | name = "polling" 1052 | version = "2.8.0" 1053 | source = "registry+https://github.com/rust-lang/crates.io-index" 1054 | checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" 1055 | dependencies = [ 1056 | "autocfg", 1057 | "bitflags 1.3.2", 1058 | "cfg-if", 1059 | "concurrent-queue", 1060 | "libc", 1061 | "log", 1062 | "pin-project-lite", 1063 | "windows-sys 0.48.0", 1064 | ] 1065 | 1066 | [[package]] 1067 | name = "polling" 1068 | version = "3.7.0" 1069 | source = "registry+https://github.com/rust-lang/crates.io-index" 1070 | checksum = "645493cf344456ef24219d02a768cf1fb92ddf8c92161679ae3d91b91a637be3" 1071 | dependencies = [ 1072 | "cfg-if", 1073 | "concurrent-queue", 1074 | "hermit-abi", 1075 | "pin-project-lite", 1076 | "rustix 0.38.34", 1077 | "tracing", 1078 | "windows-sys 0.52.0", 1079 | ] 1080 | 1081 | [[package]] 1082 | name = "precomputed-hash" 1083 | version = "0.1.1" 1084 | source = "registry+https://github.com/rust-lang/crates.io-index" 1085 | checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" 1086 | 1087 | [[package]] 1088 | name = "proc-macro2" 1089 | version = "1.0.83" 1090 | source = "registry+https://github.com/rust-lang/crates.io-index" 1091 | checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" 1092 | dependencies = [ 1093 | "unicode-ident", 1094 | ] 1095 | 1096 | [[package]] 1097 | name = "quote" 1098 | version = "1.0.36" 1099 | source = "registry+https://github.com/rust-lang/crates.io-index" 1100 | checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" 1101 | dependencies = [ 1102 | "proc-macro2", 1103 | ] 1104 | 1105 | [[package]] 1106 | name = "redox_syscall" 1107 | version = "0.5.1" 1108 | source = "registry+https://github.com/rust-lang/crates.io-index" 1109 | checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" 1110 | dependencies = [ 1111 | "bitflags 2.5.0", 1112 | ] 1113 | 1114 | [[package]] 1115 | name = "redox_users" 1116 | version = "0.4.5" 1117 | source = "registry+https://github.com/rust-lang/crates.io-index" 1118 | checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" 1119 | dependencies = [ 1120 | "getrandom", 1121 | "libredox", 1122 | "thiserror", 1123 | ] 1124 | 1125 | [[package]] 1126 | name = "regex" 1127 | version = "1.10.4" 1128 | source = "registry+https://github.com/rust-lang/crates.io-index" 1129 | checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" 1130 | dependencies = [ 1131 | "aho-corasick", 1132 | "memchr", 1133 | "regex-automata", 1134 | "regex-syntax", 1135 | ] 1136 | 1137 | [[package]] 1138 | name = "regex-automata" 1139 | version = "0.4.6" 1140 | source = "registry+https://github.com/rust-lang/crates.io-index" 1141 | checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" 1142 | dependencies = [ 1143 | "aho-corasick", 1144 | "memchr", 1145 | "regex-syntax", 1146 | ] 1147 | 1148 | [[package]] 1149 | name = "regex-syntax" 1150 | version = "0.8.3" 1151 | source = "registry+https://github.com/rust-lang/crates.io-index" 1152 | checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" 1153 | 1154 | [[package]] 1155 | name = "rustc-demangle" 1156 | version = "0.1.24" 1157 | source = "registry+https://github.com/rust-lang/crates.io-index" 1158 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 1159 | 1160 | [[package]] 1161 | name = "rustix" 1162 | version = "0.37.27" 1163 | source = "registry+https://github.com/rust-lang/crates.io-index" 1164 | checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" 1165 | dependencies = [ 1166 | "bitflags 1.3.2", 1167 | "errno", 1168 | "io-lifetimes", 1169 | "libc", 1170 | "linux-raw-sys 0.3.8", 1171 | "windows-sys 0.48.0", 1172 | ] 1173 | 1174 | [[package]] 1175 | name = "rustix" 1176 | version = "0.38.34" 1177 | source = "registry+https://github.com/rust-lang/crates.io-index" 1178 | checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" 1179 | dependencies = [ 1180 | "bitflags 2.5.0", 1181 | "errno", 1182 | "libc", 1183 | "linux-raw-sys 0.4.14", 1184 | "windows-sys 0.52.0", 1185 | ] 1186 | 1187 | [[package]] 1188 | name = "rustversion" 1189 | version = "1.0.17" 1190 | source = "registry+https://github.com/rust-lang/crates.io-index" 1191 | checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" 1192 | 1193 | [[package]] 1194 | name = "ryu" 1195 | version = "1.0.18" 1196 | source = "registry+https://github.com/rust-lang/crates.io-index" 1197 | checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" 1198 | 1199 | [[package]] 1200 | name = "same-file" 1201 | version = "1.0.6" 1202 | source = "registry+https://github.com/rust-lang/crates.io-index" 1203 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 1204 | dependencies = [ 1205 | "winapi-util", 1206 | ] 1207 | 1208 | [[package]] 1209 | name = "scopeguard" 1210 | version = "1.2.0" 1211 | source = "registry+https://github.com/rust-lang/crates.io-index" 1212 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 1213 | 1214 | [[package]] 1215 | name = "serde" 1216 | version = "1.0.202" 1217 | source = "registry+https://github.com/rust-lang/crates.io-index" 1218 | checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" 1219 | dependencies = [ 1220 | "serde_derive", 1221 | ] 1222 | 1223 | [[package]] 1224 | name = "serde_derive" 1225 | version = "1.0.202" 1226 | source = "registry+https://github.com/rust-lang/crates.io-index" 1227 | checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" 1228 | dependencies = [ 1229 | "proc-macro2", 1230 | "quote", 1231 | "syn 2.0.66", 1232 | ] 1233 | 1234 | [[package]] 1235 | name = "serde_json" 1236 | version = "1.0.117" 1237 | source = "registry+https://github.com/rust-lang/crates.io-index" 1238 | checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" 1239 | dependencies = [ 1240 | "itoa", 1241 | "ryu", 1242 | "serde", 1243 | ] 1244 | 1245 | [[package]] 1246 | name = "serde_regex" 1247 | version = "1.1.0" 1248 | source = "registry+https://github.com/rust-lang/crates.io-index" 1249 | checksum = "a8136f1a4ea815d7eac4101cfd0b16dc0cb5e1fe1b8609dfd728058656b7badf" 1250 | dependencies = [ 1251 | "regex", 1252 | "serde", 1253 | ] 1254 | 1255 | [[package]] 1256 | name = "signal-hook-registry" 1257 | version = "1.4.2" 1258 | source = "registry+https://github.com/rust-lang/crates.io-index" 1259 | checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" 1260 | dependencies = [ 1261 | "libc", 1262 | ] 1263 | 1264 | [[package]] 1265 | name = "similar" 1266 | version = "2.5.0" 1267 | source = "registry+https://github.com/rust-lang/crates.io-index" 1268 | checksum = "fa42c91313f1d05da9b26f267f931cf178d4aba455b4c4622dd7355eb80c6640" 1269 | 1270 | [[package]] 1271 | name = "siphasher" 1272 | version = "0.3.11" 1273 | source = "registry+https://github.com/rust-lang/crates.io-index" 1274 | checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" 1275 | 1276 | [[package]] 1277 | name = "slab" 1278 | version = "0.4.9" 1279 | source = "registry+https://github.com/rust-lang/crates.io-index" 1280 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 1281 | dependencies = [ 1282 | "autocfg", 1283 | ] 1284 | 1285 | [[package]] 1286 | name = "smallvec" 1287 | version = "1.13.2" 1288 | source = "registry+https://github.com/rust-lang/crates.io-index" 1289 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 1290 | 1291 | [[package]] 1292 | name = "socket2" 1293 | version = "0.4.10" 1294 | source = "registry+https://github.com/rust-lang/crates.io-index" 1295 | checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" 1296 | dependencies = [ 1297 | "libc", 1298 | "winapi", 1299 | ] 1300 | 1301 | [[package]] 1302 | name = "socket2" 1303 | version = "0.5.7" 1304 | source = "registry+https://github.com/rust-lang/crates.io-index" 1305 | checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" 1306 | dependencies = [ 1307 | "libc", 1308 | "windows-sys 0.52.0", 1309 | ] 1310 | 1311 | [[package]] 1312 | name = "string_cache" 1313 | version = "0.8.7" 1314 | source = "registry+https://github.com/rust-lang/crates.io-index" 1315 | checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" 1316 | dependencies = [ 1317 | "new_debug_unreachable", 1318 | "once_cell", 1319 | "parking_lot", 1320 | "phf_shared", 1321 | "precomputed-hash", 1322 | ] 1323 | 1324 | [[package]] 1325 | name = "syn" 1326 | version = "1.0.109" 1327 | source = "registry+https://github.com/rust-lang/crates.io-index" 1328 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 1329 | dependencies = [ 1330 | "proc-macro2", 1331 | "quote", 1332 | "unicode-ident", 1333 | ] 1334 | 1335 | [[package]] 1336 | name = "syn" 1337 | version = "2.0.66" 1338 | source = "registry+https://github.com/rust-lang/crates.io-index" 1339 | checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" 1340 | dependencies = [ 1341 | "proc-macro2", 1342 | "quote", 1343 | "unicode-ident", 1344 | ] 1345 | 1346 | [[package]] 1347 | name = "term" 1348 | version = "0.7.0" 1349 | source = "registry+https://github.com/rust-lang/crates.io-index" 1350 | checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" 1351 | dependencies = [ 1352 | "dirs-next", 1353 | "rustversion", 1354 | "winapi", 1355 | ] 1356 | 1357 | [[package]] 1358 | name = "thiserror" 1359 | version = "1.0.61" 1360 | source = "registry+https://github.com/rust-lang/crates.io-index" 1361 | checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" 1362 | dependencies = [ 1363 | "thiserror-impl", 1364 | ] 1365 | 1366 | [[package]] 1367 | name = "thiserror-impl" 1368 | version = "1.0.61" 1369 | source = "registry+https://github.com/rust-lang/crates.io-index" 1370 | checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" 1371 | dependencies = [ 1372 | "proc-macro2", 1373 | "quote", 1374 | "syn 2.0.66", 1375 | ] 1376 | 1377 | [[package]] 1378 | name = "tiny-keccak" 1379 | version = "2.0.2" 1380 | source = "registry+https://github.com/rust-lang/crates.io-index" 1381 | checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" 1382 | dependencies = [ 1383 | "crunchy", 1384 | ] 1385 | 1386 | [[package]] 1387 | name = "tinyvec" 1388 | version = "1.6.0" 1389 | source = "registry+https://github.com/rust-lang/crates.io-index" 1390 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 1391 | dependencies = [ 1392 | "tinyvec_macros", 1393 | ] 1394 | 1395 | [[package]] 1396 | name = "tinyvec_macros" 1397 | version = "0.1.1" 1398 | source = "registry+https://github.com/rust-lang/crates.io-index" 1399 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 1400 | 1401 | [[package]] 1402 | name = "tokio" 1403 | version = "1.37.0" 1404 | source = "registry+https://github.com/rust-lang/crates.io-index" 1405 | checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" 1406 | dependencies = [ 1407 | "backtrace", 1408 | "libc", 1409 | "mio", 1410 | "num_cpus", 1411 | "pin-project-lite", 1412 | "signal-hook-registry", 1413 | "socket2 0.5.7", 1414 | "tokio-macros", 1415 | "windows-sys 0.48.0", 1416 | ] 1417 | 1418 | [[package]] 1419 | name = "tokio-macros" 1420 | version = "2.2.0" 1421 | source = "registry+https://github.com/rust-lang/crates.io-index" 1422 | checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" 1423 | dependencies = [ 1424 | "proc-macro2", 1425 | "quote", 1426 | "syn 2.0.66", 1427 | ] 1428 | 1429 | [[package]] 1430 | name = "tower-service" 1431 | version = "0.3.2" 1432 | source = "registry+https://github.com/rust-lang/crates.io-index" 1433 | checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" 1434 | 1435 | [[package]] 1436 | name = "tracing" 1437 | version = "0.1.40" 1438 | source = "registry+https://github.com/rust-lang/crates.io-index" 1439 | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" 1440 | dependencies = [ 1441 | "pin-project-lite", 1442 | "tracing-core", 1443 | ] 1444 | 1445 | [[package]] 1446 | name = "tracing-core" 1447 | version = "0.1.32" 1448 | source = "registry+https://github.com/rust-lang/crates.io-index" 1449 | checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" 1450 | dependencies = [ 1451 | "once_cell", 1452 | ] 1453 | 1454 | [[package]] 1455 | name = "try-lock" 1456 | version = "0.2.5" 1457 | source = "registry+https://github.com/rust-lang/crates.io-index" 1458 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 1459 | 1460 | [[package]] 1461 | name = "unicode-bidi" 1462 | version = "0.3.15" 1463 | source = "registry+https://github.com/rust-lang/crates.io-index" 1464 | checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" 1465 | 1466 | [[package]] 1467 | name = "unicode-ident" 1468 | version = "1.0.12" 1469 | source = "registry+https://github.com/rust-lang/crates.io-index" 1470 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 1471 | 1472 | [[package]] 1473 | name = "unicode-normalization" 1474 | version = "0.1.23" 1475 | source = "registry+https://github.com/rust-lang/crates.io-index" 1476 | checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" 1477 | dependencies = [ 1478 | "tinyvec", 1479 | ] 1480 | 1481 | [[package]] 1482 | name = "unicode-xid" 1483 | version = "0.2.4" 1484 | source = "registry+https://github.com/rust-lang/crates.io-index" 1485 | checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" 1486 | 1487 | [[package]] 1488 | name = "url" 1489 | version = "2.5.0" 1490 | source = "registry+https://github.com/rust-lang/crates.io-index" 1491 | checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" 1492 | dependencies = [ 1493 | "form_urlencoded", 1494 | "idna", 1495 | "percent-encoding", 1496 | ] 1497 | 1498 | [[package]] 1499 | name = "value-bag" 1500 | version = "1.9.0" 1501 | source = "registry+https://github.com/rust-lang/crates.io-index" 1502 | checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" 1503 | 1504 | [[package]] 1505 | name = "waker-fn" 1506 | version = "1.2.0" 1507 | source = "registry+https://github.com/rust-lang/crates.io-index" 1508 | checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" 1509 | 1510 | [[package]] 1511 | name = "walkdir" 1512 | version = "2.5.0" 1513 | source = "registry+https://github.com/rust-lang/crates.io-index" 1514 | checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 1515 | dependencies = [ 1516 | "same-file", 1517 | "winapi-util", 1518 | ] 1519 | 1520 | [[package]] 1521 | name = "want" 1522 | version = "0.3.1" 1523 | source = "registry+https://github.com/rust-lang/crates.io-index" 1524 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 1525 | dependencies = [ 1526 | "try-lock", 1527 | ] 1528 | 1529 | [[package]] 1530 | name = "wasi" 1531 | version = "0.11.0+wasi-snapshot-preview1" 1532 | source = "registry+https://github.com/rust-lang/crates.io-index" 1533 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1534 | 1535 | [[package]] 1536 | name = "wasm-bindgen" 1537 | version = "0.2.92" 1538 | source = "registry+https://github.com/rust-lang/crates.io-index" 1539 | checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" 1540 | dependencies = [ 1541 | "cfg-if", 1542 | "wasm-bindgen-macro", 1543 | ] 1544 | 1545 | [[package]] 1546 | name = "wasm-bindgen-backend" 1547 | version = "0.2.92" 1548 | source = "registry+https://github.com/rust-lang/crates.io-index" 1549 | checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" 1550 | dependencies = [ 1551 | "bumpalo", 1552 | "log", 1553 | "once_cell", 1554 | "proc-macro2", 1555 | "quote", 1556 | "syn 2.0.66", 1557 | "wasm-bindgen-shared", 1558 | ] 1559 | 1560 | [[package]] 1561 | name = "wasm-bindgen-futures" 1562 | version = "0.4.42" 1563 | source = "registry+https://github.com/rust-lang/crates.io-index" 1564 | checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" 1565 | dependencies = [ 1566 | "cfg-if", 1567 | "js-sys", 1568 | "wasm-bindgen", 1569 | "web-sys", 1570 | ] 1571 | 1572 | [[package]] 1573 | name = "wasm-bindgen-macro" 1574 | version = "0.2.92" 1575 | source = "registry+https://github.com/rust-lang/crates.io-index" 1576 | checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" 1577 | dependencies = [ 1578 | "quote", 1579 | "wasm-bindgen-macro-support", 1580 | ] 1581 | 1582 | [[package]] 1583 | name = "wasm-bindgen-macro-support" 1584 | version = "0.2.92" 1585 | source = "registry+https://github.com/rust-lang/crates.io-index" 1586 | checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" 1587 | dependencies = [ 1588 | "proc-macro2", 1589 | "quote", 1590 | "syn 2.0.66", 1591 | "wasm-bindgen-backend", 1592 | "wasm-bindgen-shared", 1593 | ] 1594 | 1595 | [[package]] 1596 | name = "wasm-bindgen-shared" 1597 | version = "0.2.92" 1598 | source = "registry+https://github.com/rust-lang/crates.io-index" 1599 | checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" 1600 | 1601 | [[package]] 1602 | name = "web-sys" 1603 | version = "0.3.69" 1604 | source = "registry+https://github.com/rust-lang/crates.io-index" 1605 | checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" 1606 | dependencies = [ 1607 | "js-sys", 1608 | "wasm-bindgen", 1609 | ] 1610 | 1611 | [[package]] 1612 | name = "winapi" 1613 | version = "0.3.9" 1614 | source = "registry+https://github.com/rust-lang/crates.io-index" 1615 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1616 | dependencies = [ 1617 | "winapi-i686-pc-windows-gnu", 1618 | "winapi-x86_64-pc-windows-gnu", 1619 | ] 1620 | 1621 | [[package]] 1622 | name = "winapi-i686-pc-windows-gnu" 1623 | version = "0.4.0" 1624 | source = "registry+https://github.com/rust-lang/crates.io-index" 1625 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1626 | 1627 | [[package]] 1628 | name = "winapi-util" 1629 | version = "0.1.8" 1630 | source = "registry+https://github.com/rust-lang/crates.io-index" 1631 | checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" 1632 | dependencies = [ 1633 | "windows-sys 0.52.0", 1634 | ] 1635 | 1636 | [[package]] 1637 | name = "winapi-x86_64-pc-windows-gnu" 1638 | version = "0.4.0" 1639 | source = "registry+https://github.com/rust-lang/crates.io-index" 1640 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1641 | 1642 | [[package]] 1643 | name = "windows-sys" 1644 | version = "0.48.0" 1645 | source = "registry+https://github.com/rust-lang/crates.io-index" 1646 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 1647 | dependencies = [ 1648 | "windows-targets 0.48.5", 1649 | ] 1650 | 1651 | [[package]] 1652 | name = "windows-sys" 1653 | version = "0.52.0" 1654 | source = "registry+https://github.com/rust-lang/crates.io-index" 1655 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 1656 | dependencies = [ 1657 | "windows-targets 0.52.5", 1658 | ] 1659 | 1660 | [[package]] 1661 | name = "windows-targets" 1662 | version = "0.48.5" 1663 | source = "registry+https://github.com/rust-lang/crates.io-index" 1664 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 1665 | dependencies = [ 1666 | "windows_aarch64_gnullvm 0.48.5", 1667 | "windows_aarch64_msvc 0.48.5", 1668 | "windows_i686_gnu 0.48.5", 1669 | "windows_i686_msvc 0.48.5", 1670 | "windows_x86_64_gnu 0.48.5", 1671 | "windows_x86_64_gnullvm 0.48.5", 1672 | "windows_x86_64_msvc 0.48.5", 1673 | ] 1674 | 1675 | [[package]] 1676 | name = "windows-targets" 1677 | version = "0.52.5" 1678 | source = "registry+https://github.com/rust-lang/crates.io-index" 1679 | checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" 1680 | dependencies = [ 1681 | "windows_aarch64_gnullvm 0.52.5", 1682 | "windows_aarch64_msvc 0.52.5", 1683 | "windows_i686_gnu 0.52.5", 1684 | "windows_i686_gnullvm", 1685 | "windows_i686_msvc 0.52.5", 1686 | "windows_x86_64_gnu 0.52.5", 1687 | "windows_x86_64_gnullvm 0.52.5", 1688 | "windows_x86_64_msvc 0.52.5", 1689 | ] 1690 | 1691 | [[package]] 1692 | name = "windows_aarch64_gnullvm" 1693 | version = "0.48.5" 1694 | source = "registry+https://github.com/rust-lang/crates.io-index" 1695 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 1696 | 1697 | [[package]] 1698 | name = "windows_aarch64_gnullvm" 1699 | version = "0.52.5" 1700 | source = "registry+https://github.com/rust-lang/crates.io-index" 1701 | checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" 1702 | 1703 | [[package]] 1704 | name = "windows_aarch64_msvc" 1705 | version = "0.48.5" 1706 | source = "registry+https://github.com/rust-lang/crates.io-index" 1707 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 1708 | 1709 | [[package]] 1710 | name = "windows_aarch64_msvc" 1711 | version = "0.52.5" 1712 | source = "registry+https://github.com/rust-lang/crates.io-index" 1713 | checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" 1714 | 1715 | [[package]] 1716 | name = "windows_i686_gnu" 1717 | version = "0.48.5" 1718 | source = "registry+https://github.com/rust-lang/crates.io-index" 1719 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 1720 | 1721 | [[package]] 1722 | name = "windows_i686_gnu" 1723 | version = "0.52.5" 1724 | source = "registry+https://github.com/rust-lang/crates.io-index" 1725 | checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" 1726 | 1727 | [[package]] 1728 | name = "windows_i686_gnullvm" 1729 | version = "0.52.5" 1730 | source = "registry+https://github.com/rust-lang/crates.io-index" 1731 | checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" 1732 | 1733 | [[package]] 1734 | name = "windows_i686_msvc" 1735 | version = "0.48.5" 1736 | source = "registry+https://github.com/rust-lang/crates.io-index" 1737 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 1738 | 1739 | [[package]] 1740 | name = "windows_i686_msvc" 1741 | version = "0.52.5" 1742 | source = "registry+https://github.com/rust-lang/crates.io-index" 1743 | checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" 1744 | 1745 | [[package]] 1746 | name = "windows_x86_64_gnu" 1747 | version = "0.48.5" 1748 | source = "registry+https://github.com/rust-lang/crates.io-index" 1749 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 1750 | 1751 | [[package]] 1752 | name = "windows_x86_64_gnu" 1753 | version = "0.52.5" 1754 | source = "registry+https://github.com/rust-lang/crates.io-index" 1755 | checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" 1756 | 1757 | [[package]] 1758 | name = "windows_x86_64_gnullvm" 1759 | version = "0.48.5" 1760 | source = "registry+https://github.com/rust-lang/crates.io-index" 1761 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 1762 | 1763 | [[package]] 1764 | name = "windows_x86_64_gnullvm" 1765 | version = "0.52.5" 1766 | source = "registry+https://github.com/rust-lang/crates.io-index" 1767 | checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" 1768 | 1769 | [[package]] 1770 | name = "windows_x86_64_msvc" 1771 | version = "0.48.5" 1772 | source = "registry+https://github.com/rust-lang/crates.io-index" 1773 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 1774 | 1775 | [[package]] 1776 | name = "windows_x86_64_msvc" 1777 | version = "0.52.5" 1778 | source = "registry+https://github.com/rust-lang/crates.io-index" 1779 | checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" 1780 | --------------------------------------------------------------------------------