From 5e0c2aa5c36df2e26f6d05782bf101ebbedd4a4f Mon Sep 17 00:00:00 2001 From: Wyatt Jacob Herkamp Date: Fri, 27 May 2022 20:28:29 -0400 Subject: [PATCH 01/76] Starting 1.1 --- README.md | 1 + backend/Cargo.toml | 44 +- backend/build.rs | 4 +- backend/migrations/.gitkeep | 0 .../2021-07-08-184225_create_users/down.sql | 1 - .../2021-07-08-184225_create_users/up.sql | 10 - .../down.sql | 1 - .../up.sql | 9 - .../down.sql | 1 - .../up.sql | 9 - .../down.sql | 1 - .../up.sql | 9 - backend/resources/email/forgot_password.html | 8 - backend/resources/pages/error/500.html | 10 - backend/src/api_response.rs | 106 ---- .../src/authentication/auth_token/database.rs | 113 +++++ backend/src/authentication/auth_token/mod.rs | 86 ++++ backend/src/authentication/middleware.rs | 240 +++++++++ backend/src/authentication/mod.rs | 132 +++++ .../src/authentication/session/basic/mod.rs | 96 ++++ backend/src/authentication/session/mod.rs | 75 +++ backend/src/bin/nitro_repo_full.rs | 118 +++++ backend/src/cli/mod.rs | 49 ++ backend/src/database.rs | 29 -- backend/src/error/api_error.rs | 80 +++ backend/src/error/handlers/json_error.rs | 31 +- backend/src/error/internal_error.rs | 100 ++-- backend/src/error/mod.rs | 2 +- backend/src/error/response.rs | 102 ---- backend/src/frontend/controllers.rs | 17 +- backend/src/install/mod.rs | 140 +++--- backend/src/lib.rs | 25 + backend/src/main.rs | 211 -------- backend/src/misc/frontend_helpers.rs | 20 - backend/src/misc/mod.rs | 7 - backend/src/repository/admin/controller.rs | 448 ----------------- backend/src/repository/admin/mod.rs | 21 - backend/src/repository/api.rs | 78 --- backend/src/repository/badge.rs | 60 --- backend/src/repository/controller.rs | 359 -------------- backend/src/repository/data/mod.rs | 78 +++ backend/src/repository/deploy/mod.rs | 40 -- backend/src/repository/handler.rs | 87 ++++ backend/src/repository/maven/error.rs | 25 + backend/src/repository/maven/mod.rs | 367 +++++--------- backend/src/repository/maven/models.rs | 30 +- backend/src/repository/maven/utils.rs | 58 --- backend/src/repository/mod.rs | 37 +- backend/src/repository/models.rs | 44 -- backend/src/repository/nitro/mod.rs | 35 +- .../src/repository/nitro/nitro_repository.rs | 237 +++++++++ backend/src/repository/nitro/utils.rs | 130 +++++ backend/src/repository/npm/error.rs | 25 + backend/src/repository/npm/mod.rs | 455 +++++++----------- backend/src/repository/npm/models.rs | 31 +- backend/src/repository/npm/utils.rs | 120 +---- backend/src/repository/public.rs | 62 --- backend/src/repository/response.rs | 79 +++ backend/src/repository/settings/frontend.rs | 12 +- backend/src/repository/settings/mod.rs | 40 +- backend/src/repository/settings/security.rs | 18 +- backend/src/repository/settings/webhook.rs | 6 +- backend/src/repository/types.rs | 153 ------ backend/src/repository/utils.rs | 206 -------- backend/src/schema.rs | 39 -- backend/src/settings/controller.rs | 24 - backend/src/settings/mod.rs | 22 +- backend/src/settings/models.rs | 72 +-- backend/src/storage/admin/controller.rs | 116 ----- backend/src/storage/admin/mod.rs | 10 - backend/src/storage/bad_storage.rs | 160 ++++++ backend/src/storage/error.rs | 39 ++ backend/src/storage/file.rs | 180 +++++++ backend/src/storage/local_storage.rs | 342 ------------- backend/src/storage/local_storage/mod.rs | 407 ++++++++++++++++ backend/src/storage/mod.rs | 276 ++++++++--- backend/src/storage/models.rs | 273 ++++++----- backend/src/storage/multi/mod.rs | 176 +++++++ backend/src/storage/multi/web/admin.rs | 37 ++ backend/src/storage/multi/web/mod.rs | 7 + backend/src/system/action.rs | 181 ------- backend/src/system/controllers/me.rs | 37 -- backend/src/system/controllers/mod.rs | 18 - backend/src/system/controllers/public.rs | 50 -- backend/src/system/controllers/user.rs | 172 ------- backend/src/system/mod.rs | 6 +- backend/src/system/models.rs | 62 +-- backend/src/system/permissions/mod.rs | 71 +-- backend/src/system/permissions/options.rs | 118 +++-- backend/src/system/permissions/orm.rs | 47 ++ backend/src/system/user/database.rs | 38 ++ backend/src/system/user/mod.rs | 15 + backend/src/system/utils.rs | 123 +---- backend/src/system/web/mod.rs | 14 + backend/src/system/web/public.rs | 36 ++ backend/src/system/web/user.rs | 15 + backend/src/updater/mod.rs | 11 + backend/src/updater/one_one/mod.rs | 1 + backend/src/utils.rs | 12 + backend/src/webhook/mod.rs | 44 -- frontend/README.md | 30 +- frontend/config.json.example | 3 - 102 files changed, 3972 insertions(+), 4540 deletions(-) delete mode 100644 backend/migrations/.gitkeep delete mode 100644 backend/migrations/2021-07-08-184225_create_users/down.sql delete mode 100644 backend/migrations/2021-07-08-184225_create_users/up.sql delete mode 100644 backend/migrations/2021-07-08-213104_create_session_tokens/down.sql delete mode 100644 backend/migrations/2021-07-08-213104_create_session_tokens/up.sql delete mode 100644 backend/migrations/2021-07-13-180028_create_forgot_password/down.sql delete mode 100644 backend/migrations/2021-07-13-180028_create_forgot_password/up.sql delete mode 100644 backend/migrations/2021-09-29-194126_create_auth_tokens/down.sql delete mode 100644 backend/migrations/2021-09-29-194126_create_auth_tokens/up.sql delete mode 100644 backend/resources/email/forgot_password.html delete mode 100644 backend/resources/pages/error/500.html delete mode 100644 backend/src/api_response.rs create mode 100644 backend/src/authentication/auth_token/database.rs create mode 100644 backend/src/authentication/auth_token/mod.rs create mode 100644 backend/src/authentication/middleware.rs create mode 100644 backend/src/authentication/mod.rs create mode 100644 backend/src/authentication/session/basic/mod.rs create mode 100644 backend/src/authentication/session/mod.rs create mode 100644 backend/src/bin/nitro_repo_full.rs create mode 100644 backend/src/cli/mod.rs delete mode 100644 backend/src/database.rs create mode 100644 backend/src/error/api_error.rs delete mode 100644 backend/src/error/response.rs create mode 100644 backend/src/lib.rs delete mode 100644 backend/src/main.rs delete mode 100644 backend/src/misc/frontend_helpers.rs delete mode 100644 backend/src/misc/mod.rs delete mode 100644 backend/src/repository/admin/controller.rs delete mode 100644 backend/src/repository/admin/mod.rs delete mode 100644 backend/src/repository/api.rs delete mode 100644 backend/src/repository/badge.rs delete mode 100644 backend/src/repository/controller.rs create mode 100644 backend/src/repository/data/mod.rs delete mode 100644 backend/src/repository/deploy/mod.rs create mode 100644 backend/src/repository/handler.rs create mode 100644 backend/src/repository/maven/error.rs delete mode 100644 backend/src/repository/models.rs create mode 100644 backend/src/repository/nitro/nitro_repository.rs create mode 100644 backend/src/repository/nitro/utils.rs create mode 100644 backend/src/repository/npm/error.rs delete mode 100644 backend/src/repository/public.rs create mode 100644 backend/src/repository/response.rs delete mode 100644 backend/src/repository/types.rs delete mode 100644 backend/src/repository/utils.rs delete mode 100644 backend/src/schema.rs delete mode 100644 backend/src/settings/controller.rs delete mode 100644 backend/src/storage/admin/controller.rs delete mode 100644 backend/src/storage/admin/mod.rs create mode 100644 backend/src/storage/bad_storage.rs create mode 100644 backend/src/storage/error.rs create mode 100644 backend/src/storage/file.rs delete mode 100644 backend/src/storage/local_storage.rs create mode 100644 backend/src/storage/local_storage/mod.rs create mode 100644 backend/src/storage/multi/mod.rs create mode 100644 backend/src/storage/multi/web/admin.rs create mode 100644 backend/src/storage/multi/web/mod.rs delete mode 100644 backend/src/system/action.rs delete mode 100644 backend/src/system/controllers/me.rs delete mode 100644 backend/src/system/controllers/mod.rs delete mode 100644 backend/src/system/controllers/public.rs delete mode 100644 backend/src/system/controllers/user.rs create mode 100644 backend/src/system/permissions/orm.rs create mode 100644 backend/src/system/user/database.rs create mode 100644 backend/src/system/user/mod.rs create mode 100644 backend/src/system/web/mod.rs create mode 100644 backend/src/system/web/public.rs create mode 100644 backend/src/system/web/user.rs create mode 100644 backend/src/updater/mod.rs create mode 100644 backend/src/updater/one_one/mod.rs delete mode 100644 backend/src/webhook/mod.rs delete mode 100644 frontend/config.json.example diff --git a/README.md b/README.md index 603a08b1..0b6e2665 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![Push](https://github.com/wherkamp/nitro_repo/actions/workflows/push.yml/badge.svg)](https://github.com/wherkamp/nitro_repo/actions/workflows/push.yml) [![issues](https://img.shields.io/github/issues/wherkamp/nitro_repo/help%20wanted)](https://github.com/wherkamp/nitro_repo/issues) +## 1.1 Development Nitro Repo is an open source free artifact manager. Written with a Rust back end and a Vue front end to create a fast and modern experience. diff --git a/backend/Cargo.toml b/backend/Cargo.toml index e9e67cd4..3ae20ba7 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -1,28 +1,37 @@ [package] name = "nitro_repo" -version = "1.0.1" +version = "1.1.0-BETA" authors = ["Wyatt Jacob Herkamp "] edition = "2021" build = "build.rs" license-file = "../LICENSE" +default-run = "nitro_repo_full" + +[lib] +name = "api" +path = "src/lib.rs" +[[bin]] +name = "nitro_repo_full" +required-features = ["multi_storage"] + + [dependencies] # Web -actix-web = { version = "4.0.1", features = ["openssl"] } +actix-web = { version = "4.0.1", features = ["openssl", "cookies"] } actix-cors = "0.6.1" actix-service = "2.0.2" openssl = { version = "0.10.40", features = ["v110"], optional = true } actix-files = "0.6.0" # Partly Web lettre = "0.10.0-rc.6" -handlebars = "4.3.0" +handlebars = "4.2.2" # Database -diesel = { version = "1.4.8", features = ["mysql", "r2d2"] } -diesel_migrations = "1.4.0" -r2d2 = "0.8.9" -r2d2_mysql = "21.0.0" +sea-orm = { version = "0.7.1", features = ["sqlx-mysql", "sqlx-sqlite", "runtime-actix-native-tls", "macros"] } +sqlx = "0.5.13" # Serde serde = { version = "1.0.137", features = ["derive"] } serde_json = "1.0.81" +futures = "0.3.21" serde-xml-rs = "0.5.1" toml = "0.5.9" @@ -32,13 +41,16 @@ rand_core = { version = "0.6.3", features = ["std"] } rust-embed = { version = "6.4.0", features = ["interpolate-folder-path"] } argon2 = "0.4.0" chrono = "0.4.19" -regex = "1.5.6" +time = "0.3.9" +regex = "1.5.5" futures-util = "0.3.21" base64 = "0.13.0" -tokio = "1.18.2" +tokio = { version = "1.18.1", features = ["full"] } +uuid = { version = "1.0.0", features = ["serde", "v4"] } style-term = "1.0.0" +mime_guess = "2.0.4" # Log -nitro_log = { git = "https://github.com/wherkamp/nitro_log", features = ["chrono", "style-term"] } +nitro_log = { git = "https://github.com/wyatt-herkamp/nitro_log", features = ["chrono", "style-term"] } log = "0.4.17" # Rust Internal strum = { version = "0.24.0", features = ["derive"] } @@ -55,11 +67,17 @@ webhook = "2.0.0" # Installer tui = "0.18.0" crossterm = "0.23.2" -clap = { version = "3.1.18", features = ["derive"] } +clap = { version = "3.1.15", features = ["derive"] } unicode-width = "0.1.9" - +semver = "1.0.9" [build-dependencies] -vergen = "7.1.0" +vergen = "7.0.0" [features] +# The latest Updaters will always be under default features +default = ["updater_one-one", "multi_storage"] ssl = ["openssl", "actix-web/openssl"] +multi_storage = [] +# Updaters +# Updater for 1.0.0 - 1.1.0 +updater_one-one = [] diff --git a/backend/build.rs b/backend/build.rs index ebfb7746..b72de18b 100644 --- a/backend/build.rs +++ b/backend/build.rs @@ -1,5 +1,5 @@ -use vergen::{Config, vergen}; +use vergen::{vergen, Config}; fn main() { vergen(Config::default()).unwrap(); -} \ No newline at end of file +} diff --git a/backend/migrations/.gitkeep b/backend/migrations/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/migrations/2021-07-08-184225_create_users/down.sql b/backend/migrations/2021-07-08-184225_create_users/down.sql deleted file mode 100644 index 02bd7940..00000000 --- a/backend/migrations/2021-07-08-184225_create_users/down.sql +++ /dev/null @@ -1 +0,0 @@ -drop table users; \ No newline at end of file diff --git a/backend/migrations/2021-07-08-184225_create_users/up.sql b/backend/migrations/2021-07-08-184225_create_users/up.sql deleted file mode 100644 index 54bb37a3..00000000 --- a/backend/migrations/2021-07-08-184225_create_users/up.sql +++ /dev/null @@ -1,10 +0,0 @@ -CREATE TABLE users -( - id BIGINT AUTO_INCREMENT PRIMARY KEY, - name TEXT, - username TEXT, - email TEXT, - password TEXT, - permissions TEXT, - created BIGINT -) \ No newline at end of file diff --git a/backend/migrations/2021-07-08-213104_create_session_tokens/down.sql b/backend/migrations/2021-07-08-213104_create_session_tokens/down.sql deleted file mode 100644 index 1dfc9981..00000000 --- a/backend/migrations/2021-07-08-213104_create_session_tokens/down.sql +++ /dev/null @@ -1 +0,0 @@ -drop table session_tokens; \ No newline at end of file diff --git a/backend/migrations/2021-07-08-213104_create_session_tokens/up.sql b/backend/migrations/2021-07-08-213104_create_session_tokens/up.sql deleted file mode 100644 index e480a602..00000000 --- a/backend/migrations/2021-07-08-213104_create_session_tokens/up.sql +++ /dev/null @@ -1,9 +0,0 @@ -CREATE TABLE session_tokens -( - id BIGINT AUTO_INCREMENT PRIMARY KEY, - user BIGINT, - token TEXT, - expiration BIGINT, - created BIGINT - -) \ No newline at end of file diff --git a/backend/migrations/2021-07-13-180028_create_forgot_password/down.sql b/backend/migrations/2021-07-13-180028_create_forgot_password/down.sql deleted file mode 100644 index e695f4ae..00000000 --- a/backend/migrations/2021-07-13-180028_create_forgot_password/down.sql +++ /dev/null @@ -1 +0,0 @@ -drop table forgot_password; \ No newline at end of file diff --git a/backend/migrations/2021-07-13-180028_create_forgot_password/up.sql b/backend/migrations/2021-07-13-180028_create_forgot_password/up.sql deleted file mode 100644 index 5052c423..00000000 --- a/backend/migrations/2021-07-13-180028_create_forgot_password/up.sql +++ /dev/null @@ -1,9 +0,0 @@ -CREATE TABLE forgot_passwords -( - id BIGINT AUTO_INCREMENT PRIMARY KEY, - user BIGINT, - token TEXT, - expiration BIGINT, - created BIGINT - -) \ No newline at end of file diff --git a/backend/migrations/2021-09-29-194126_create_auth_tokens/down.sql b/backend/migrations/2021-09-29-194126_create_auth_tokens/down.sql deleted file mode 100644 index 21d68943..00000000 --- a/backend/migrations/2021-09-29-194126_create_auth_tokens/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE auth_tokens; \ No newline at end of file diff --git a/backend/migrations/2021-09-29-194126_create_auth_tokens/up.sql b/backend/migrations/2021-09-29-194126_create_auth_tokens/up.sql deleted file mode 100644 index 629fd021..00000000 --- a/backend/migrations/2021-09-29-194126_create_auth_tokens/up.sql +++ /dev/null @@ -1,9 +0,0 @@ -CREATE TABLE auth_tokens -( - id BIGINT AUTO_INCREMENT PRIMARY KEY, - user BIGINT, - token TEXT, - expiration BIGINT, - created BIGINT - -) \ No newline at end of file diff --git a/backend/resources/email/forgot_password.html b/backend/resources/email/forgot_password.html deleted file mode 100644 index 716852be..00000000 --- a/backend/resources/email/forgot_password.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/backend/resources/pages/error/500.html b/backend/resources/pages/error/500.html deleted file mode 100644 index dfa2cebd..00000000 --- a/backend/resources/pages/error/500.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - Internal Server Error - - - - - \ No newline at end of file diff --git a/backend/src/api_response.rs b/backend/src/api_response.rs deleted file mode 100644 index a7689e94..00000000 --- a/backend/src/api_response.rs +++ /dev/null @@ -1,106 +0,0 @@ -use actix_web::http::StatusCode; -use actix_web::{HttpRequest, HttpResponse}; -use std::fmt::{Display, Formatter}; - -use crate::error::internal_error::InternalError; -use serde::{Deserialize, Serialize}; - -pub type SiteResponse = Result; - -#[derive(Debug, Serialize, Deserialize)] -pub struct APIResponse { - pub success: bool, - pub data: Option, - pub status_code: Option, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct RequestErrorResponse { - //User friendly messages will be provided for some cases - pub user_friendly_message: Option, - //Look into that specific API for what this will be set to. This is something that specific api will control - pub error_code: Option, -} -impl RequestErrorResponse { - pub fn new>(friendly: S, error: S) -> RequestErrorResponse { - RequestErrorResponse { - user_friendly_message: Some(friendly.into()), - error_code: Some(error.into()), - } - } -} - -impl Display for APIResponse { - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - write!(f, "{}", serde_json::to_string(self).unwrap()) - } -} - -impl Display for RequestErrorResponse { - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - write!(f, "{}", serde_json::to_string(self).unwrap()) - } -} - -impl From for APIResponse { - fn from(error: RequestErrorResponse) -> Self { - APIResponse::new(false, Some(error)) - } -} -impl From for APIResponse { - fn from(status: bool) -> Self { - APIResponse { - success: status, - data: Some(status), - status_code: None, - } - } -} -impl From> for APIResponse { - /// If the value is None it will create a 404 response - /// If the value is Some it will set Success to True and the data is provided - fn from(value: Option) -> Self { - if value.is_none() { - APIResponse { - success: true, - data: None, - status_code: Some(404), - } - } else { - APIResponse::::new(true, value) - } - } -} - -impl APIResponse { - pub fn new(success: bool, data: Option) -> APIResponse { - APIResponse { - success, - data, - status_code: None, - } - } - pub fn error(&self, status: StatusCode) -> SiteResponse { - return Ok(HttpResponse::Ok() - .status(status) - .content_type("application/json") - .body(serde_json::to_string(self).unwrap())); - } - pub fn respond(self, _req: &HttpRequest) -> SiteResponse { - let i = self.status_code.unwrap_or(200); - let result = HttpResponse::Ok() - .status(StatusCode::from_u16(i).unwrap_or(StatusCode::OK)) - .content_type("application/json") - .body(serde_json::to_string(&self).unwrap()); - Ok(result) - } - pub fn respond_new>>(response: S, _req: &HttpRequest) -> SiteResponse { - let response = response.into(); - let i = response.status_code.unwrap_or(200); - let result = HttpResponse::Ok() - .status(StatusCode::from_u16(i).unwrap_or(StatusCode::OK)) - .content_type("application/json") - .body(serde_json::to_string(&response).unwrap()); - Ok(result) - } -} diff --git a/backend/src/authentication/auth_token/database.rs b/backend/src/authentication/auth_token/database.rs new file mode 100644 index 00000000..bbff3fee --- /dev/null +++ b/backend/src/authentication/auth_token/database.rs @@ -0,0 +1,113 @@ +use std::convert::Infallible; + +use actix_web::dev::Payload; +use actix_web::{FromRequest, HttpMessage, HttpRequest}; +use futures_util::future::{ready, Ready}; + +use sea_orm::entity::prelude::*; +use sea_orm::JsonValue; +use serde::{Deserialize, Serialize}; + +use crate::system::user::{UserEntity, UserModel}; + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct TokenProperties { + pub description: Option, +} + +impl From for JsonValue { + fn from(auth: TokenProperties) -> Self { + serde_json::to_value(auth).unwrap() + } +} + +impl From for sea_orm::Value { + fn from(source: TokenProperties) -> Self { + sea_orm::Value::Json(Some(Box::new(source.into()))) + } +} + +impl sea_orm::TryGetable for TokenProperties { + fn try_get( + res: &sea_orm::QueryResult, + pre: &str, + col: &str, + ) -> Result { + let val: JsonValue = res.try_get(pre, col).map_err(sea_orm::TryGetError::DbErr)?; + serde_json::from_value(val) + .map_err(|e| sea_orm::TryGetError::DbErr(DbErr::Json(e.to_string()))) + } +} + +impl sea_orm::sea_query::ValueType for TokenProperties { + fn try_from(v: sea_orm::Value) -> Result { + match v { + sea_orm::Value::Json(Some(x)) => { + let auth_properties: TokenProperties = serde_json::from_value(*x) + .map_err(|_error| sea_orm::sea_query::ValueTypeErr)?; + Ok(auth_properties) + } + _ => Err(sea_orm::sea_query::ValueTypeErr), + } + } + + fn type_name() -> String { + stringify!(AuthProperties).to_owned() + } + + fn column_type() -> sea_orm::sea_query::ColumnType { + sea_orm::sea_query::ColumnType::Json + } +} + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] +#[sea_orm(table_name = "auth_tokens")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i64, + pub token: String, + pub expiration: i64, + pub properties: TokenProperties, + pub created: i64, + pub user_id: i64, +} + +impl Model { + pub async fn get_user( + &self, + database: &DatabaseConnection, + ) -> Result, DbErr> { + UserEntity::find_by_id(self.user_id).one(database).await + } +} + +impl FromRequest for Model { + type Error = Infallible; + type Future = Ready>; + + #[inline] + fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future { + let model = req.extensions_mut().get::().cloned().unwrap(); + ready(Ok(model)) + } +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "crate::system::user::database::Entity", + from = "Column::UserId", + to = "crate::system::user::database::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/backend/src/authentication/auth_token/mod.rs b/backend/src/authentication/auth_token/mod.rs new file mode 100644 index 00000000..e6e89e94 --- /dev/null +++ b/backend/src/authentication/auth_token/mod.rs @@ -0,0 +1,86 @@ +pub mod database; + +use crate::authentication::auth_token::database::TokenProperties; +use crate::error::internal_error::InternalError; +use crate::utils::get_current_time; +pub use database::Entity as AuthTokenEntity; +pub use database::Model as AuthTokenModel; +use log::error; +use rand::distributions::Alphanumeric; +use rand::Rng; +use sea_orm::FromQueryResult; +use sea_orm::{ColumnTrait, DatabaseConnection, EntityTrait, QueryFilter}; +use serde::{Deserialize, Serialize}; +use time::OffsetDateTime; + +#[derive(Debug, Clone, Serialize, Deserialize, FromQueryResult)] +pub struct TokenResponse { + pub id: i64, + pub expiration: i64, + pub properties: TokenProperties, + pub created: i64, + pub user_id: i64, +} + +pub async fn get_tokens_by_user( + user: i64, + database: &DatabaseConnection, +) -> Result, InternalError> { + AuthTokenEntity::find() + .filter(database::Column::UserId.eq(user)) + .into_model::() + .all(database) + .await + .map_err(InternalError::DBError) +} + +pub async fn get_by_token( + token: &str, + connection: &DatabaseConnection, +) -> Result, InternalError> { + let result = database::Entity::find() + .filter(database::Column::Token.eq(token)) + .one(connection) + .await?; + if let Some(token) = result { + // Delete Token if Expired + if token.expiration <= get_current_time() { + let database = connection.clone(); + actix_web::rt::spawn(async move { + let database = database; + if let Err(error) = AuthTokenEntity::delete_by_id(token.id) + .exec(&database) + .await + { + error!("Unable to delete Auth Token Error: {}", error); + } + }); + } + return Ok(Some(token)); + } + Ok(None) +} + +pub async fn delete_by_token( + token: &str, + connection: &DatabaseConnection, +) -> Result<(), InternalError> { + database::Entity::delete_many() + .filter(database::Column::Token.eq(token)) + .exec(connection) + .await?; + Ok(()) +} + +pub fn generate_token() -> String { + let token: String = rand::thread_rng() + .sample_iter(&Alphanumeric) + .take(24) + .map(char::from) + .collect(); + format!("nrp_{}", token) +} + +pub fn token_expiration(add: i64) -> i64 { + OffsetDateTime::now_utc().unix_timestamp() + add +} diff --git a/backend/src/authentication/middleware.rs b/backend/src/authentication/middleware.rs new file mode 100644 index 00000000..cd15d1a9 --- /dev/null +++ b/backend/src/authentication/middleware.rs @@ -0,0 +1,240 @@ +use std::fmt; +use std::future::{ready, Ready}; +use std::rc::Rc; + +use std::time::SystemTime; + +use crate::authentication::{ + auth_token, session::Session, session::SessionManager, verify_login, Authentication, +}; + +use actix_web::cookie::{Cookie, SameSite}; +use actix_web::http::header::{HeaderValue, AUTHORIZATION, ORIGIN, SET_COOKIE}; +use actix_web::http::Method; +use actix_web::{ + dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform}, + web, Error, HttpMessage, +}; + +use futures_util::future::LocalBoxFuture; +use log::{debug, trace, warn}; +use sea_orm::DatabaseConnection; + +use crate::authentication::session::SessionManagerType; + +pub struct HandleSession; + +impl Transform for HandleSession +where + S: Service, Error = Error> + 'static, + S::Future: 'static, + B: 'static, +{ + type Response = ServiceResponse; + type Error = Error; + type Transform = SessionMiddleware; + type InitError = (); + type Future = Ready>; + + fn new_transform(&self, service: S) -> Self::Future { + ready(Ok(SessionMiddleware { + service: Rc::new(service), + })) + } +} + +pub struct SessionMiddleware { + service: Rc, +} + +impl Service for SessionMiddleware +where + S: Service, Error = Error> + 'static, + S::Future: 'static, + B: 'static, +{ + type Response = ServiceResponse; + type Error = Error; + type Future = LocalBoxFuture<'static, Result>; + + forward_ready!(service); + + fn call(&self, req: ServiceRequest) -> Self::Future { + if req.method() == Method::OPTIONS { + let fut = self.service.call(req); + return Box::pin(async move { + let res = fut.await?; + Ok(res) + }); + } + let service: Rc = Rc::clone(&self.service); + trace!("Request at {}", req.path()); + // Move all into an Async Box. + Box::pin(async move { + //Step One Find the Authorization + let (authentication, session): (Authentication, Option) = if let Some(cookie) = + req.cookie("session") + { + //Check for the Session Cookie + let session_manager: &web::Data = req.app_data().unwrap(); + trace!("Cookie sent {}", cookie.encoded().to_string()); + let session = session_manager + .retrieve_session(cookie.value()) + .await + .unwrap(); + if session.is_none() { + //Create a new session and go with it! + let _session_manager: &web::Data = req.app_data().unwrap(); + if let Some(origin) = req.headers().get(ORIGIN) { + trace!( + "Cookie {} not found. Creating a new Session for {}", + cookie.value(), + origin.to_str().unwrap_or("Bad Origin") + ); + let session_manager: &web::Data = req.app_data().unwrap(); + let session = session_manager.create_session().await.unwrap(); + (Authentication::Session(session.clone()), Some(session)) + } else { + (Authentication::NoIdentification, Option::None) + } + } else { + let mut session = session.unwrap(); + if session.expiration <= SystemTime::UNIX_EPOCH { + session = session_manager + .re_create_session(&session.token) + .await + .unwrap(); + } + (Authentication::Session(session.clone()), Option::None) + } + } else if let Some(header) = req.headers().get(AUTHORIZATION) { + //If it is an Authorization Header pull Database from App Data + let database: &web::Data = req.app_data().unwrap(); + // Convert Header to String + let header_value = header.to_str().unwrap(); + trace!("Authorization Header {}", &header_value); + + let split = header_value.split(' ').collect::>(); + if split.len() != 2 { + debug!("Invalid Authorization Header!"); + // If the length is not correct. It is an invalid authorization. But let request continue + (Authentication::NoIdentification, Option::None) + } else { + let value = split.get(1).unwrap(); + let auth_type = split.get(0).unwrap(); + // If its a Bearer use the token System + if auth_type.eq(&"Bearer") { + trace!("Authorization Bearer (token)"); + + let auth_token = auth_token::get_by_token(value, database) + .await + .map_err(internal_server_error)?; + + if let Some(token) = auth_token { + (Authentication::AuthToken(token), Option::None) + } else { + (Authentication::NoIdentification, Option::None) + } + } else if auth_type.eq(&"Basic") { + //If its a Basic header. Parse from base64 + let base64 = base64::decode(value).map_err(request_error)?; + let string = String::from_utf8(base64).map_err(request_error)?; + let split = string.split(':').collect::>(); + + if split.len() != 2 { + debug!("Invalid Authorization Basic Header!"); + (Authentication::NoIdentification, Option::None) + } else { + let username = split.get(0).unwrap().to_string(); + let password = split.get(1).unwrap().to_string(); + // Maven will pass everything as a Basic. Setting the username as Token lets you use the token system + if username.eq("token") { + trace!("Authorization Basic token:(token)"); + + // Treat the password as a token + let auth_token = auth_token::get_by_token(&password, database) + .await + .map_err(internal_server_error)?; + if let Some(token) = auth_token { + (Authentication::AuthToken(token), Option::None) + } else { + (Authentication::NoIdentification, Option::None) + } + } else { + // Treat authorization as normal login + trace!("Authorization Basic username:password"); + let user = verify_login(username, password, database).await?; + if let Ok(user) = user { + trace!("Authorized User"); + (Authentication::Basic(user), None) + } else { + trace!("Invalid username:password combo"); + (Authentication::NoIdentification, None) + } + } + } + } else { + ( + Authentication::AuthorizationHeaderUnknown( + auth_type.to_string(), + value.to_string(), + ), + None, + ) + } + } + } else { + // Try to create a new Session for the user. Could be a first request + // Require a Origin Header for request + if let Some(origin) = req.headers().get(ORIGIN) { + trace!( + "Creating a new Session for {}. ", + origin.to_str().unwrap_or("Bad Origin") + ); + let session_manager: &web::Data = req.app_data().unwrap(); + let session = session_manager.create_session().await.unwrap(); + (Authentication::Session(session.clone()), Some(session)) + } else { + warn!("A Not Origin Not Authorized Request was made"); + (Authentication::NoIdentification, Option::None) + } + }; + // Add the authentication Information for the data + req.extensions_mut().insert(authentication); + // Finish the request + let fut = service.call(req); + // Get the response + let mut res: Self::Response = fut.await?; + // If a new cookie needs to be added. Do it + if let Some(session) = session { + let mut cookie = Cookie::new("session", &session.token); + cookie.set_secure(false); + cookie.set_same_site(SameSite::Lax); + cookie.set_path("/"); + cookie.set_expires(session.expiration); + let cookie_encoded = cookie.encoded().to_string(); + trace!("Sending Cookie Response {}", &cookie_encoded); + let val = HeaderValue::from_str(&cookie_encoded).unwrap(); + + res.headers_mut().append(SET_COOKIE, val); + } + Ok(res) + }) + } +} + +fn internal_server_error(err: E) -> Error { + actix_web::error::InternalError::from_response( + err, + actix_web::HttpResponse::InternalServerError().finish(), + ) + .into() +} + +fn request_error(err: E) -> Error { + actix_web::error::InternalError::from_response( + err, + actix_web::HttpResponse::BadRequest().finish(), + ) + .into() +} diff --git a/backend/src/authentication/mod.rs b/backend/src/authentication/mod.rs new file mode 100644 index 00000000..287a75d7 --- /dev/null +++ b/backend/src/authentication/mod.rs @@ -0,0 +1,132 @@ +pub mod auth_token; +pub mod middleware; +pub mod session; + +use actix_web::dev::Payload; +use actix_web::http::StatusCode; +use actix_web::{FromRequest, HttpMessage, HttpRequest, ResponseError}; +use argon2::{Argon2, PasswordHash, PasswordVerifier}; +use std::fmt::{Debug, Display, Formatter}; + +use futures_util::future::{ready, Ready}; +use log::trace; + +use sea_orm::{DatabaseConnection, EntityTrait}; + +use crate::authentication::auth_token::AuthTokenModel; +use crate::authentication::session::Session; +use crate::error::internal_error::InternalError; +use crate::system::user; + +use crate::system::user::{UserEntity, UserModel}; +pub struct NotAuthenticated; + +impl Debug for NotAuthenticated { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "Not Authenticated") + } +} + +impl Display for NotAuthenticated { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "Not Authenticated") + } +} + +impl ResponseError for NotAuthenticated { + fn status_code(&self) -> StatusCode { + StatusCode::UNAUTHORIZED + } +} +#[derive(Clone, Debug, PartialEq)] +pub enum Authentication { + /// Neither a Session or Auth Token exist. + /// Might deny these requests in the future on API routes + NoIdentification, + /// An Auth Token was passed under the Authorization Header + AuthToken(AuthTokenModel), + /// Session Value from Cookie + Session(Session), + /// If the Authorization Header could not be parsed. Give them the value + AuthorizationHeaderUnknown(String, String), + /// Authorization Basic Header + Basic(UserModel), +} + +impl Authentication { + pub fn authorized(&self) -> bool { + if let Authentication::NoIdentification = &self { + return false; + } + if let Authentication::Session(session) = &self { + return session.user.is_some(); + } + true + } + pub async fn get_user( + self, + database: &DatabaseConnection, + ) -> Result, InternalError> { + match self { + Authentication::AuthToken(auth) => { + let option = auth.get_user(database).await?; + if let Some(user) = option { + Ok(Ok(user)) + } else { + Ok(Err(NotAuthenticated)) + } + } + Authentication::Session(session) => { + if let Some(user) = session.user { + let option = UserEntity::find_by_id(user).one(database).await?; + if let Some(user) = option { + Ok(Ok(user)) + } else { + Ok(Err(NotAuthenticated)) + } + } else { + Ok(Err(NotAuthenticated)) + } + } + Authentication::Basic(user) => Ok(Ok(user)), + _ => Ok(Err(NotAuthenticated)), + } + } +} + +impl FromRequest for Authentication { + type Error = InternalError; + type Future = Ready>; + + #[inline] + fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future { + let model = req.extensions_mut().get::().cloned(); + if model.is_none() { + trace!("Missing Extension"); + return ready(Ok(Authentication::NoIdentification)); + } + + ready(Ok(model.unwrap())) + } +} + +pub async fn verify_login( + username: String, + password: String, + database: &DatabaseConnection, +) -> Result, InternalError> { + let user_found: Option = user::get_by_username(&username, database).await?; + if user_found.is_none() { + return Ok(Err(NotAuthenticated)); + } + let argon2 = Argon2::default(); + let user = user_found.unwrap(); + let parsed_hash = PasswordHash::new(user.password.as_str())?; + if argon2 + .verify_password(password.as_bytes(), &parsed_hash) + .is_err() + { + return Ok(Err(NotAuthenticated)); + } + Ok(Ok(user)) +} diff --git a/backend/src/authentication/session/basic/mod.rs b/backend/src/authentication/session/basic/mod.rs new file mode 100644 index 00000000..8b0450b2 --- /dev/null +++ b/backend/src/authentication/session/basic/mod.rs @@ -0,0 +1,96 @@ +use async_trait::async_trait; +use rand::distributions::Alphanumeric; +use rand::Rng; +use std::collections::HashMap; +use std::ops::Add; + +use crate::authentication::session::{Session, SessionManagerType}; +use time::{Duration, OffsetDateTime}; +use tokio::sync::RwLock; + +pub struct BasicSessionManager { + pub sessions: RwLock>, +} + +impl Default for BasicSessionManager { + fn default() -> Self { + BasicSessionManager { + sessions: RwLock::new(HashMap::new()), + } + } +} + +#[async_trait] +impl SessionManagerType for BasicSessionManager { + type Error = (); + + async fn delete_session(&self, token: &str) -> Result<(), Self::Error> { + let mut guard = self.sessions.write().await; + guard.remove(token); + return Ok(()); + } + + async fn create_session(&self) -> Result { + let mut guard = self.sessions.write().await; + let session = Session { + token: generate_token(), + user: None, + expiration: token_expiration(), + }; + guard.insert(session.token.clone(), session.clone()); + return Ok(session); + } + + async fn retrieve_session(&self, token: &str) -> Result, Self::Error> { + let guard = self.sessions.read().await; + for x in guard.iter() { + println!("{:?}", x.0); + } + return Ok(guard.get(token).cloned()); + } + + async fn re_create_session(&self, token: &str) -> Result { + let mut guard = self.sessions.write().await; + guard.remove(token); + + let session = Session { + token: generate_token(), + user: None, + expiration: token_expiration(), + }; + guard.insert(session.token.clone(), session.clone()); + return Ok(session); + } + + async fn set_user(&self, token: &str, user: i64) -> Result<(), Self::Error> { + let mut guard = self.sessions.write().await; + + for x in guard.iter() { + println!("{:?}", x.0); + } + let option = guard.get_mut(token); + if let Some(x) = option { + x.user = Some(user); + return Ok(()); + } + + log::warn!( + "A user was set to an Auth Token that does not exist! {}", + token + ); + return Ok(()); + } +} + +fn generate_token() -> String { + let token: String = rand::thread_rng() + .sample_iter(&Alphanumeric) + .take(12) + .map(char::from) + .collect(); + format!("nrs_{}", token) +} + +pub fn token_expiration() -> OffsetDateTime { + OffsetDateTime::now_utc().add(Duration::days(1)) +} diff --git a/backend/src/authentication/session/mod.rs b/backend/src/authentication/session/mod.rs new file mode 100644 index 00000000..e0765cb0 --- /dev/null +++ b/backend/src/authentication/session/mod.rs @@ -0,0 +1,75 @@ +pub mod basic; + +use crate::authentication::session::basic::BasicSessionManager; +use crate::settings::models::SessionSettings; +use async_trait::async_trait; +use time::OffsetDateTime; + +pub enum SessionManager { + BasicSessionManager(BasicSessionManager), +} + +#[derive(Clone, Debug, PartialEq)] +pub struct Session { + pub token: String, + pub user: Option, + pub expiration: OffsetDateTime, +} + +#[async_trait] +pub trait SessionManagerType { + type Error; + async fn delete_session(&self, token: &str) -> Result<(), Self::Error>; + async fn create_session(&self) -> Result; + async fn retrieve_session(&self, token: &str) -> Result, Self::Error>; + async fn re_create_session(&self, token: &str) -> Result; + async fn set_user(&self, token: &str, user: i64) -> Result<(), Self::Error>; +} + +#[async_trait] +impl SessionManagerType for SessionManager { + type Error = (); + + async fn delete_session(&self, token: &str) -> Result<(), Self::Error> { + return match self { + SessionManager::BasicSessionManager(basic) => basic.delete_session(token).await, + }; + } + + async fn create_session(&self) -> Result { + return match self { + SessionManager::BasicSessionManager(basic) => basic.create_session().await, + }; + } + + async fn retrieve_session(&self, token: &str) -> Result, Self::Error> { + return match self { + SessionManager::BasicSessionManager(basic) => basic.retrieve_session(token).await, + }; + } + + async fn re_create_session(&self, token: &str) -> Result { + return match self { + SessionManager::BasicSessionManager(basic) => basic.re_create_session(token).await, + }; + } + + async fn set_user(&self, token: &str, user: i64) -> Result<(), Self::Error> { + return match self { + SessionManager::BasicSessionManager(basic) => basic.set_user(token, user).await, + }; + } +} + +impl TryFrom for SessionManager { + type Error = String; + + fn try_from(value: SessionSettings) -> Result { + return match value.manager.as_str() { + "BasicSessionManager" => Ok(SessionManager::BasicSessionManager( + BasicSessionManager::default(), + )), + _ => Err("Invalid Session Manager".to_string()), + }; + } +} diff --git a/backend/src/bin/nitro_repo_full.rs b/backend/src/bin/nitro_repo_full.rs new file mode 100644 index 00000000..1bfa0956 --- /dev/null +++ b/backend/src/bin/nitro_repo_full.rs @@ -0,0 +1,118 @@ +use std::env::current_dir; +use std::error::Error; +use std::io::ErrorKind; +use std::net::ToSocketAddrs; +use std::process::exit; +use std::rc::Rc; +use actix_cors::Cors; +use actix_web::{App, HttpServer, web}; +use actix_web::guard::GuardContext; +use actix_web::web::Data; +use log::{info, trace}; +use semver::Version; +use tokio::fs::read_to_string; +use tokio::sync::RwLock; +use api::cli::handle_cli; +use api::{frontend, NitroRepo, storage, system}; +use api::settings::load_configs; +use api::settings::models::GeneralSettings; +use api::storage::multi::MultiStorageController; +use api::utils::load_logger; +use actix_web::main; +use sea_orm::DatabaseConnection; +use api::authentication::middleware::HandleSession; +use api::authentication::session::SessionManager; + +#[main] +async fn main() -> std::io::Result<()> { + if handle_cli().await.map_err(convert_error)? { + return Ok(()); + } + let current_dir = current_dir()?; + let configs = current_dir.join("cfg"); + let main_config = current_dir.join("nitro_repo.toml"); + if !main_config.exists() { + eprintln!("Config not found. Should be at {:?}", main_config.as_os_str()); + exit(1) + } + + let init_settings: GeneralSettings = toml::from_str(&read_to_string(&main_config).await?).map_err(convert_error)?; + let version = Version::parse(&init_settings.internal.version).map_err(convert_error)?; + // Sets the Log Location + std::env::set_var("LOG_LOCATION", &init_settings.application.log); + load_logger(&init_settings.application.mode); + info!("Initializing Database Connection"); + let connection = sea_orm::Database::connect(init_settings.database.clone()).await.map_err(convert_error)?; + info!("Initializing Session and Authorization"); + let session_manager = SessionManager::try_from(init_settings.session.clone()).unwrap(); + info!("Initializing State"); + let settings = load_configs(configs).await.map_err(convert_error)?; + + + let storages = current_dir.join("storages.json"); + let storages = MultiStorageController::init(storages).await.map_err(convert_error)?; + + let nitro_repo = NitroRepo { + settings: RwLock::new(settings), + core: init_settings, + current_version: version, + }; + + let application = nitro_repo.core.application.clone(); + + let max_upload = application.max_upload; + + let address = application.address.clone(); + let storages_data = Data::new(storages); + let site_state = Data::new(nitro_repo); + let database_data = Data::new(connection); + let session_data = Data::new(session_manager); + + let server = HttpServer::new(move || { + App::new(). + app_data(storages_data.clone()). + app_data(site_state.clone()). + app_data(database_data.clone()). + app_data(session_data.clone()) + .wrap( + Cors::default() + .allow_any_header() + .allow_any_method() + .allow_any_origin().supports_credentials(), + ) + .service( + web::scope("/api") + .wrap(HandleSession {}) + .configure(system::web::init_public_routes) + .configure(system::web::user_routes) + .service(web::scope("/admin") + .configure(system::web::init_user_manager_routes) + .configure(storage::multi::web::init_admin_routes) + ) + ) + .configure(frontend::init) + }); + + #[cfg(feature = "ssl")] + { + if let Some(private) = application.ssl_private_key { + let cert = application + .ssl_cert_key + .expect("If Private Key is set. CERT Should be set"); + use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; + + let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); + builder + .set_private_key_file(private, SslFiletype::PEM) + .unwrap(); + builder.set_certificate_chain_file(cert).unwrap(); + return server.bind_openssl(address, builder)?.run().await; + } + } + + return server.bind(address)?.run().await; +} + +fn convert_error>>(e: E) -> std::io::Error { + std::io::Error::new(ErrorKind::Other, e) +} \ No newline at end of file diff --git a/backend/src/cli/mod.rs b/backend/src/cli/mod.rs new file mode 100644 index 00000000..70eac3d9 --- /dev/null +++ b/backend/src/cli/mod.rs @@ -0,0 +1,49 @@ +use std::env::current_dir; +use crate::install::load_installer; +use crate::settings::models::Mode; +use crate::updater; +use crate::utils::load_logger; +use clap::Parser; +use log::error; +use std::path::Path; +use style_term::{DefaultColor, StyleString}; + +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct NitroRepoCLI { + #[clap(short, long)] + install: bool, + #[clap(short, long)] + update: Option, +} + +pub async fn handle_cli() -> std::io::Result { + let path = current_dir()?; + + let parse: NitroRepoCLI = NitroRepoCLI::parse(); + if parse.install { + load_logger(Mode::Install); + if let Err(error) = load_installer(path).await { + error!("Unable to complete Install {error}"); + println!( + "{}", + "Unable to Complete Installation" + .style() + .text_color(DefaultColor::Red) + ); + } + return Ok(true); + } else if let Some(update) = parse.update { + if let Err(error) = updater::update(update).await { + error!("Unable to complete update {error}"); + println!( + "{}", + "Unable to Complete Update" + .style() + .text_color(DefaultColor::Red) + ); + } + return Ok(true); + } + Ok(false) +} diff --git a/backend/src/database.rs b/backend/src/database.rs deleted file mode 100644 index 01dd11e0..00000000 --- a/backend/src/database.rs +++ /dev/null @@ -1,29 +0,0 @@ -use actix_web::web; -use anyhow::Result; -use diesel::r2d2::ConnectionManager; -use diesel::{Connection, MysqlConnection}; -use diesel_migrations::embed_migrations; -use log::info; - -pub type DbPool = r2d2::Pool>; -pub type Database = web::Data; -embed_migrations!(); - -pub fn init(db_url: &str) -> Result { - info!("Loading Database"); - let manager = ConnectionManager::::new(db_url); - let pool = DbPool::new(manager)?; - let conn = pool.get()?; - info!("Checking and Running Migrations"); - embedded_migrations::run(&conn)?; - Ok(pool) -} - -pub fn init_single_connection(db_url: &str) -> Result { - info!("Loading Database"); - let connection = MysqlConnection::establish(db_url)?; - - info!("Checking and Running Migrations"); - embedded_migrations::run(&connection)?; - Ok(connection) -} diff --git a/backend/src/error/api_error.rs b/backend/src/error/api_error.rs new file mode 100644 index 00000000..8193735a --- /dev/null +++ b/backend/src/error/api_error.rs @@ -0,0 +1,80 @@ +use actix_web::body::BoxBody; +use actix_web::http::StatusCode; + +use actix_web::{HttpResponse, HttpResponseBuilder, ResponseError}; +use serde_json::json; +use std::error::Error; +use std::fmt::{Debug, Display, Formatter}; + +pub struct APIError { + pub message: Option, + pub status_code: StatusCode, +} +impl APIError { + pub fn bad_request(error: E) -> APIError { + APIError { + message: Some(error.to_string()), + status_code: StatusCode::BAD_REQUEST, + } + } + pub fn internal_error(error: E) -> APIError { + APIError { + message: Some(error.to_string()), + status_code: StatusCode::INTERNAL_SERVER_ERROR, + } + } + pub fn not_found() -> APIError { + APIError { + message: None, + status_code: StatusCode::NOT_FOUND, + } + } +} +impl From<(&str, StatusCode)> for APIError { + fn from((message, status): (&str, StatusCode)) -> Self { + APIError { + message: Some(message.to_string()), + status_code: status, + } + } +} +impl Debug for APIError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + if let Some(message) = &self.message { + write!( + f, + "Status Code: {} Error: {}", + self.status_code.to_string(), + message + ) + } else { + write!(f, "Status Code: {}", self.status_code.to_string(),) + } + } +} + +impl Display for APIError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + if let Some(message) = &self.message { + write!( + f, + "Status Code: {} Error: {}", + self.status_code.to_string(), + message + ) + } else { + write!(f, "Status Code: {}", self.status_code.to_string(),) + } + } +} + +impl ResponseError for APIError { + fn status_code(&self) -> StatusCode { + self.status_code + } + fn error_response(&self) -> HttpResponse { + HttpResponseBuilder::new(self.status_code).json(json!({ + "error": self.to_string(), + })) + } +} diff --git a/backend/src/error/handlers/json_error.rs b/backend/src/error/handlers/json_error.rs index 5b77f4c0..c81ea8ba 100644 --- a/backend/src/error/handlers/json_error.rs +++ b/backend/src/error/handlers/json_error.rs @@ -1,35 +1,14 @@ -use crate::api_response::{APIResponse, RequestErrorResponse}; -use actix_web::error::JsonPayloadError; +use actix_web::error::{ErrorBadRequest, JsonPayloadError}; + use actix_web::web::JsonConfig; use actix_web::HttpRequest; +use log::trace; pub fn json_config() -> JsonConfig { JsonConfig::default().error_handler(handle) } pub fn handle(payload: JsonPayloadError, _request: &HttpRequest) -> actix_web::Error { - match payload { - JsonPayloadError::ContentType => actix_web::error::ErrorBadRequest(APIResponse::from( - RequestErrorResponse::new("Json Bad Content Type", "CONTENT_TYPE"), - )), - JsonPayloadError::Deserialize(_) => actix_web::error::ErrorBadRequest(APIResponse::from( - RequestErrorResponse::new("Invalid Json", "JSON"), - )), - JsonPayloadError::Payload(_) => actix_web::error::ErrorBadRequest(APIResponse::from( - RequestErrorResponse::new("BAD PAYLOAD", "PAYLOAD"), - )), - JsonPayloadError::OverflowKnownLength { .. } => actix_web::error::ErrorBadRequest( - APIResponse::from(RequestErrorResponse::new("BAD PAYLOAD", "PAYLOAD")), - ), - JsonPayloadError::Serialize(_) => actix_web::error::ErrorBadRequest(APIResponse::from( - RequestErrorResponse::new("BAD PAYLOAD", "PAYLOAD"), - )), - JsonPayloadError::Overflow { .. } => actix_web::error::ErrorBadRequest(APIResponse::from( - RequestErrorResponse::new("Json Overflow", "INTERNAL"), - )), - _ => actix_web::error::ErrorBadRequest(APIResponse::from(RequestErrorResponse::new( - "Json Overflow", - "INTERNAL", - ))), - } + trace!("JSON Error: {}", payload); + ErrorBadRequest(format!("Bad Json Payload {}", payload.to_string())) } diff --git a/backend/src/error/internal_error.rs b/backend/src/error/internal_error.rs index acb0edda..0fba5463 100644 --- a/backend/src/error/internal_error.rs +++ b/backend/src/error/internal_error.rs @@ -3,12 +3,16 @@ use std::str::ParseBoolError; use std::string::FromUtf8Error; use std::time::SystemTimeError; -use actix_web::http::StatusCode; -use actix_web::HttpResponse; +use crate::storage::error::StorageError; + +use crate::system::permissions::PermissionError; + +use actix_web::ResponseError; use base64::DecodeError; use thiserror::Error; -use crate::system::permissions::PermissionError; +/// Errors that happen internally to the system. +/// Not as a direct result of a Request #[derive(Error, Debug)] pub enum InternalError { #[error("JSON error {0}")] @@ -16,11 +20,7 @@ pub enum InternalError { #[error("IO error {0}")] IOError(std::io::Error), #[error("DB error {0}")] - DBError(diesel::result::Error), - #[error("Actix Error")] - ActixWebError(actix_web::Error), - #[error("R2d2 Parse Error")] - R2D2Error(r2d2::Error), + DBError(sea_orm::error::DbErr), #[error("Boolean Parse Error")] BooleanParseError(ParseBoolError), #[error("Decode Error")] @@ -29,44 +29,19 @@ pub enum InternalError { UTF8Error(FromUtf8Error), #[error("SMTP Error")] SMTPTransportError(lettre::transport::smtp::Error), - #[error("Missing Argument {0}")] - MissingArgument(String), - #[error("Not Found")] - NotFound, #[error("Internal Error {0}")] Error(String), #[error("Missing Config Value {0}")] ConfigError(String), + #[error("Storage Error: {0}")] + StorageError(StorageError), #[error("Invalid Repository Type {0}")] InvalidRepositoryType(String), - #[error("Permission Error: {0}")] - PermissionError(crate::system::permissions::PermissionError), - #[error("THE INTERNAL WEBSITE HAS BROKEN DOWN. PLEASE REPORT to https://github.com/wherkamp/nitro_repo and restart application")] - DeadSite, -} - -pub type NResult = Result; - -impl InternalError { - pub fn json_error(&self) -> HttpResponse { - let result = HttpResponse::Ok() - .status(StatusCode::INTERNAL_SERVER_ERROR) - .content_type("text/plain") - .body(self.to_string()); - result - } -} - -impl actix_web::error::ResponseError for InternalError { - fn error_response(&self) -> HttpResponse { - self.json_error() - } } - -//from -impl From for InternalError { - fn from(err: PermissionError) -> InternalError { - InternalError::PermissionError(err) +impl ResponseError for InternalError {} +impl From for InternalError { + fn from(storage_error: StorageError) -> Self { + InternalError::StorageError(storage_error) } } @@ -82,6 +57,18 @@ impl From for InternalError { } } +impl From for InternalError { + fn from(err: std::io::Error) -> InternalError { + InternalError::IOError(err) + } +} + +impl From for InternalError { + fn from(err: serde_json::Error) -> InternalError { + InternalError::JSONError(err) + } +} + impl From for InternalError { fn from(err: FromUtf8Error) -> InternalError { InternalError::UTF8Error(err) @@ -94,18 +81,12 @@ impl From> for InternalError { } } -impl From for InternalError { - fn from(err: diesel::result::Error) -> InternalError { +impl From for InternalError { + fn from(err: sea_orm::DbErr) -> InternalError { InternalError::DBError(err) } } -impl From for InternalError { - fn from(err: r2d2::Error) -> InternalError { - InternalError::R2D2Error(err) - } -} - impl From for InternalError { fn from(err: argon2::password_hash::Error) -> InternalError { InternalError::Error(err.to_string()) @@ -118,30 +99,12 @@ impl From for InternalError { } } -impl From for InternalError { - fn from(err: serde_json::Error) -> InternalError { - InternalError::JSONError(err) - } -} - -impl From for InternalError { - fn from(err: actix_web::Error) -> InternalError { - InternalError::ActixWebError(err) - } -} - impl From for InternalError { fn from(err: SystemTimeError) -> InternalError { InternalError::Error(err.to_string()) } } -impl From for InternalError { - fn from(err: std::io::Error) -> InternalError { - InternalError::IOError(err) - } -} - impl From for InternalError { fn from(err: lettre::transport::smtp::Error) -> InternalError { InternalError::SMTPTransportError(err) @@ -153,9 +116,8 @@ impl From for InternalError { InternalError::BooleanParseError(err) } } - -impl From<&str> for InternalError { - fn from(error: &str) -> Self { - InternalError::Error(error.to_string()) +impl From for InternalError { + fn from(err: PermissionError) -> InternalError { + InternalError::ConfigError(err.to_string()) } } diff --git a/backend/src/error/mod.rs b/backend/src/error/mod.rs index 30cba2b8..7e17c36d 100644 --- a/backend/src/error/mod.rs +++ b/backend/src/error/mod.rs @@ -1,3 +1,3 @@ +pub mod api_error; pub mod handlers; pub mod internal_error; -pub mod response; diff --git a/backend/src/error/response.rs b/backend/src/error/response.rs deleted file mode 100644 index 7808d6dc..00000000 --- a/backend/src/error/response.rs +++ /dev/null @@ -1,102 +0,0 @@ -use crate::api_response::{APIResponse, RequestErrorResponse, SiteResponse}; -use actix_web::http::StatusCode; - -pub fn invalid_login() -> SiteResponse { - APIResponse::::new(false, None).error(StatusCode::UNAUTHORIZED) -} - -pub fn mismatching_passwords() -> SiteResponse { - APIResponse::new( - false, - Some(RequestErrorResponse { - user_friendly_message: None, - error_code: Some("MISMATCHING_PASSWORDS".to_string()), - }), - ) - .error(StatusCode::BAD_REQUEST) -} - -pub fn not_found() -> SiteResponse { - APIResponse::::new(false, None).error(StatusCode::NOT_FOUND) -} - -pub fn unauthorized() -> SiteResponse { - APIResponse::::new(false, None).error(StatusCode::UNAUTHORIZED) -} - -pub fn already_exists() -> SiteResponse { - APIResponse::new( - false, - Some(RequestErrorResponse { - user_friendly_message: None, - error_code: Some("ALREADY_EXISTS".to_string()), - }), - ) - .error(StatusCode::CONFLICT) -} - -pub fn already_exists_what>(value: T) -> SiteResponse { - APIResponse::new( - false, - Some(RequestErrorResponse { - user_friendly_message: None, - error_code: Some(value.into()), - }), - ) - .error(StatusCode::CONFLICT) -} - -pub fn uninstalled() -> SiteResponse { - APIResponse::new( - false, - Some(RequestErrorResponse { - user_friendly_message: None, - error_code: Some("UNINSTALLED".to_string()), - }), - ) - .error(StatusCode::BAD_GATEWAY) -} - -pub fn i_am_a_teapot>(value: S) -> SiteResponse { - APIResponse::new( - false, - Some(RequestErrorResponse { - user_friendly_message: Some(value.into()), - error_code: None, - }), - ) - .error(StatusCode::IM_A_TEAPOT) -} - -pub fn bad_request>(value: S) -> SiteResponse { - APIResponse::new( - false, - Some(RequestErrorResponse { - user_friendly_message: Some(value.into()), - error_code: None, - }), - ) - .error(StatusCode::BAD_REQUEST) -} - -pub fn missing_arguments>(value: S) -> SiteResponse { - APIResponse::new( - false, - Some(RequestErrorResponse { - user_friendly_message: Some(value.into()), - error_code: Some("MISSING_ARGUMENT".to_string()), - }), - ) - .error(StatusCode::BAD_REQUEST) -} - -pub fn error>(value: S, status: Option) -> SiteResponse { - APIResponse::new( - false, - Some(RequestErrorResponse { - user_friendly_message: Some(value.into()), - error_code: None, - }), - ) - .error(status.unwrap_or(StatusCode::BAD_REQUEST)) -} diff --git a/backend/src/frontend/controllers.rs b/backend/src/frontend/controllers.rs index f1ed323c..feb58c75 100644 --- a/backend/src/frontend/controllers.rs +++ b/backend/src/frontend/controllers.rs @@ -1,14 +1,14 @@ -use std::fs::{read_to_string}; +use std::fs::read_to_string; use std::path::Path; use actix_files::Files; +use actix_web::error::ErrorInternalServerError; use actix_web::web::Data; use actix_web::{web, HttpResponse}; use handlebars::Handlebars; use log::{debug, trace, warn}; use serde_json::json; -use crate::api_response::SiteResponse; use crate::NitroRepoData; pub fn init(cfg: &mut web::ServiceConfig) { @@ -22,8 +22,7 @@ pub fn init(cfg: &mut web::ServiceConfig) { return; } let mut reg = Handlebars::new(); - let content = read_to_string(index) - .expect("Unable to read index.html"); + let content = read_to_string(index).expect("Unable to read index.html"); reg.register_template_string("index", content) .expect("Unable to Parse Template"); let reg = Data::new(reg); @@ -40,11 +39,15 @@ pub fn init(cfg: &mut web::ServiceConfig) { .service(Files::new("/", frontend_path).show_files_listing()); } - -pub async fn frontend_handler(hb: web::Data>, site: NitroRepoData) -> SiteResponse { +pub async fn frontend_handler( + hb: web::Data>, + site: NitroRepoData, +) -> Result { let guard = site.settings.read().await; let value = json!({"base_url": site.core.application.app_url, "title": guard.site.name,"description": guard.site.description}); - let content = hb.render("index", &value)?; + let content = hb + .render("index", &value) + .map_err(ErrorInternalServerError)?; return Ok(HttpResponse::Ok().content_type("text/html").body(content)); } diff --git a/backend/src/install/mod.rs b/backend/src/install/mod.rs index e5fd07f5..78b00083 100644 --- a/backend/src/install/mod.rs +++ b/backend/src/install/mod.rs @@ -1,24 +1,15 @@ use std::io; -use crate::database::init_single_connection; - use log::{error, info, trace}; use serde::{Deserialize, Serialize}; -use crate::system::action::add_new_user; - -use crate::system::models::{User}; - -use crossterm::{ - event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, - execute, - terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, -}; -use diesel::MysqlConnection; +use crossterm::{event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, ExecutableCommand, execute, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}}; +use sea_orm::ActiveValue::Set; +use sea_orm::{DatabaseConnection, EntityTrait, Schema}; use std::fmt::{Display, Formatter}; use std::fs::{create_dir_all, OpenOptions}; use std::io::{Stdout, Write}; -use std::path::Path; +use std::path::{Path, PathBuf}; use tui::{ backend::{Backend, CrosstermBackend}, layout::{Constraint, Direction, Layout}, @@ -30,12 +21,15 @@ use tui::{ use thiserror::Error; -use crate::settings::models::{Application, Database}; +use crate::settings::models::{Application, Database, EmailSetting, Mode, MysqlSettings, SecuritySettings, SiteSetting, StringMap}; +use crate::system::permissions::UserPermissions; +use crate::system::user; +use crate::system::user::UserEntity; use crate::system::utils::hash; use crate::utils::get_current_time; -use crate::{EmailSetting, GeneralSettings, Mode, SecuritySettings, SiteSetting, StringMap}; +use crate::{authentication, GeneralSettings}; +use sea_orm::ConnectionTrait; use unicode_width::UnicodeWidthStr; -use crate::system::permissions::UserPermissions; #[derive(Error, Debug)] pub enum InstallError { @@ -57,6 +51,12 @@ impl From for InstallError { } } +impl std::convert::From for InstallError { + fn from(error: sea_orm::DbErr) -> Self { + InstallError::InstallError(error.to_string()) + } +} + //mysql://newuser:"password"@127.0.0.1/nitro_repo #[derive(Serialize, Deserialize, Clone, Debug)] struct DatabaseStage { @@ -66,17 +66,15 @@ struct DatabaseStage { pub database: Option, } -impl From for Database { +impl From for Database { fn from(db: DatabaseStage) -> Self { - let mut map = StringMap::new(); - map.insert("user".to_string(), db.user.unwrap()); - map.insert("password".to_string(), db.password.unwrap()); - map.insert("host".to_string(), db.host.unwrap()); - map.insert("database".to_string(), db.database.unwrap()); - Self { - db_type: "mysql".to_string(), - settings: map, - } + let mysql_settings = MysqlSettings { + user: db.user.unwrap(), + password: db.password.unwrap(), + host: db.host.unwrap(), + database: db.database.unwrap(), + }; + crate::settings::models::Database::Mysql(mysql_settings) } } @@ -103,23 +101,25 @@ pub struct UserStage { pub password_two: Option, } -impl From for User { +impl From for user::database::ActiveModel { fn from(value: UserStage) -> Self { - User { - id: 0, - name: value.name.unwrap_or_default(), - username: value.username.unwrap_or_default(), - email: value.email.unwrap_or_default(), - password: hash(value.password.unwrap_or_default()).unwrap(), - permissions: UserPermissions { + user::database::ActiveModel { + id: Default::default(), + name: Set(value.name.unwrap_or_default()), + username: Set(value.username.unwrap_or_default()), + email: Set(value.email.unwrap_or_default()), + password: Set(hash(value.password.unwrap_or_default()).unwrap()), + permissions: Set(UserPermissions { disabled: false, admin: true, user_manager: true, repository_manager: true, deployer: None, - viewer: None - }, - created: get_current_time(), + viewer: None, + } + .try_into() + .unwrap()), + created: Set(get_current_time()), } } } @@ -156,7 +156,7 @@ struct App { database_stage: DatabaseStage, user_stage: UserStage, other_stage: OtherStage, - connection: Option, + connection: Option, } impl Default for App { @@ -188,7 +188,7 @@ impl Default for App { } } -fn run_app( +async fn run_app( mut terminal: Terminal>, mut app: App, ) -> Result { @@ -221,25 +221,21 @@ fn run_app( } else { let string = app.database_stage.to_string(); trace!("Database String: {}", &string); - let result = init_single_connection(&string); - match result { - Ok(db) => { - app.connection = Some(db); - app.stage = 1; - } - Err(error) => { - error!( - "Unable to Connect to Database {} :{}", - string, error - ); - app.database_stage = DatabaseStage { - user: None, - password: None, - host: None, - database: None, - } - } - } + let database_conn = sea_orm::Database::connect(string).await?; + let schema = Schema::new(database_conn.get_database_backend()); + let users = schema.create_table_from_entity(UserEntity); + database_conn + .execute(database_conn.get_database_backend().build(&users)) + .await?; + let tokens = schema.create_table_from_entity( + authentication::auth_token::AuthTokenEntity, + ); + database_conn + .execute(database_conn.get_database_backend().build(&tokens)) + .await?; + + app.connection = Some(database_conn); + app.stage = 1; } } 1 => { @@ -256,11 +252,8 @@ fn run_app( let stage = app.user_stage.clone(); //TODO dont kill program on failure to create user - if let Err(error) = add_new_user(&stage.into(), connection) { - error!("Unable to Create user, {}", error); - std::process::exit(1); - } - + let user: user::database::ActiveModel = stage.into(); + UserEntity::insert(user).exec(connection).await?; app.stage = 2; } } @@ -388,7 +381,7 @@ fn ui(f: &mut Frame, app: &App) { Constraint::Length(1), Constraint::Length(3), ] - .as_ref(), + .as_ref(), ) .split(f.size()); let mut messages: Vec = Vec::new(); @@ -510,29 +503,30 @@ fn ui(f: &mut Frame, app: &App) { ) } -pub fn load_installer(config: &Path) -> anyhow::Result<()> { +pub async fn load_installer(working_dir: PathBuf) -> anyhow::Result<()> { enable_raw_mode()?; let mut stdout = io::stdout(); execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?; let backend = CrosstermBackend::new(stdout); let terminal = Terminal::new(backend)?; - let app = run_app(terminal, App::default())?; + let app = run_app(terminal, App::default()).await?; let general = GeneralSettings { database: app.database_stage.into(), application: Application::from(app.other_stage), internal: Default::default(), - env: Default::default() + session: Default::default(), }; - create_dir_all(config)?; + let configs = working_dir.join("cfg"); + create_dir_all(&configs)?; let other = toml::to_string_pretty(&general)?; let mut file = OpenOptions::new() .write(true) .append(true) .create(true) - .open(config.join("nitro_repo.toml"))?; + .open(working_dir.join("nitro_repo.toml"))?; file.write_all(other.as_bytes())?; let security = toml::to_string_pretty(&SecuritySettings::default())?; @@ -540,7 +534,7 @@ pub fn load_installer(config: &Path) -> anyhow::Result<()> { .write(true) .append(true) .create(true) - .open(config.join("security.toml"))?; + .open(configs.join("security.toml"))?; file.write_all(security.as_bytes())?; let email = toml::to_string_pretty(&EmailSetting::default())?; @@ -548,14 +542,14 @@ pub fn load_installer(config: &Path) -> anyhow::Result<()> { .write(true) .append(true) .create(true) - .open(config.join("email.toml"))?; + .open(configs.join("email.toml"))?; file.write_all(email.as_bytes())?; let site = toml::to_string_pretty(&SiteSetting::default())?; let mut file = OpenOptions::new() .write(true) .append(true) .create(true) - .open(config.join("site.toml"))?; + .open(configs.join("site.toml"))?; file.write_all(site.as_bytes())?; info!("Installation Complete"); Ok(()) @@ -568,6 +562,6 @@ fn close(mut terminal: Terminal>) { LeaveAlternateScreen, DisableMouseCapture ) - .unwrap(); + .unwrap(); terminal.show_cursor().unwrap(); } diff --git a/backend/src/lib.rs b/backend/src/lib.rs new file mode 100644 index 00000000..240ba08e --- /dev/null +++ b/backend/src/lib.rs @@ -0,0 +1,25 @@ +pub mod authentication; +pub mod cli; +pub mod constants; +pub mod error; +pub mod frontend; +pub mod install; +pub mod repository; +pub mod settings; +pub mod storage; +pub mod system; +pub mod updater; +pub mod utils; + +use crate::settings::models::{GeneralSettings, Settings}; +use actix_web::web::Data; +use tokio::sync::RwLock; + +#[derive(Debug)] +pub struct NitroRepo { + pub settings: RwLock, + pub core: GeneralSettings, + pub current_version: semver::Version, +} + +pub type NitroRepoData = Data; diff --git a/backend/src/main.rs b/backend/src/main.rs deleted file mode 100644 index c0fc06f1..00000000 --- a/backend/src/main.rs +++ /dev/null @@ -1,211 +0,0 @@ -#[macro_use] -extern crate diesel; -#[macro_use] -extern crate diesel_migrations; - -use actix_cors::Cors; -use actix_web::web::{Data, PayloadConfig}; -use actix_web::{middleware, web, App, HttpServer}; -use std::fs::read_to_string; -use std::path::Path; - -use log::{error, info, trace}; -use nitro_log::config::Config; -use nitro_log::{LoggerBuilders, NitroLogger}; - -use crate::api_response::{APIResponse, SiteResponse}; -use crate::utils::Resources; - -pub mod database; - -pub mod api_response; -pub mod constants; -pub mod error; -pub mod frontend; -pub mod install; -mod misc; -pub mod repository; -pub mod schema; -pub mod settings; -pub mod storage; -pub mod system; -pub mod utils; -pub mod webhook; - -use crate::database::Database; -use crate::install::load_installer; -use crate::settings::models::{ - EmailSetting, GeneralSettings, Mode, MysqlSettings, SecuritySettings, Settings, SiteSetting, - StringMap, -}; -use crate::storage::models::{load_storages, Storages}; -use clap::Parser; -use tokio::sync::RwLock; -use style_term::{DefaultColor, StyleString}; - -#[derive(Parser, Debug)] -#[clap(author, version, about, long_about = None)] -struct Cli { - #[clap(short, long)] - install: bool, -} - -#[derive(Debug)] -pub struct NitroRepo { - storages: RwLock, - settings: RwLock, - core: GeneralSettings, -} - -pub type NitroRepoData = Data; - -fn load_configs() -> anyhow::Result { - let cfgs = Path::new("cfg"); - - let security: SecuritySettings = toml::from_str(&read_to_string(cfgs.join("security.toml"))?)?; - let site: SiteSetting = toml::from_str(&read_to_string(cfgs.join("site.toml"))?)?; - let email: EmailSetting = toml::from_str(&read_to_string(cfgs.join("email.toml"))?)?; - - Ok(Settings { - email, - site, - security, - }) -} - -fn load_logger>(logger: T) { - let file = match logger.as_ref() { - Mode::Debug => "log-debug.json", - Mode::Release => "log-release.json", - Mode::Install => "log-install.json", - }; - let config: Config = serde_json::from_str(Resources::file_get_string(file).as_str()).unwrap(); - NitroLogger::load(config, LoggerBuilders::default()).unwrap(); -} - -#[actix_web::main] -async fn main() -> std::io::Result<()> { - let path = Path::new("cfg"); - let main_config = path.join("nitro_repo.toml"); - if !main_config.exists() { - let parse: Cli = Cli::parse(); - if parse.install { - load_logger(Mode::Install); - if let Err(error) = load_installer(path) { - error!("Unable to complete Install {error}"); - println!("{}", "Unable to Complete Installation".style().text_color(DefaultColor::Red)); - std::process::exit(1); - } - println!("{}", "Installation Complete".style().text_color(DefaultColor::Green)); - return Ok(()); - } else { - println!( - "Nitro Repo Not Installed. Please ReRun nitro launcher with the --install flag" - ); - std::process::exit(1); - } - } - info!("Loading Main Config"); - let string = read_to_string(&main_config)?; - let init_settings: GeneralSettings = toml::from_str(&string)?; - // Sets the Log Location - std::env::set_var("LOG_LOCATION", &init_settings.application.log); - - load_logger(&init_settings.application.mode); - for (key, value) in init_settings.env.iter() { - trace!("Adding Environment Var {key} set to {value}"); - std::env::set_var(key, value); - } - info!("Initializing Database"); - let pool = match init_settings.database.db_type.as_str() { - "mysql" => { - let result = MysqlSettings::try_from(init_settings.database.settings.clone()); - if let Err(error) = result { - error!("Unable to load database Settings {error}"); - std::process::exit(1); - } - database::init(&result.unwrap().to_string()) - } - _ => { - error!("Invalid Database Type"); - std::process::exit(1); - } - }; - if let Err(error) = pool { - error!("Unable to load database {error}"); - std::process::exit(1); - } - let pool = pool.unwrap(); - info!("Loading Other Configs"); - let settings = load_configs(); - if let Err(error) = settings { - error!("Unable to load Settings {error}"); - std::process::exit(1); - } - let settings = settings.unwrap(); - info!("Loading Storages"); - let storages = load_storages(); - if let Err(error) = storages { - error!("Unable to load Settings {error}"); - std::process::exit(1); - } - let storages = storages.unwrap(); - info!("Initializing Web Server"); - let nitro_repo = NitroRepo { - storages: RwLock::new(storages), - settings: RwLock::new(settings), - core: init_settings, - }; - let application = nitro_repo.core.application.clone(); - - let max_upload = application.max_upload; - - let address = application.address.clone(); - let data = web::Data::new(nitro_repo); - - let server = HttpServer::new(move || { - App::new() - .wrap( - Cors::default() - .allow_any_header() - .allow_any_method() - .allow_any_origin(), - ) - .wrap(middleware::Logger::default()) - .app_data(web::Data::new(pool.clone())) - .app_data(data.clone()) - .app_data(web::Data::new(PayloadConfig::new( - (max_upload * 1024 * 1024) as usize, - ))) - .configure(error::handlers::init) - .configure(settings::init) - .configure(repository::init) - .configure(storage::admin::init) - .configure(repository::admin::init) - .configure(system::controllers::init) - .configure(misc::init) - .configure(frontend::init) - }) - .workers(2); - - // I am pretty sure this is correctly working - // If I am correct this will only be available if the feature ssl is added - #[cfg(feature = "ssl")] - { - if let Some(private) = application.ssl_private_key { - let cert = application - .ssl_cert_key - .expect("If Private Key is set. CERT Should be set"); - use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; - - let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); - builder - .set_private_key_file(private, SslFiletype::PEM) - .unwrap(); - builder.set_certificate_chain_file(cert).unwrap(); - return server.bind_openssl(address, builder)?.run().await; - } - } - - return server.bind(address)?.run().await; -} diff --git a/backend/src/misc/frontend_helpers.rs b/backend/src/misc/frontend_helpers.rs deleted file mode 100644 index cd827d18..00000000 --- a/backend/src/misc/frontend_helpers.rs +++ /dev/null @@ -1,20 +0,0 @@ -use actix_web::{get, HttpRequest}; -use serde::{Deserialize, Serialize}; - -use crate::{APIResponse, NitroRepoData, SiteResponse}; -#[derive(Serialize, Deserialize)] -pub struct SiteInfo { - pub name: String, - pub description: String, -} - -#[get("/api/info/site")] -pub async fn site_info(site: NitroRepoData, request: HttpRequest) -> SiteResponse { - let mutex = site.settings.read().await; - - let info = SiteInfo { - name: mutex.site.name.clone(), - description: mutex.site.name.clone(), - }; - APIResponse::respond_new(Some(info), &request) -} diff --git a/backend/src/misc/mod.rs b/backend/src/misc/mod.rs deleted file mode 100644 index 60c120f3..00000000 --- a/backend/src/misc/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -use actix_web::web; - -mod frontend_helpers; - -pub fn init(cfg: &mut web::ServiceConfig) { - cfg.service(frontend_helpers::site_info); -} diff --git a/backend/src/repository/admin/controller.rs b/backend/src/repository/admin/controller.rs deleted file mode 100644 index dc03a5d5..00000000 --- a/backend/src/repository/admin/controller.rs +++ /dev/null @@ -1,448 +0,0 @@ -use actix_web::web::{Bytes, Path}; -use actix_web::{delete, get, patch, post, put, web, HttpRequest}; -use log::error; -use serde::{Deserialize, Serialize}; - -use crate::api_response::{APIResponse, SiteResponse}; -use crate::constants::SUPPORTED_REPO_TYPES; -use crate::database::DbPool; -use crate::error::response::{bad_request, not_found, unauthorized}; -use crate::NitroRepoData; -use crate::repository::models::RepositorySummary; -use crate::repository::settings::frontend::{BadgeSettings, Frontend}; -use crate::repository::settings::Policy; -use crate::repository::settings::security::Visibility; -use crate::repository::settings::webhook::{ReportGeneration, Webhook}; -use crate::system::permissions::options::CanIDo; - -use crate::system::utils::get_user_by_header; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ListRepositories { - pub repositories: Vec, -} - -/// let user = match user.can_i_edit_repos() { -// Ok(user) => { -// user -// } -// Err(_) => return unauthorized() -// }; -#[get("/api/admin/repositories/list")] -pub async fn list_repos( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, -) -> SiteResponse { - let connection = pool.get()?; - - let user = get_user_by_header(r.headers(), &connection)?; - if user.can_i_edit_repos().is_err() { - return unauthorized(); - } - //TODO Change the frontend to only show repos based on the current storage being looked at. - let mut vec = Vec::new(); - let result = site.storages.read().await; - for (_, storage) in result.iter() { - for (_, repo) in storage.get_repositories()? { - vec.push(repo); - } - } - let response = ListRepositories { repositories: vec }; - APIResponse::new(true, Some(response)).respond(&r) -} - -#[get("/api/admin/repositories/{storage}/list")] -pub async fn list_repos_by_storage( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - storage: Path, -) -> SiteResponse { - let connection = pool.get()?; - - let user = get_user_by_header(r.headers(), &connection)?; - if user.can_i_edit_repos().is_err() { - return unauthorized(); - } - let result = site.storages.read().await; - let storage = storage.into_inner(); - let storage = result.get(&storage); - if storage.is_none() { - return not_found(); - } - let storage = storage.unwrap(); - let mut vec = Vec::new(); - for (_, repo) in storage.get_repositories()? { - vec.push(repo); - } - let response = ListRepositories { repositories: vec }; - APIResponse::new(true, Some(response)).respond(&r) -} - -#[get("/api/admin/repositories/get/{storage}/{repo}")] -pub async fn get_repo( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - path: web::Path<(String, String)>, -) -> SiteResponse { - let (storage, repo) = path.into_inner(); - let connection = pool.get()?; - - if get_user_by_header(r.headers(), &connection)?.can_i_edit_repos().is_err() { - return unauthorized(); - } - let result = site.storages.read().await; - let storage = result.get(&storage); - if storage.is_none() { - return not_found(); - } - let storage = storage.unwrap(); - let repository = storage.get_repository(&repo)?; - APIResponse::from(repository).respond(&r) -} - -#[post("/api/admin/repository/add")] -pub async fn add_repo( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - nc: web::Json, -) -> SiteResponse { - let connection = pool.get()?; - - if get_user_by_header(r.headers(), &connection)?.can_i_edit_repos().is_err() { - return unauthorized(); - } - let result = site.storages.read().await; - let storage = result.get(&nc.storage); - if storage.is_none() { - return not_found(); - } - if !SUPPORTED_REPO_TYPES.contains(&nc.repo_type.as_str()) { - return bad_request(format!("Unsupported Repository Type {}", &nc.repo_type)); - } - let storage = storage.unwrap(); - let repository = storage.create_repository(nc.0)?; - - APIResponse::from(Some(repository)).respond(&r) -} - -#[patch("/api/admin/repository/{storage}/{repository}/active/{active}")] -pub async fn update_active_status( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - path: web::Path<(String, String, bool)>, -) -> SiteResponse { - let connection = pool.get()?; - if get_user_by_header(r.headers(), &connection)?.can_i_edit_repos().is_err() { - return unauthorized(); - } - - let (storage, repo, active) = path.into_inner(); - let result = site.storages.read().await; - let storage = result.get(&storage); - if storage.is_none() { - return not_found(); - } - let storage = storage.unwrap(); - let repository = storage.get_repository(&repo)?; - if repository.is_none() { - return not_found(); - } - let mut repository = repository.unwrap(); - repository.settings.active = active; - storage.update_repository(&repository)?; - APIResponse::new(true, Some(repository)).respond(&r) -} - -#[patch("/api/admin/repository/{storage}/{repository}/policy/{policy}")] -pub async fn update_policy( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - path: web::Path<(String, String, Policy)>, -) -> SiteResponse { - let connection = pool.get()?; - if get_user_by_header(r.headers(), &connection)?.can_i_edit_repos().is_err() { - return unauthorized(); - } - - let (storage, repository, policy) = path.into_inner(); - let result = site.storages.read().await; - let storage = result.get(&storage); - if storage.is_none() { - return not_found(); - } - let storage = storage.unwrap(); - let repository = storage.get_repository(&repository)?; - if repository.is_none() { - return not_found(); - } - let mut repository = repository.unwrap(); - repository.settings.policy = policy; - storage.update_repository(&repository)?; - APIResponse::new(true, Some(repository)).respond(&r) -} - -#[patch("/api/admin/repository/{storage}/{repository}/description")] -pub async fn update_description( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - b: Bytes, - path: web::Path<(String, String)>, -) -> SiteResponse { - let connection = pool.get()?; - if get_user_by_header(r.headers(), &connection)?.can_i_edit_repos().is_err() { - return unauthorized(); - } - - let (storage, repository) = path.into_inner(); - let vec = b.to_vec(); - let string = String::from_utf8(vec); - if let Err(error) = string { - error!("Unable to Parse String from Request: {}", error); - return bad_request("Bad Description"); - } - - let result = site.storages.read().await; - let storage = result.get(&storage); - if storage.is_none() { - return not_found(); - } - let storage = storage.unwrap(); - let repository = storage.get_repository(&repository)?; - if repository.is_none() { - return not_found(); - } - let mut repository = repository.unwrap(); - repository.settings.description = string.unwrap(); - storage.update_repository(&repository)?; - APIResponse::new(true, Some(repository)).respond(&r) -} - -#[patch("/api/admin/repository/{storage}/{repository}/modify/settings/frontend")] -pub async fn modify_frontend_settings( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - path: web::Path<(String, String)>, - nc: web::Json, -) -> SiteResponse { - let connection = pool.get()?; - if get_user_by_header(r.headers(), &connection)?.can_i_edit_repos().is_err() { - return unauthorized(); - } - let (storage, repository) = path.into_inner(); - - let result = site.storages.read().await; - let storage = result.get(&storage); - if storage.is_none() { - return not_found(); - } - let storage = storage.unwrap(); - let repository = storage.get_repository(&repository)?; - if repository.is_none() { - return not_found(); - } - let mut repository = repository.unwrap(); - repository.settings.frontend = nc.0; - storage.update_repository(&repository)?; - APIResponse::new(true, Some(repository)).respond(&r) -} - -#[patch("/api/admin/repository/{storage}/{repository}/modify/settings/badge")] -pub async fn modify_badge_settings( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - path: web::Path<(String, String)>, - nc: web::Json, -) -> SiteResponse { - let connection = pool.get()?; - if get_user_by_header(r.headers(), &connection)?.can_i_edit_repos().is_err() { - return unauthorized(); - } - let (storage, repository) = path.into_inner(); - let result = site.storages.read().await; - let storage = result.get(&storage); - if storage.is_none() { - return not_found(); - } - let storage = storage.unwrap(); - let repository = storage.get_repository(&repository)?; - if repository.is_none() { - return not_found(); - } - let mut repository = repository.unwrap(); - repository.settings.badge = nc.0; - storage.update_repository(&repository)?; - APIResponse::new(true, Some(repository)).respond(&r) -} - -#[patch("/api/admin/repository/{storage}/{repository}/modify/security/visibility/{visibility}")] -pub async fn modify_security( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - path: web::Path<(String, String, Visibility)>, -) -> SiteResponse { - let connection = pool.get()?; - - if get_user_by_header(r.headers(), &connection)?.can_i_edit_repos().is_err() { - return unauthorized(); - } - let (storage, repository, visibility) = path.into_inner(); - - let result = site.storages.read().await; - let storage = result.get(&storage); - if storage.is_none() { - return not_found(); - } - let storage = storage.unwrap(); - let repository = storage.get_repository(&repository)?; - if repository.is_none() { - return not_found(); - } - let mut repository = repository.unwrap(); - repository.security.visibility = visibility; - storage.update_repository(&repository)?; - APIResponse::new(true, Some(repository)).respond(&r) -} - - -#[patch("/api/admin/repository/{storage}/{repository}/modify/deploy/report")] -pub async fn modify_deploy( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - path: web::Path<(String, String)>, - nc: web::Json, -) -> SiteResponse { - let connection = pool.get()?; - - if get_user_by_header(r.headers(), &connection)?.can_i_edit_repos().is_err() { - return unauthorized(); - } - let (storage, repository) = path.into_inner(); - let result = site.storages.read().await; - let storage = result.get(&storage); - if storage.is_none() { - return not_found(); - } - let storage = storage.unwrap(); - let repository = storage.get_repository(&repository)?; - if repository.is_none() { - return not_found(); - } - let mut repository = repository.unwrap(); - repository.deploy_settings.report_generation = nc.0; - storage.update_repository(&repository)?; - - APIResponse::respond_new(Some(repository), &r) -} - -#[put("/api/admin/repository/{storage}/{repository}/modify/deploy/webhook/add")] -pub async fn add_webhook( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - path: web::Path<(String, String)>, - nc: web::Json, -) -> SiteResponse { - let connection = pool.get()?; - - if get_user_by_header(r.headers(), &connection)?.can_i_edit_repos().is_err() { - return unauthorized(); - } - let (storage, repository) = path.into_inner(); - - - let user = get_user_by_header(r.headers(), &connection)?; - if user.is_none() || !user.unwrap().permissions.admin { - return unauthorized(); - } - let result = site.storages.read().await; - let storage = result.get(&storage); - if storage.is_none() { - return not_found(); - } - let storage = storage.unwrap(); - let repository = storage.get_repository(&repository)?; - if repository.is_none() { - return not_found(); - } - let mut repository = repository.unwrap(); - repository.deploy_settings.add_webhook(nc.0); - storage.update_repository(&repository)?; - APIResponse::respond_new(Some(repository), &r) -} - -#[delete("/api/admin/repository/{storage}/{repository}/modify/deploy/webhook/{webhook}")] -pub async fn remove_webhook( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - path: web::Path<(String, String, String)>, -) -> SiteResponse { - let connection = pool.get()?; - - if get_user_by_header(r.headers(), &connection)?.can_i_edit_repos().is_err() { - return unauthorized(); - } - let (storage, repository, webhook) = path.into_inner(); - - let result = site.storages.read().await; - let storage = result.get(&storage); - if storage.is_none() { - return not_found(); - } - let storage = storage.unwrap(); - let repository = storage.get_repository(&repository)?; - if repository.is_none() { - return not_found(); - } - let mut repository = repository.unwrap(); - repository.deploy_settings.remove_hook(webhook); - storage.update_repository(&repository)?; - APIResponse::respond_new(Some(repository), &r) -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct DeleteRequest { - pub delete_files: Option, -} - -#[delete("/api/admin/repository/{storage}/{repository}")] -pub async fn delete_repository( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - path: web::Path<(String, String)>, - query: web::Query, -) -> SiteResponse { - let connection = pool.get()?; - - if get_user_by_header(r.headers(), &connection)?.can_i_edit_repos().is_err() { - return unauthorized(); - } - let (storage, repository) = path.into_inner(); - - - let result = site.storages.read().await; - let storage = result.get(&storage); - if storage.is_none() { - return not_found(); - } - let storage = storage.unwrap(); - let repository = storage.get_repository(&repository)?; - if repository.is_none() { - return not_found(); - } - let repository = repository.unwrap(); - storage.delete_repository(&repository, query.delete_files.unwrap_or(false))?; - APIResponse::from(true).respond(&r) -} diff --git a/backend/src/repository/admin/mod.rs b/backend/src/repository/admin/mod.rs deleted file mode 100644 index 632035ce..00000000 --- a/backend/src/repository/admin/mod.rs +++ /dev/null @@ -1,21 +0,0 @@ -use actix_web::web; - -pub mod controller; - -pub fn init(cfg: &mut web::ServiceConfig) { - cfg - .service(controller::add_repo) - .service(controller::get_repo) - .service(controller::list_repos_by_storage) - .service(controller::list_repos) - .service(controller::modify_security) - .service(controller::modify_frontend_settings) - .service(controller::modify_deploy) - .service(controller::add_webhook) - .service(controller::remove_webhook) - .service(controller::update_active_status) - .service(controller::update_policy) - .service(controller::modify_badge_settings) - .service(controller::update_description) - .service(controller::delete_repository); -} diff --git a/backend/src/repository/api.rs b/backend/src/repository/api.rs deleted file mode 100644 index 865f6d7a..00000000 --- a/backend/src/repository/api.rs +++ /dev/null @@ -1,78 +0,0 @@ -use actix_web::{get, web, HttpRequest}; -use serde::{Deserialize, Serialize}; - -use crate::api_response::SiteResponse; -use crate::database::DbPool; -use crate::NitroRepoData; - -use crate::repository::controller::{handle_result, to_request}; -use crate::repository::maven::MavenHandler; -use crate::repository::models::Repository; -use crate::repository::npm::NPMHandler; -use crate::repository::types::RepositoryHandler; -use crate::repository::types::RepositoryType::{Maven, NPM}; - -// - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ListRepositories { - pub repositories: Vec, -} - -#[get("/api/versions/{storage}/{repository}/{file:.*}")] -pub async fn get_versions( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - path: web::Path<(String, String, String)>, -) -> SiteResponse { - let (storage, repository, file) = path.into_inner(); - let connection = pool.get()?; - - let request = to_request(storage, repository, file, site).await?; - - let x = match request.repository.repo_type { - Maven(_) => { MavenHandler::handle_versions(&request, &r, &connection) } - NPM(_) => { NPMHandler::handle_versions(&request, &r, &connection) } - }?; - handle_result(x, request.value, r) -} - -#[get("/api/project/{storage}/{repository}/{file:.*}")] -pub async fn get_project( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - path: web::Path<(String, String, String)>, -) -> SiteResponse { - let (storage, repository, file) = path.into_inner(); - let connection = pool.get()?; - - let request = to_request(storage, repository, file, site).await?; - - let x = match request.repository.repo_type { - Maven(_) => { MavenHandler::handle_project(&request, &r, &connection) } - NPM(_) => { NPMHandler::handle_project(&request, &r, &connection) } - }?; - handle_result(x, request.value, r) -} - -#[get("/api/version/{storage}/{repository}/{project}/{version}")] -pub async fn get_version( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - path: web::Path<(String, String, String, String)>, -) -> SiteResponse { - let (storage, repository, project, version) = path.into_inner(); - let connection = pool.get()?; - - let request = to_request(storage, repository, project, site).await?; - - - let x = match request.repository.repo_type { - Maven(_) => { MavenHandler::handle_version(&request, version, &r, &connection) } - NPM(_) => { NPMHandler::handle_version(&request, version, &r, &connection) } - }?; - handle_result(x, request.value, r) -} diff --git a/backend/src/repository/badge.rs b/backend/src/repository/badge.rs deleted file mode 100644 index 8833b997..00000000 --- a/backend/src/repository/badge.rs +++ /dev/null @@ -1,60 +0,0 @@ -use crate::api_response::SiteResponse; -use crate::database::DbPool; -use crate::NitroRepoData; -use actix_web::{get, web, HttpRequest, HttpResponse}; -use badge_maker::BadgeBuilder; - -use crate::repository::controller::to_request; -use crate::repository::maven::MavenHandler; -use crate::repository::npm::NPMHandler; -use crate::repository::types::RepositoryHandler; -use crate::repository::types::RepositoryType::{Maven, NPM}; - -#[get("/badge/{storage}/{repository}/{file:.*}/badge")] -pub async fn badge( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - path: web::Path<(String, String, String)>, -) -> SiteResponse { - let (storage, repository, file) = path.into_inner(); - let connection = pool.get()?; - - let request = to_request(storage, repository, file, site).await?; - - let (label, message) = if request.value.eq("nitro_repo_example") { - (request.repository.name.clone(), "example".to_string()) - } else if request.value.eq("nitro_repo_status") { - ( - request.repository.name.clone(), - request.repository.settings.active.to_string(), - ) - } else if request.value.eq("nitro_repo_info") { - ( - format!("{} Repository", &request.repository.repo_type.to_string()), - request.repository.name.clone(), - ) - } else { - let version = match request.repository.repo_type { - Maven(_) => { MavenHandler::latest_version(&request, &r, &connection) } - NPM(_) => { NPMHandler::latest_version(&request, &r, &connection) } - }?; - - ( - request.repository.name.clone(), - version.unwrap_or_else(|| "404".to_string()), - ) - }; - let b_s = request.repository.settings.badge; - - let svg: String = BadgeBuilder::new() - .label(&label) - .message(message.as_str()) - .style(b_s.style.to_badge_maker_style()) - .color_parse(b_s.color.as_str()) - .label_color_parse(b_s.label_color.as_str()) - .build() - .unwrap() - .svg(); - return Ok(HttpResponse::Ok().content_type("image/svg+xml").body(svg)); -} diff --git a/backend/src/repository/controller.rs b/backend/src/repository/controller.rs deleted file mode 100644 index 31189c95..00000000 --- a/backend/src/repository/controller.rs +++ /dev/null @@ -1,359 +0,0 @@ -use actix_web::http::StatusCode; -use actix_web::web::Bytes; -use actix_web::{get, web, HttpRequest, HttpResponse}; -use log::{debug, trace}; -use serde::{Deserialize, Serialize}; - -use crate::api_response::{APIResponse, SiteResponse}; -use crate::database::DbPool; -use crate::error::internal_error::InternalError; -use crate::error::response::{bad_request, i_am_a_teapot, not_found}; -use crate::repository::maven::MavenHandler; -use crate::repository::models::Repository; -use crate::repository::nitro::ResponseType::Storage; -use crate::repository::nitro::{NitroFile, NitroFileResponse, ResponseType}; -use crate::repository::npm::NPMHandler; -use crate::repository::types::{RepoResponse, RepositoryRequest, RepositoryHandler}; -use crate::storage::StorageFile; -use crate::utils::get_accept; -use crate::NitroRepoData; -use crate::repository::types::RepositoryType::{Maven, NPM}; - -// - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ListRepositories { - pub repositories: Vec, -} - -pub async fn to_request( - storage_name: String, - repo_name: String, - file: String, - site: NitroRepoData, -) -> Result { - let storages = site.storages.read().await; - let storage = storages.get(&storage_name); - if storage.is_none() { - trace!("Storage {} not found", &storage_name); - return Err(InternalError::NotFound); - } - let storage = storage.unwrap().clone(); - let repository = storage.get_repository(&repo_name)?; - if repository.is_none() { - trace!("Repository {} not found", repo_name); - return Err(InternalError::NotFound); - } - let repository = repository.unwrap(); - - let request = RepositoryRequest { - storage, - repository, - value: file, - }; - Ok(request) -} - -pub async fn generate_storage_list(site: NitroRepoData) -> NitroFileResponse { - let mut storages = NitroFileResponse { - files: vec![], - response_type: ResponseType::Other, - active_dir: "".to_string(), - }; - - for (name, storage) in site.storages.read().await.iter() { - storages.files.push(NitroFile { - response_type: Storage, - file: StorageFile { - name: name.clone(), - full_path: name.clone(), - directory: true, - file_size: 0, - created: storage.created as u128, - }, - }); - } - storages -} - -pub async fn browse(site: NitroRepoData, r: HttpRequest) -> SiteResponse { - APIResponse::respond_new(Some(generate_storage_list(site).await), &r) -} - -#[get("/storages/{storage}")] -pub async fn browse_storage( - site: NitroRepoData, - r: HttpRequest, - path: web::Path, -) -> SiteResponse { - let string = path.into_inner(); - println!("HEY"); - if string.is_empty() { - return APIResponse::respond_new(Some(generate_storage_list(site).await), &r); - } - let storages = site.storages.read().await; - - let storage = storages.get(&string); - if storage.is_none() { - trace!("Storage {} not found", &string); - return Err(InternalError::NotFound); - } - let storage = storage.unwrap(); - let map = storage.get_repositories()?; - let mut repos = NitroFileResponse { - files: vec![], - response_type: ResponseType::Storage, - active_dir: string.clone(), - }; - for (name, sum) in map { - repos.files.push(NitroFile { - response_type: ResponseType::Repository(sum), - file: StorageFile { - name: name.clone(), - full_path: format!("{}/{}", &storage.name, &name), - directory: true, - file_size: 0, - created: 0, - }, - }); - } - APIResponse::respond_new(Some(repos), &r) -} - -#[derive(Serialize, Deserialize, Clone)] -pub struct GetPath { - pub storage: String, - pub repository: String, - pub file: Option, -} - -pub async fn get_repository( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - path: web::Path, -) -> SiteResponse { - let connection = pool.get()?; - let path = path.into_inner(); - let file = path.file.unwrap_or_else(|| "".to_string()); - let result = to_request(path.storage, path.repository, file, site).await; - if let Err(error) = result { - return match error { - InternalError::NotFound => not_found(), - _ => Err(error), - }; - } - let request = result.unwrap(); - let x = match request.repository.repo_type { - Maven(_) => { MavenHandler::handle_get(&request, &r, &connection) } - NPM(_) => { NPMHandler::handle_get(&request, &r, &connection) } - }?; - - handle_result(x, request.value, r) -} - -/// TODO look into this method -pub fn handle_result(response: RepoResponse, _url: String, r: HttpRequest) -> SiteResponse { - let x = get_accept(r.headers())?.unwrap_or_else(|| "text/html".to_string()); - return match response { - RepoResponse::FileList(files) => { - if x.contains(&"application/json".to_string()) { - APIResponse::new(true, Some(files)).respond(&r) - } else { - trace!("Access to Simple Dir Listing {}", r.uri()); - Ok(HttpResponse::Ok() - .content_type("text/html") - .body("Coming Soon(Simple DIR Listing)")) - } - } - RepoResponse::FileResponse(file) => file, - RepoResponse::Ok => APIResponse::new(true, Some(false)).respond(&r), - RepoResponse::NotFound => { - if x.contains(&"application/json".to_string()) { - return not_found(); - } else { - Ok(HttpResponse::NotFound() - .content_type("text/html") - .body("NOT FOUND")) - } - } - - RepoResponse::NotAuthorized => { - let r = APIResponse:: { - success: false, - data: None, - status_code: Some(401), - }; - let result = HttpResponse::Ok() - .status(StatusCode::UNAUTHORIZED) - .content_type("application/json") - .append_header(("WWW-Authenticate", "Basic realm=nitro_repo")) - .body(serde_json::to_string(&r).unwrap()); - return Ok(result); - } - RepoResponse::BadRequest(e) => { - return bad_request(e); - } - RepoResponse::IAmATeapot(e) => { - return i_am_a_teapot(e); - } - RepoResponse::ProjectResponse(project) => APIResponse::new(true, Some(project)).respond(&r), - RepoResponse::VersionListingResponse(versions) => { - APIResponse::new(true, Some(versions)).respond(&r) - } - RepoResponse::CreatedWithJSON(json) => { - let result = HttpResponse::Ok() - .status(StatusCode::CREATED) - .content_type("application/json") - .body(json); - return Ok(result); - } - RepoResponse::OkWithJSON(json) => { - let result = HttpResponse::Ok() - .status(StatusCode::OK) - .content_type("application/json") - .body(json); - return Ok(result); - } - RepoResponse::NitroVersionListingResponse(value) => { - APIResponse::new(true, Some(value)).respond(&r) - } - RepoResponse::NitroVersionResponse(value) => { - APIResponse::new(true, Some(value)).respond(&r) - } - RepoResponse::NitroProjectResponse(value) => { - APIResponse::new(true, Some(value)).respond(&r) - } - - RepoResponse::NitroFileList(value) => APIResponse::new(true, Some(value)).respond(&r), - }; -} - -pub async fn post_repository( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - path: web::Path<(String, String, String)>, - bytes: Bytes, -) -> SiteResponse { - let connection = pool.get()?; - let (storage, repository, file) = path.into_inner(); - let result = to_request(storage, repository, file, site).await; - if let Err(error) = result { - return match error { - InternalError::NotFound => not_found(), - _ => Err(error), - }; - } - let request = result.unwrap(); - debug!( - "POST {} in {}/{}: Route: {}", - &request.repository.repo_type.to_string(), - &request.storage.name, - &request.repository.name, - &request.value - ); - let x = match request.repository.repo_type { - Maven(_) => { MavenHandler::handle_post(&request, &r, &connection, bytes) } - NPM(_) => { NPMHandler::handle_post(&request, &r, &connection, bytes) } - }?; - - handle_result(x, request.value, r) -} - -pub async fn patch_repository( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - path: web::Path<(String, String, String)>, - bytes: Bytes, -) -> SiteResponse { - let connection = pool.get()?; - - let (storage, repository, file) = path.into_inner(); - let result = to_request(storage, repository, file, site).await; - if let Err(error) = result { - return match error { - InternalError::NotFound => not_found(), - _ => Err(error), - }; - } - let request = result.unwrap(); - debug!( - "PATCH {} in {}/{}: Route: {}", - &request.repository.repo_type.to_string(), - &request.storage.name, - &request.repository.name, - &request.value - ); - let x = match request.repository.repo_type { - Maven(_) => { MavenHandler::handle_patch(&request, &r, &connection, bytes) } - NPM(_) => { NPMHandler::handle_patch(&request, &r, &connection, bytes) } - }?; - - handle_result(x, request.value, r) -} - -pub async fn put_repository( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - path: web::Path<(String, String, String)>, - bytes: Bytes, -) -> SiteResponse { - let connection = pool.get()?; - let (storage, repository, file) = path.into_inner(); - let result = to_request(storage, repository, file, site).await; - if let Err(error) = result { - return match error { - InternalError::NotFound => not_found(), - _ => Err(error), - }; - } - let request = result.unwrap(); - debug!( - "PUT {} in {}/{}: Route: {}", - &request.repository.repo_type.to_string(), - &request.storage.name, - &request.repository.name, - &request.value - ); - let x = match request.repository.repo_type { - Maven(_) => { MavenHandler::handle_put(&request, &r, &connection, bytes) } - NPM(_) => { NPMHandler::handle_put(&request, &r, &connection, bytes) } - }?; - - handle_result(x, request.value, r) -} - -pub async fn head_repository( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - path: web::Path<(String, String, String)>, -) -> SiteResponse { - let connection = pool.get()?; - - let (storage, repository, file) = path.into_inner(); - let result = to_request(storage, repository, file, site).await; - if let Err(error) = result { - return match error { - InternalError::NotFound => not_found(), - _ => Err(error), - }; - } - let request = result.unwrap(); - debug!( - "HEAD {} in {}/{}: Route: {}", - &request.repository.repo_type.to_string(), - &request.storage.name, - &request.repository.name, - &request.value - ); - let x = match request.repository.repo_type { - Maven(_) => { MavenHandler::handle_head(&request, &r, &connection) } - NPM(_) => { NPMHandler::handle_head(&request, &r, &connection) } - }?; - - handle_result(x, request.value, r) -} diff --git a/backend/src/repository/data/mod.rs b/backend/src/repository/data/mod.rs new file mode 100644 index 00000000..9962e125 --- /dev/null +++ b/backend/src/repository/data/mod.rs @@ -0,0 +1,78 @@ +use std::fmt::Debug; + +use serde::{Deserialize, Serialize}; + +use crate::repository::settings::frontend::Frontend; +use crate::repository::settings::security::Visibility; + +use crate::repository::settings::{Policy, FRONTEND_CONFIG}; +use crate::storage::models::Storage; + +use crate::error::internal_error::InternalError; +use serde::de::DeserializeOwned; + +/// Types of Repositories that can exist. +#[derive(Serialize, Deserialize, Clone, Debug, strum_macros::Display, strum_macros::EnumString)] +pub enum RepositoryType { + Maven, + NPM, +} + +/// The Basic Repository Config +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct RepositoryConfig { + /// Repository Name + pub name: String, + /// The Type of Repository + pub repository_type: RepositoryType, + /// Storage. + pub storage: String, + /// Visibility. + #[serde(default)] + pub visibility: Visibility, + /// Rather or not the Repository is active. Meaning it can be pulled or pushed + #[serde(default = "default")] + pub active: bool, + ///The versioning policy for the Repository + #[serde(default)] + pub policy: Policy, + /// When it was created + pub created: i64, +} +impl RepositoryConfig { + /// Pull the Frontend Config + pub async fn get_frontend_config( + &self, + storage: &Box, + ) -> Result, InternalError> { + let option = storage.get_file(self, FRONTEND_CONFIG).await?; + if option.is_none() { + return Ok(None); + } + serde_json::from_slice(option.unwrap().as_slice()) + .map(Some) + .map_err(InternalError::from) + } + /// Update the frontend config + async fn save_frontend_config( + &self, + storage: &Box, + frontend: Option, + ) -> Result<(), InternalError> { + if frontend.is_none() { + // Treats a disable + storage.delete_file(self, FRONTEND_CONFIG).await?; + } + let value = serde_json::to_string(&frontend.unwrap())?; + storage + .save_file(self, value.as_bytes(), FRONTEND_CONFIG) + .await?; + Ok(()) + } +} + +fn default() -> bool { + true +} + +pub trait RepositorySetting: Send + Sync + Clone + Debug + Serialize + DeserializeOwned {} diff --git a/backend/src/repository/deploy/mod.rs b/backend/src/repository/deploy/mod.rs deleted file mode 100644 index 0915a22a..00000000 --- a/backend/src/repository/deploy/mod.rs +++ /dev/null @@ -1,40 +0,0 @@ -use std::fmt::{Display, Formatter}; - -use serde::de::value::MapDeserializer; -use serde::{Deserialize, Serialize}; - -use crate::error::internal_error::InternalError; -use crate::repository::models::Repository; -use crate::storage::models::StringStorage; -use crate::system::models::User; - -use crate::webhook::{DiscordConfig, DiscordHandler, WebhookHandler}; - -#[derive(Clone, Deserialize, Serialize)] -pub struct DeployInfo { - pub user: User, - pub version: String, - pub name: String, - pub version_folder: String, -} - -impl Display for DeployInfo { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", serde_json::to_string(self).unwrap()) - } -} - -pub async fn handle_post_deploy( - _storage: &StringStorage, - repository: &Repository, - deploy: &DeployInfo, -) -> Result<(), InternalError> { - for x in &repository.deploy_settings.webhooks { - if x.handler.as_str() == "discord" { - let result = - DiscordConfig::deserialize(MapDeserializer::new(x.settings.clone().into_iter()))?; - DiscordHandler::handle(&result, deploy).await?; - } - } - Ok(()) -} diff --git a/backend/src/repository/handler.rs b/backend/src/repository/handler.rs new file mode 100644 index 00000000..5930e5ca --- /dev/null +++ b/backend/src/repository/handler.rs @@ -0,0 +1,87 @@ +use crate::authentication::Authentication; +use actix_web::http::header::HeaderMap; +use actix_web::http::StatusCode; +use actix_web::web::Bytes; + +use crate::error::api_error::APIError; +use async_trait::async_trait; +use sea_orm::DatabaseConnection; + +use crate::repository::response::RepoResponse; + +#[async_trait] +pub trait RepositoryHandler<'a>: Send + Sync { + /// Handles a get request to a Repo + async fn handle_get( + &self, + _path: &str, + _http: &HeaderMap, + _conn: &DatabaseConnection, + _authentication: Authentication, + ) -> Result { + Err(APIError::from(( + "Get is not implemented for this type", + StatusCode::IM_A_TEAPOT, + )) + .into()) + } + /// Handles a Post Request to a Repo + async fn handle_post( + &self, + _path: &str, + _http: &HeaderMap, + _conn: &DatabaseConnection, + _authentication: Authentication, + _bytes: Bytes, + ) -> Result { + Err(APIError::from(( + "POST is not implemented for this type", + StatusCode::IM_A_TEAPOT, + )) + .into()) + } + /// Handles a PUT Request to a Repo + async fn handle_put( + &self, + _path: &str, + _http: &HeaderMap, + _conn: &DatabaseConnection, + _authentication: Authentication, + _bytes: Bytes, + ) -> Result { + Err(APIError::from(( + "PUT is not implemented for this type", + StatusCode::IM_A_TEAPOT, + )) + .into()) + } + /// Handles a PATCH Request to a Repo + async fn handle_patch( + &self, + _path: &str, + _http: &HeaderMap, + _conn: &DatabaseConnection, + _authentication: Authentication, + _bytes: Bytes, + ) -> Result { + Err(APIError::from(( + "Patch is not implemented for this type", + StatusCode::IM_A_TEAPOT, + )) + .into()) + } + /// Handles a HAPIResponseAD Request to a Repo + async fn handle_head( + &self, + _path: &str, + _http: &HeaderMap, + _conn: &DatabaseConnection, + _authentication: Authentication, + ) -> Result { + Err(APIError::from(( + "Head is not implemented for this type", + StatusCode::IM_A_TEAPOT, + )) + .into()) + } +} diff --git a/backend/src/repository/maven/error.rs b/backend/src/repository/maven/error.rs new file mode 100644 index 00000000..907ee385 --- /dev/null +++ b/backend/src/repository/maven/error.rs @@ -0,0 +1,25 @@ +use std::error::Error; +use std::fmt::{Display, Formatter}; + +#[derive(Debug)] +pub struct MavenError(String); + +impl Display for MavenError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl Error for MavenError {} + +impl From<&str> for MavenError { + fn from(err: &str) -> MavenError { + MavenError(err.to_string()) + } +} + +impl From for MavenError { + fn from(err: String) -> MavenError { + MavenError(err) + } +} diff --git a/backend/src/repository/maven/mod.rs b/backend/src/repository/maven/mod.rs index 4ecce2b9..2ecdee75 100644 --- a/backend/src/repository/maven/mod.rs +++ b/backend/src/repository/maven/mod.rs @@ -1,282 +1,157 @@ -use crate::constants::PROJECT_FILE; +use actix_web::http::header::HeaderMap; +use actix_web::http::StatusCode; use actix_web::web::Bytes; -use actix_web::HttpRequest; -use diesel::MysqlConnection; -use log::Level::Trace; -use log::{debug, error, log_enabled, trace}; -use crate::error::internal_error::InternalError; -use crate::repository::deploy::{handle_post_deploy, DeployInfo}; +use log::error; +use sea_orm::DatabaseConnection; + use crate::repository::maven::models::Pom; -use crate::repository::maven::utils::parse_project_to_directory; -use crate::repository::models::{RepositorySummary}; +use crate::repository::settings::security::Visibility; use crate::repository::settings::Policy; -use crate::repository::types::RepoResponse::{ - BadRequest, IAmATeapot, NotAuthorized, NotFound, ProjectResponse, -}; -use crate::repository::types::{RepositoryHandler, RepositoryRequest}; -use crate::repository::types::{Project, RepoResponse, RepoResult}; -use crate::repository::utils::{ - get_project_data, get_version_data, get_versions, process_storage_files, -}; -use crate::system::utils::{can_deploy_basic_auth, can_read_basic_auth}; +use crate::authentication::Authentication; +use crate::repository::data::RepositoryConfig; +use crate::repository::handler::RepositoryHandler; +use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; + +use crate::error::api_error::APIError; +use crate::error::internal_error::InternalError; +use crate::repository::response::RepoResponse; +use crate::storage::file::StorageFileResponse; +use crate::storage::models::Storage; +use crate::system::permissions::options::CanIDo; +use crate::system::user::UserModel; +use async_trait::async_trait; + +use crate::storage::DynamicStorage; +use tokio::sync::RwLockReadGuard; +pub mod error; pub mod models; mod utils; -pub struct MavenHandler; +pub struct MavenHandler<'a> { + config: RepositoryConfig, + storage: RwLockReadGuard<'a, DynamicStorage>, +} -impl RepositoryHandler for MavenHandler { - fn handle_get( - request: &RepositoryRequest, - http: &HttpRequest, - conn: &MysqlConnection, - ) -> RepoResult { - if !can_read_basic_auth(http.headers(), &request.repository, conn)?.0 { - return RepoResult::Ok(NotAuthorized); - } - let result = - request - .storage - .get_file_as_response(&request.repository, &request.value, http)?; - if result.is_left() { - Ok(RepoResponse::FileResponse(result.left().unwrap())) - } else { - let vec = result.right().unwrap(); - let file_response = - process_storage_files(&request.storage, &request.repository, vec, &request.value)?; - Ok(RepoResponse::NitroFileList(file_response)) +impl<'a> MavenHandler<'a> { + pub fn create( + repository: RepositoryConfig, + storage: RwLockReadGuard<'a, DynamicStorage>, + ) -> MavenHandler<'a> { + MavenHandler::<'a> { + config: repository, + storage, } } +} - fn handle_post( - _request: &RepositoryRequest, - _http: &HttpRequest, - _conn: &MysqlConnection, - _bytes: Bytes, - ) -> RepoResult { - Ok(IAmATeapot("Post is not handled in Maven".to_string())) - } +#[async_trait] +impl<'a> RepositoryHandler<'a> for MavenHandler<'a> { + async fn handle_get( + &self, + path: &str, + _: &HeaderMap, + conn: &DatabaseConnection, + authentication: Authentication, + ) -> Result { + if self.config.visibility == Visibility::Private { + let caller: UserModel = authentication.get_user(conn).await??; + if let Some(value) = caller.can_read_from(&self.config)? { + return Err(value.into()); + } + } - fn handle_put( - request: &RepositoryRequest, - http: &HttpRequest, - conn: &MysqlConnection, - bytes: Bytes, - ) -> RepoResult { - let x = can_deploy_basic_auth(http.headers(), &request.repository, conn)?; - if !x.0 { - return RepoResult::Ok(NotAuthorized); + match self + .storage + .get_file_as_response(&self.config, path) + .await + .map_err(InternalError::from)? + { + StorageFileResponse::List(list) => { + let files = self.process_storage_files(list, path).await?; + Ok(RepoResponse::try_from((files, StatusCode::OK))?) + } + value => Ok(RepoResponse::FileResponse(value)), } + } - //TODO find a better way to do this - match request.repository.settings.policy { + async fn handle_put( + &self, + path: &str, + _: &HeaderMap, + conn: &DatabaseConnection, + authentication: Authentication, + bytes: Bytes, + ) -> Result { + let caller: UserModel = authentication.get_user(conn).await??; + if let Some(_value) = caller.can_deploy_to(&self.config)? {} + match self.config.policy { Policy::Release => { - if request.value.contains("-SNAPSHOT") { - return Ok(BadRequest("SNAPSHOT in release only".to_string())); + if path.contains("-SNAPSHOT") { + return Err(APIError::from(( + "SNAPSHOT in release only", + StatusCode::BAD_REQUEST, + )) + .into()); } } Policy::Snapshot => { - if !request.value.contains("-SNAPSHOT") { - return Ok(BadRequest("Release in a snapshot only".to_string())); + if !path.contains("-SNAPSHOT") { + return Err(APIError::from(( + "Release in a snapshot only", + StatusCode::BAD_REQUEST, + )) + .into()); } } Policy::Mixed => {} } - request + let exists = self .storage - .save_file(&request.repository, bytes.as_ref(), &request.value)?; - if request.value.ends_with(".pom") { - let vec = bytes.as_ref().to_vec(); - let result = String::from_utf8(vec)?; - let pom: Result = serde_xml_rs::from_str(&result); - if let Err(error) = &pom { - error!( - "Unable to Parse Pom File {} Error {}", - &request.value, error - ); - } - if let Ok(pom) = pom { - let project_folder = - format!("{}/{}", pom.group_id.replace('.', "/"), pom.artifact_id); - trace!("Project Folder Location {}", project_folder); - let repository = request.repository.clone(); - let storage = request.storage.clone(); - actix_web::rt::spawn(async move { - if let Err(error) = crate::repository::maven::utils::update_project( - &storage, - &repository, - &project_folder, - pom.version.clone(), - pom.clone(), - ) { - error!("Unable to update {}, {}", PROJECT_FILE, error); - if log_enabled!(Trace) { - trace!( - "Version {} Name: {}", - &pom.version, - format!("{}:{}", &pom.group_id, &pom.artifact_id) - ); - } - } + .save_file(&self.config, bytes.as_ref(), path) + .await + .map_err(InternalError::from)?; - if let Err(error) = crate::repository::utils::update_project_in_repositories( - &storage, - &repository, - format!("{}:{}", &pom.group_id, &pom.artifact_id), - ) { - error!("Unable to update repository.json, {}", error); - if log_enabled!(Trace) { - trace!( - "Version {} Name: {}", - &pom.version, - format!("{}:{}", &pom.group_id, &pom.artifact_id) - ); - } - } - let string = format!("{}/{}", project_folder, &pom.version); - let info = DeployInfo { - user: x.1.unwrap(), - version: pom.version, - name: format!("{}:{}", &pom.group_id, &pom.artifact_id), - version_folder: string, - }; - - debug!("Starting Post Deploy Tasks"); - if log_enabled!(Trace) { - trace!("Data {}", &info); - } - let deploy = handle_post_deploy(&storage, &repository, &info).await; - if let Err(error) = deploy { - error!("Error Handling Post Deploy Tasks {}", error); - } else { - debug!("All Post Deploy Tasks Completed and Happy :)"); - } - }); + // Post Deploy Handler + if path.ends_with(".pom") { + let vec = bytes.as_ref().to_vec(); + let result = String::from_utf8(vec).map_err(APIError::bad_request)?; + let pom: Pom = serde_xml_rs::from_str(&result).map_err(APIError::bad_request)?; + + let project_folder = format!("{}/{}", pom.group_id.replace('.', "/"), pom.artifact_id); + let version_folder = format!("{}/{}", &project_folder, &pom.version); + if let Err(error) = self + .post_deploy(project_folder, version_folder, caller, pom.into()) + .await + { + error!("Unable to complete post processing Tasks {}", error); } } - Ok(RepoResponse::Ok) + // Everything was ok + Ok(RepoResponse::PUTResponse( + exists, + format!( + "/storages/{}/{}/{}", + &self.storage.storage_config().name, + &self.config.name, + path + ), + )) } +} - fn handle_patch( - _request: &RepositoryRequest, - _http: &HttpRequest, - _conn: &MysqlConnection, - _bytes: Bytes, - ) -> RepoResult { - Ok(IAmATeapot("Patch is not handled in Maven".to_string())) - } - - fn handle_head( - request: &RepositoryRequest, - http: &HttpRequest, - _conn: &MysqlConnection, - ) -> RepoResult { - let result = - request - .storage - .get_file_as_response(&request.repository, &request.value, http)?; - if result.is_left() { - Ok(RepoResponse::FileResponse(result.left().unwrap())) - } else { - Ok(RepoResponse::FileList(result.right().unwrap())) - } - } - - fn handle_versions( - request: &RepositoryRequest, - http: &HttpRequest, - conn: &MysqlConnection, - ) -> RepoResult { - if !can_read_basic_auth(http.headers(), &request.repository, conn)?.0 { - return RepoResult::Ok(NotAuthorized); - } - let project_dir = parse_project_to_directory(&request.value); - - let vec = get_versions(&request.storage, &request.repository, project_dir)?; - Ok(RepoResponse::NitroVersionListingResponse(vec)) - } - - fn handle_version( - request: &RepositoryRequest, - version: String, - http: &HttpRequest, - conn: &MysqlConnection, - ) -> RepoResult { - if !can_read_basic_auth(http.headers(), &request.repository, conn)?.0 { - return RepoResult::Ok(NotAuthorized); - } - let project_dir = parse_project_to_directory(&request.value); - - let project_data = - get_project_data(&request.storage, &request.repository, project_dir.clone())?; - if let Some(project_data) = project_data { - let version_data = crate::repository::utils::get_version_data( - &request.storage, - &request.repository, - format!("{}/{}", project_dir, &version), - )?; - - let project = Project { - repo_summary: RepositorySummary::new(&request.repository), - project: project_data, - version: version_data, - frontend_response: None, - }; - return Ok(ProjectResponse(project)); - } - RepoResult::Ok(NotFound) +impl NitroRepositoryHandler for MavenHandler<'_> { + fn parse_project_to_directory>(value: S) -> String { + value.into().replace('.', "/").replace(':', "/") } - fn handle_project( - request: &RepositoryRequest, - http: &HttpRequest, - conn: &MysqlConnection, - ) -> RepoResult { - if !can_read_basic_auth(http.headers(), &request.repository, conn)?.0 { - return RepoResult::Ok(NotAuthorized); - } - let string = parse_project_to_directory(&request.value); - - let project_data = get_project_data(&request.storage, &request.repository, string.clone())?; - if let Some(project_data) = project_data { - let version_data = get_version_data( - &request.storage, - &request.repository, - format!("{}/{}", string, &project_data.versions.latest_version), - )?; - - let project = Project { - repo_summary: RepositorySummary::new(&request.repository), - project: project_data, - version: version_data, - frontend_response: None, - }; - return Ok(ProjectResponse(project)); - } - RepoResult::Ok(NotFound) + fn storage(&self) -> &DynamicStorage { + &self.storage } - fn latest_version( - request: &RepositoryRequest, - http: &HttpRequest, - conn: &MysqlConnection, - ) -> Result, InternalError> { - if !can_read_basic_auth(http.headers(), &request.repository, conn)?.0 { - return Ok(None); - } - let string = parse_project_to_directory(&request.value); - let project_data = get_project_data(&request.storage, &request.repository, string)?; - Ok(if let Some(project_data) = project_data { - let latest_release = project_data.versions.latest_release; - if latest_release.is_empty() { - Some(project_data.versions.latest_version) - } else { - Some(latest_release) - } - } else { - None - }) + fn repository(&self) -> &RepositoryConfig { + &self.config } } diff --git a/backend/src/repository/maven/models.rs b/backend/src/repository/maven/models.rs index 87f90023..7bf12ccc 100644 --- a/backend/src/repository/maven/models.rs +++ b/backend/src/repository/maven/models.rs @@ -1,9 +1,22 @@ +use crate::repository::data::RepositorySetting; +use crate::repository::nitro::VersionData; +use crate::utils::get_current_time; use serde::{Deserialize, Serialize}; +use serde_json::Value; -#[derive(Debug, Serialize, Deserialize, Clone,Default)] -pub struct MavenSettings{ +#[derive(Debug, Serialize, Deserialize, Clone, Default)] +pub struct MavenSettings {} +impl TryFrom for MavenSettings { + type Error = serde_json::Error; + + fn try_from(value: Value) -> Result { + serde_json::from_value(value) + } } + +impl RepositorySetting for MavenSettings {} + #[derive(Debug, Serialize, Deserialize, Clone)] pub struct DeployMetadata { #[serde(rename = "groupId")] @@ -43,3 +56,16 @@ pub struct Pom { pub url: Option, pub scm: Option, } + +impl Into for Pom { + fn into(self) -> VersionData { + VersionData { + name: format!("{}:{}", &self.group_id, &self.artifact_id), + description: self.description.unwrap_or_default(), + source: None, + licence: None, + version: self.version, + created: get_current_time(), + } + } +} diff --git a/backend/src/repository/maven/utils.rs b/backend/src/repository/maven/utils.rs index 6f1fd126..1680f44b 100644 --- a/backend/src/repository/maven/utils.rs +++ b/backend/src/repository/maven/utils.rs @@ -1,22 +1,9 @@ use std::fs::read_dir; use std::path::Path; -use crate::constants::{PROJECT_FILE, VERSION_DATA}; use chrono::NaiveDateTime; -use log::trace; use crate::error::internal_error::InternalError; -use crate::repository::maven::models::Pom; -use crate::repository::models::Repository; -use crate::repository::nitro::{ProjectData, VersionData}; - -use crate::storage::models::StringStorage; -use crate::utils::get_current_time; - -/// Project format {groupID}:{artifactID} -pub fn parse_project_to_directory(value: &str) -> String { - value.replace('.', "/").replace(':', "/") -} #[allow(dead_code)] fn get_artifacts(path: &Path) -> Vec { @@ -55,48 +42,3 @@ mod tests { ); } } - -pub fn update_project( - storage: &StringStorage, - repository: &Repository, - project_folder: &str, - version: String, - pom: Pom, -) -> Result<(), InternalError> { - let project_file = format!("{}/{}", &project_folder, PROJECT_FILE); - let version_folder = format!("{}/{}/{}", &project_folder, &version, VERSION_DATA); - trace!("Project File Location {}", project_file); - let option = storage.get_file(repository, &project_file)?; - let mut project_data: ProjectData = if let Some(data) = option { - let string = String::from_utf8(data)?; - let value = serde_json::from_str(&string)?; - storage.delete_file(repository, &project_file)?; - value - } else { - ProjectData { - versions: Default::default(), - created: get_current_time(), - updated: get_current_time(), - } - }; - let version_data = VersionData { - name: format!("{}:{}", &pom.group_id, &pom.artifact_id), - description: pom.description.unwrap_or_default(), - source: None, - licence: None, - version: version.clone(), - created: get_current_time(), - }; - project_data.versions.update_version(version); - storage.save_file( - repository, - serde_json::to_string_pretty(&project_data)?.as_bytes(), - &project_file, - )?; - storage.save_file( - repository, - serde_json::to_string_pretty(&version_data)?.as_bytes(), - &version_folder, - )?; - Ok(()) -} diff --git a/backend/src/repository/mod.rs b/backend/src/repository/mod.rs index 1e51ffbe..719134fb 100644 --- a/backend/src/repository/mod.rs +++ b/backend/src/repository/mod.rs @@ -1,41 +1,12 @@ -use actix_web::web; - -pub mod admin; -mod api; -mod badge; -pub mod controller; -pub mod deploy; +pub mod data; pub mod frontend; +pub mod handler; pub mod maven; -pub mod models; pub mod nitro; pub mod npm; -pub mod public; -pub mod types; -pub mod utils; +pub mod response; pub mod settings; pub static REPOSITORY_CONF: &str = "repository.nitro_repo"; +pub static REPOSITORY_CONF_FOLDER: &str = ".config.nitro_repo"; pub static REPOSITORY_CONF_BAK: &str = "repository.nitro_repo.bak"; - -pub fn init(cfg: &mut web::ServiceConfig) { - cfg.service(controller::browse_storage) - .service(web::resource(["/storages/", "/storages"]).to(controller::browse)) - .service( - web::resource([ - "/storages/{storage}/{repository}", - "/storages/{storage}/{repository}/{file:.*}", - "/storages/{storage}/{repository}/", - ]) - .route(web::get().to(controller::get_repository)) - .route(web::put().to(controller::put_repository)) - .route(web::head().to(controller::head_repository)) - .route(web::patch().to(controller::patch_repository)) - .route(web::post().to(controller::post_repository)), - ) - .service(api::get_versions) - .service(api::get_version) - .service(api::get_project) - .service(badge::badge) - .service(public::get_repo); -} diff --git a/backend/src/repository/models.rs b/backend/src/repository/models.rs deleted file mode 100644 index b54b210a..00000000 --- a/backend/src/repository/models.rs +++ /dev/null @@ -1,44 +0,0 @@ -use std::fmt::Debug; - -use serde::{Deserialize, Serialize}; - -use crate::repository::settings::{RepositorySettings}; -use crate::repository::settings::security::SecurityRules; -use crate::repository::settings::webhook::DeploySettings; -use crate::repository::types::RepositoryType; - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct RepositorySummary { - pub name: String, - pub storage: String, - pub repo_type: String, -} - -impl RepositorySummary { - pub fn new(repo: &Repository) -> RepositorySummary { - RepositorySummary { - name: repo.name.clone(), - storage: repo.storage.clone(), - repo_type: repo.repo_type.to_string(), - } - } -} - - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Repository { - pub name: String, - pub repo_type: RepositoryType, - pub storage: String, - pub settings: RepositorySettings, - pub security: SecurityRules, - pub deploy_settings: DeploySettings, - pub created: i64, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct RepositoryListResponse { - pub name: String, - pub repo_type: String, - pub storage: String, -} diff --git a/backend/src/repository/nitro/mod.rs b/backend/src/repository/nitro/mod.rs index 2bff6566..15a3aed3 100644 --- a/backend/src/repository/nitro/mod.rs +++ b/backend/src/repository/nitro/mod.rs @@ -1,22 +1,24 @@ -use crate::repository::models::RepositorySummary; -use crate::repository::types::Project; -use crate::storage::StorageFile; -use serde::{Deserialize, Serialize}; +pub mod nitro_repository; +pub mod utils; +use crate::repository::data::RepositoryConfig; +use crate::repository::response::Project; +use crate::storage::file::StorageFile; use crate::utils::get_current_time; +use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize, Clone, Debug)] +#[derive(Serialize, Clone, Debug)] pub struct NitroFileResponse { pub files: Vec, - pub response_type: ResponseType, + pub response_type: NitroFileResponseType, pub active_dir: String, } #[derive(Serialize, Deserialize, Clone, Debug)] -pub enum ResponseType { +pub enum NitroFileResponseType { Project(Option), Version(VersionBrowseResponse), - Repository(RepositorySummary), + Repository(RepositoryConfig), Storage, Other, } @@ -27,9 +29,9 @@ pub struct VersionBrowseResponse { pub version: String, } -#[derive(Serialize, Deserialize, Clone, Debug)] +#[derive(Serialize, Clone, Debug)] pub struct NitroFile { - pub response_type: ResponseType, + pub response_type: NitroFileResponseType, #[serde(flatten)] pub file: StorageFile, } @@ -72,7 +74,15 @@ pub struct ProjectData { #[serde(default = "crate::utils::get_current_time")] pub updated: i64, } - +impl Default for ProjectData { + fn default() -> Self { + ProjectData { + versions: Default::default(), + created: get_current_time(), + updated: get_current_time(), + } + } +} #[derive(Debug, Serialize, Deserialize, Clone)] pub struct ProjectSource { pub name: String, @@ -120,7 +130,8 @@ impl From for NitroVersion { } impl NitroRepoVersions { - pub fn update_version(&mut self, version: String) { + pub fn update_version>(&mut self, version: S) { + let version = version.into(); for v in self.versions.iter_mut() { if v.version.eq(&version) { if !v.snapshot { diff --git a/backend/src/repository/nitro/nitro_repository.rs b/backend/src/repository/nitro/nitro_repository.rs new file mode 100644 index 00000000..31fb4ab0 --- /dev/null +++ b/backend/src/repository/nitro/nitro_repository.rs @@ -0,0 +1,237 @@ +use crate::repository::response::Project; +use crate::storage::models::Storage; + +use crate::constants::{PROJECT_FILE, VERSION_DATA}; +use crate::error::internal_error::InternalError; +use async_trait::async_trait; +use log::{debug, error, trace}; + +use crate::repository::data::RepositoryConfig; + +use crate::repository::nitro::utils::{ + get_project_data, get_version_data, get_versions, update_project_in_repositories, +}; +use crate::repository::nitro::{ + NitroFile, NitroFileResponse, NitroFileResponseType, NitroRepoVersions, ProjectData, + VersionData, +}; +use crate::storage::file::StorageDirectoryResponse; +use crate::storage::DynamicStorage; +use crate::system::user::UserModel; + +#[async_trait] +pub trait NitroRepositoryHandler { + fn parse_project_to_directory>(value: S) -> String; + fn storage(&self) -> &DynamicStorage; + fn repository(&self) -> &RepositoryConfig; + /// Handles a List of versions request + async fn get_versions( + &self, + project: &str, + ) -> Result, InternalError> { + Ok(Some( + get_versions( + self.storage(), + self.repository(), + Self::parse_project_to_directory(project), + ) + .await?, + )) + } + async fn get_project_specific_version( + &self, + + project: &str, + version: &str, + ) -> Result, InternalError> { + let project_dir = Self::parse_project_to_directory(project); + + let project_data = + get_project_data(self.storage(), self.repository(), &project_dir.clone()).await?; + if let Some(project_data) = project_data { + let version_data = get_version_data( + self.storage(), + self.repository(), + &format!("{}/{}", project_dir, &version), + ) + .await?; + + let project = Project { + repo_summary: self.repository().clone(), + project: project_data, + version: version_data, + frontend_response: None, + }; + return Ok(Some(project)); + } + return Ok(None); + } + async fn get_project_latest(&self, project: &str) -> Result, InternalError> { + let project_dir = Self::parse_project_to_directory(project); + + let project_data = + get_project_data(self.storage(), self.repository(), &project_dir).await?; + if let Some(project_data) = project_data { + let version_data = get_version_data( + self.storage(), + self.repository(), + &format!("{}/{}", &project_dir, &project_data.versions.latest_version), + ) + .await?; + + let project = Project { + repo_summary: self.repository().clone(), + project: project_data, + version: version_data, + frontend_response: None, + }; + return Ok(Some(project)); + } + return Ok(None); + } + + /// Returns the latest version published. + async fn latest_version(&self, project: &str) -> Result, InternalError> { + let project_dir = Self::parse_project_to_directory(project); + let project_data = + get_project_data(self.storage(), self.repository(), &project_dir).await?; + if let Some(project_data) = project_data { + let latest_release = project_data.versions.latest_release; + if latest_release.is_empty() { + Ok(Some(project_data.versions.latest_version)) + } else { + Ok(Some(latest_release)) + } + } else { + Ok(None) + } + } + + async fn process_storage_files( + &self, + directory: StorageDirectoryResponse, + requested_dir: &str, + ) -> Result { + let mut nitro_files = Vec::new(); + for file in directory.files { + nitro_files.push(NitroFile { + //TODO Implement This + response_type: NitroFileResponseType::Other, + file, + }); + } + let value = if let Some(project_data) = + get_project_data(self.storage(), self.repository(), requested_dir).await? + { + let version_data = get_version_data( + self.storage(), + self.repository(), + &format!( + "{}/{}", + &requested_dir, &project_data.versions.latest_version + ), + ) + .await?; + + let project = Project { + repo_summary: self.repository().clone(), + project: project_data, + version: version_data, + frontend_response: None, + }; + NitroFileResponseType::Project(Some(project)) + } else if let Some(version) = + get_version_data(self.storage(), self.repository(), requested_dir).await? + { + let project_dir = Self::parse_project_to_directory(&version.name); + let project = get_project_data(self.storage(), self.repository(), &project_dir) + .await? + .unwrap(); + + let project = Project { + repo_summary: self.repository().clone(), + project, + version: Some(version), + frontend_response: None, + }; + NitroFileResponseType::Project(Some(project)) + } else { + NitroFileResponseType::Other + }; + Ok(NitroFileResponse { + files: nitro_files, + response_type: value, + active_dir: requested_dir.to_string(), + }) + } + + /// Handles the Update Process and Post Deploy tasks for a Nitro Repository + async fn post_deploy( + &self, + project_folder: String, + version_folder: String, + _: UserModel, + version_data: VersionData, + ) -> Result<(), InternalError> { + let project_file = format!("{}/{}", &project_folder, PROJECT_FILE); + let version_file = format!("{}/{}", &version_folder, VERSION_DATA); + trace!("Project File Location {}", project_file); + trace!("Version File Location {}", version_file); + let result: Result<(), InternalError> = { + let option = self + .storage() + .get_file(self.repository(), &project_file) + .await?; + let mut project_data: ProjectData = if let Some(data) = option { + let string = String::from_utf8(data)?; + let value = serde_json::from_str(&string)?; + self.storage() + .delete_file(self.repository(), &project_file) + .await?; + value + } else { + debug!("Creating new Project Data Value"); + ProjectData::default() + }; + project_data.versions.update_version(&version_data.version); + self.storage() + .save_file( + self.repository(), + serde_json::to_string_pretty(&project_data)?.as_bytes(), + &project_file, + ) + .await?; + self.storage() + .save_file( + self.repository(), + serde_json::to_string_pretty(&version_data)?.as_bytes(), + &version_folder, + ) + .await?; + Ok(()) + }; + if let Err(error) = result { + error!("Unable to update {}, {}", PROJECT_FILE, error); + trace!( + "Version {} Name: {}", + &version_data.version, + &version_data.name + ); + } + if let Err(error) = update_project_in_repositories( + self.storage(), + self.repository(), + version_data.name.clone(), + ) + .await + { + error!("Unable to update repository.json, {}", error); + trace!( + "Version {} Name: {}", + &version_data.version, + &version_data.name + ); + } + Ok(()) + } +} diff --git a/backend/src/repository/nitro/utils.rs b/backend/src/repository/nitro/utils.rs new file mode 100644 index 00000000..a43c9803 --- /dev/null +++ b/backend/src/repository/nitro/utils.rs @@ -0,0 +1,130 @@ +use crate::constants::{PROJECTS_FILE, PROJECT_FILE, VERSION_DATA}; +use crate::error::internal_error::InternalError; +use crate::repository::data::RepositoryConfig; +use crate::repository::nitro::{NitroRepoVersions, ProjectData, RepositoryListing, VersionData}; +use crate::repository::response::VersionResponse; + +use crate::storage::models::Storage; +use crate::storage::DynamicStorage; +use log::debug; +use std::fs::read_to_string; +use std::path::Path; + +pub async fn get_version( + storage: &DynamicStorage, + repository: &RepositoryConfig, + project: String, + version: String, +) -> Result, InternalError> { + let versions_value = get_versions(storage, repository, project).await?; + Ok(get_version_by_data(&versions_value, version)) +} + +pub fn get_version_by_data( + versions_value: &NitroRepoVersions, + version: String, +) -> Option { + for x in &versions_value.versions { + if x.version.eq(&version) { + return Some(VersionResponse { + version: x.clone(), + other: Default::default(), + }); + } + } + None +} + +pub async fn update_project_in_repositories( + storage: &DynamicStorage, + repository: &RepositoryConfig, + project: String, +) -> Result<(), InternalError> { + let option = storage.get_file(repository, PROJECTS_FILE).await?; + let mut repo_listing: RepositoryListing = if let Some(data) = option { + let data = String::from_utf8(data)?; + storage.delete_file(repository, PROJECTS_FILE).await?; + serde_json::from_str(&data)? + } else { + RepositoryListing { values: vec![] } + }; + + repo_listing.add_value(project); + let string = serde_json::to_string_pretty(&repo_listing)?; + storage + .save_file(repository, string.as_bytes(), PROJECTS_FILE) + .await?; + Ok(()) +} + +pub async fn get_versions( + storage: &DynamicStorage, + repository: &RepositoryConfig, + path: String, +) -> Result { + let string = format!("{}/{}", path, PROJECT_FILE); + let option = storage.get_file(repository, &string).await?; + Ok(if let Some(vec) = option { + let data: ProjectData = serde_json::from_str(&String::from_utf8(vec)?)?; + data.versions + } else { + Default::default() + }) +} + +pub fn get_latest_version(path: &Path, release: bool) -> Option { + let versions = path.join(".nitro.versions.json"); + if versions.exists() { + let option: NitroRepoVersions = + serde_json::from_str(&read_to_string(&versions).unwrap()).unwrap(); + get_latest_version_data(&option, release) + } else { + None + } +} + +pub fn get_latest_version_data( + versions_value: &NitroRepoVersions, + release: bool, +) -> Option { + if release { + Some(versions_value.latest_release.clone()) + } else { + Some(versions_value.latest_version.clone()) + } +} + +pub async fn get_project_data( + storage: &DynamicStorage, + repository: &RepositoryConfig, + project: &str, +) -> Result, InternalError> { + let string = format!("{}/{}", project, PROJECT_FILE); + debug!("Project Data Location {}", &string); + let option = storage.get_file(repository, &string).await?; + Ok(if let Some(vec) = option { + let mut data: ProjectData = serde_json::from_str(&String::from_utf8(vec)?)?; + if data.versions.latest_release.is_empty() { + data.versions.latest_release = data.versions.latest_version.clone(); + } + Some(data) + } else { + None + }) +} +pub async fn get_version_data( + storage: &DynamicStorage, + repository: &RepositoryConfig, + folder: &str, +) -> Result, InternalError> { + let string = format!("{}/{}", folder, VERSION_DATA); + debug!("Version Data Location {}", &string); + let option = storage.get_file(repository, &string).await?; + Ok(if let Some(vec) = option { + let data: VersionData = serde_json::from_str(&String::from_utf8(vec)?)?; + + Some(data) + } else { + None + }) +} diff --git a/backend/src/repository/npm/error.rs b/backend/src/repository/npm/error.rs new file mode 100644 index 00000000..26df4153 --- /dev/null +++ b/backend/src/repository/npm/error.rs @@ -0,0 +1,25 @@ +use std::error::Error; +use std::fmt::{Display, Formatter}; + +#[derive(Debug)] +pub struct NPMError(String); + +impl Display for NPMError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl Error for NPMError {} + +impl From<&str> for NPMError { + fn from(err: &str) -> NPMError { + NPMError(err.to_string()) + } +} + +impl From for NPMError { + fn from(err: String) -> NPMError { + NPMError(err) + } +} diff --git a/backend/src/repository/npm/mod.rs b/backend/src/repository/npm/mod.rs index 36c25fdb..97aad2dd 100644 --- a/backend/src/repository/npm/mod.rs +++ b/backend/src/repository/npm/mod.rs @@ -1,48 +1,76 @@ use std::collections::HashMap; -use crate::constants::PROJECT_FILE; use actix_web::web::Bytes; -use actix_web::HttpRequest; -use diesel::MysqlConnection; -use log::Level::Trace; -use log::{debug, error, log_enabled, trace}; + +use actix_web::http::header::HeaderMap; +use actix_web::http::StatusCode; + +use log::{debug, error, trace}; use regex::Regex; +use sea_orm::DatabaseConnection; use std::string::String; -use crate::error::internal_error::InternalError; -use crate::repository::deploy::{handle_post_deploy, DeployInfo}; -use crate::repository::models::RepositorySummary; - use crate::repository::npm::models::{Attachment, LoginRequest, LoginResponse, PublishRequest}; -use crate::repository::npm::utils::{generate_get_response, is_valid, parse_project_to_directory}; +use crate::repository::npm::utils::generate_get_response; + +use crate::authentication::{verify_login, Authentication}; -use crate::repository::types::RepoResponse::{ - BadRequest, CreatedWithJSON, IAmATeapot, NotAuthorized, NotFound, ProjectResponse, -}; -use crate::repository::types::{ - Project, RepoResponse, RepoResult, RepositoryRequest, RepositoryHandler, -}; -use crate::repository::utils::{get_project_data, get_versions, process_storage_files}; -use crate::system::utils::{can_deploy_basic_auth, can_read_basic_auth}; +use crate::repository::response::RepoResponse; +use crate::storage::models::Storage; +use crate::system::permissions::options::CanIDo; +use crate::system::user::UserModel; +pub mod error; pub mod models; mod utils; -pub struct NPMHandler; +use crate::repository::data::RepositoryConfig; +use crate::repository::handler::RepositoryHandler; +use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; + +use crate::error::api_error::APIError; +use crate::error::internal_error::InternalError; +use crate::storage::file::StorageFileResponse; +use crate::storage::DynamicStorage; +use async_trait::async_trait; +use tokio::sync::RwLockReadGuard; + +pub struct NPMHandler<'a> { + config: RepositoryConfig, + storage: RwLockReadGuard<'a, DynamicStorage>, +} +impl<'a> NPMHandler<'a> { + pub fn create( + repository: RepositoryConfig, + storage: RwLockReadGuard<'a, DynamicStorage>, + ) -> NPMHandler<'a> { + NPMHandler { + config: repository, + storage, + } + } + fn bad_npm_command() -> actix_web::Error { + APIError::from(("Bad NPM Command", StatusCode::BAD_REQUEST)).into() + } +} // name/version -impl RepositoryHandler for NPMHandler { - fn handle_get( - request: &RepositoryRequest, - http: &HttpRequest, - conn: &MysqlConnection, - ) -> RepoResult { - if !can_read_basic_auth(http.headers(), &request.repository, conn)?.0 { - return RepoResult::Ok(NotAuthorized); +#[async_trait] +impl<'a> RepositoryHandler<'a> for NPMHandler<'a> { + async fn handle_get( + &self, + path: &str, + headers: &HeaderMap, + conn: &DatabaseConnection, + authentication: Authentication, + ) -> Result { + let caller: UserModel = authentication.get_user(conn).await??; + if let Some(value) = caller.can_read_from(&self.config)? { + return Err(value.into()); } - if http.headers().get("npm-command").is_some() { - if request.value.contains(".tgz") { - let split: Vec<&str> = request.value.split("/-/").collect(); + if headers.get("npm-command").is_some() { + if path.contains(".tgz") { + let split: Vec<&str> = path.split("/-/").collect(); let package = split.get(0).unwrap().to_string(); let file = split.get(1).unwrap().to_string(); let version = file @@ -53,107 +81,90 @@ impl RepositoryHandler for NPMHandler { "Trying to Retrieve Package: {} Version {}. Location {}", &package, &version, &nitro_file_location ); - let result = request.storage.get_file_as_response( - &request.repository, - &nitro_file_location, - http, - )?; - return if result.is_left() { - Ok(RepoResponse::FileResponse(result.left().unwrap())) - } else { - Ok(BadRequest("Expected File got Folder".to_string())) - }; + + let result = self + .storage + .get_file_as_response(&self.config, &nitro_file_location) + .await + .map_err(InternalError::from)?; + return Ok(RepoResponse::FileResponse(result)); } - let get_response = - generate_get_response(&request.storage, &request.repository, &request.value) - .unwrap(); + let get_response = generate_get_response(&self.storage, &self.config, path) + .await + .unwrap(); if get_response.is_none() { - return Ok(NotFound); + return Err(APIError::not_found().into()); } - let string = serde_json::to_string_pretty(&get_response.unwrap())?; - Ok(RepoResponse::OkWithJSON(string)) + let string = + serde_json::to_value(&get_response.unwrap()).map_err(InternalError::from)?; + Ok(RepoResponse::Json(string, StatusCode::OK)) } else { - let result = - request - .storage - .get_file_as_response(&request.repository, &request.value, http)?; - if result.is_left() { - Ok(RepoResponse::FileResponse(result.left().unwrap())) - } else { - let vec = result.right().unwrap(); - - let file_response = process_storage_files( - &request.storage, - &request.repository, - vec, - &request.value, - )?; - Ok(RepoResponse::NitroFileList(file_response)) + match self + .storage + .get_file_as_response(&self.config, path) + .await + .map_err(InternalError::from)? + { + StorageFileResponse::List(list) => { + let files = self.process_storage_files(list, path).await?; + Ok(RepoResponse::try_from((files, StatusCode::OK))?) + } + value => Ok(RepoResponse::FileResponse(value)), } } } - fn handle_post( - _request: &RepositoryRequest, - _http: &HttpRequest, - _conn: &MysqlConnection, - _bytes: Bytes, - ) -> RepoResult { - Ok(IAmATeapot("POST is not handled in NPM".to_string())) - } + async fn handle_put( + &self, - fn handle_put( - request: &RepositoryRequest, - http: &HttpRequest, - conn: &MysqlConnection, + path: &str, + headers: &HeaderMap, + conn: &DatabaseConnection, + authentication: Authentication, bytes: Bytes, - ) -> RepoResult { - for x in http.headers() { - log::trace!("Header {}: {}", x.0, x.1.to_str().unwrap()); - } - log::trace!("URL: {}", request.value); + ) -> Result { let user = Regex::new(r"-/user/org\.couchdb\.user:[a-zA-Z]+").unwrap(); // Check if its a user verification request - if user.is_match(request.value.as_str()) { + if user.is_match(path) { let content = String::from_utf8(bytes.as_ref().to_vec()).unwrap(); let json: LoginRequest = serde_json::from_str(content.as_str()).unwrap(); - let username = request.value.replace("-/user/org.couchdb.user:", ""); - return if is_valid(&username, &json, conn)? { - trace!("User Request for {} was authorized", &username); - let message = format!("user '{}' created", username); - Ok(CreatedWithJSON(serde_json::to_string(&LoginResponse { - ok: message, - })?)) - } else { - trace!("User Request for {} was not authorized", &username); - Ok(NotAuthorized) - }; + let username = path.replace("-/user/org.couchdb.user:", ""); + let user = verify_login(username, json.password, conn).await??; + trace!("User Request for {} was authorized", &user.username); + let message = format!("user '{}' created", user.username); + let created_response = serde_json::to_value(&LoginResponse { ok: message }) + .map_err(InternalError::from)?; + return Ok(RepoResponse::Json(created_response, StatusCode::CREATED)); } //Handle Normal Request - let (allowed, user) = can_deploy_basic_auth(http.headers(), &request.repository, conn)?; - if !allowed { - return RepoResult::Ok(NotAuthorized); + let caller: UserModel = authentication.get_user(conn).await??; + if let Some(value) = caller.can_deploy_to(&self.config)? { + return Err(value.into()); } - let user = user.unwrap(); - if let Some(npm_command) = http.headers().get("npm-command") { + if let Some(npm_command) = headers.get("npm-command") { let npm_command = npm_command.to_str().unwrap(); - trace!("NPM {} Command {}", &request.value, &npm_command); + trace!("NPM {} Command {}", &path, &npm_command); if npm_command.eq("publish") { - let publish_request: PublishRequest = serde_json::from_slice(bytes.as_ref())?; - let attachments: HashMap> = publish_request + let publish_request: PublishRequest = + serde_json::from_slice(bytes.as_ref()).map_err(APIError::bad_request)?; + + let attachments: HashMap> = publish_request ._attachments .iter() - .map(|(key, value)| { - let attachment: serde_json::Result = - serde_json::from_value(value.clone()); + .map(|(key, path)| { + let attachment: Result = + serde_json::from_value(path.clone()).map_err(APIError::bad_request); (key.clone(), attachment) }) .collect(); + let mut exists = false; for (attachment_key, attachment) in attachments { let attachment = attachment?; - let attachment_data = base64::decode(attachment.data)?; + let attachment_data = + base64::decode(attachment.data).map_err(APIError::bad_request)?; for (version, version_data) in publish_request.versions.iter() { - let version_data_string = serde_json::to_string(version_data)?; + let version_data_string = + serde_json::to_string(version_data).map_err(APIError::bad_request)?; trace!( "Publishing {} Version: {} File:{} Data {}", &publish_request.name, @@ -165,203 +176,77 @@ impl RepositoryHandler for NPMHandler { format!("{}/{}/{}", &publish_request.name, version, &attachment_key); let npm_version_data = format!("{}/{}/package.json", &publish_request.name, version); - request.storage.save_file( - &request.repository, - attachment_data.as_ref(), - &attachment_file_loc, - )?; - request.storage.save_file( - &request.repository, - version_data_string.as_bytes(), - &npm_version_data, - )?; + + if self + .storage + .save_file(&self.config, attachment_data.as_ref(), &attachment_file_loc) + .await + .map_err(InternalError::from)? + { + exists = true + }; + + if self + .storage + .save_file( + &self.config, + version_data_string.as_bytes(), + &npm_version_data, + ) + .await + .map_err(InternalError::from)? + { + exists = true; + }; let project_folder = publish_request.name.clone(); + let version_folder = + format!("{}/{}", &project_folder, &version_data.version); + trace!("Project Folder Location {}", project_folder); - let repository = request.repository.clone(); - let storage = request.storage.clone(); let version_for_saving = version_data.clone(); - let user = user.clone(); - actix_web::rt::spawn(async move { - if let Err(error) = crate::repository::npm::utils::update_project( - &storage, - &repository, - &project_folder, - version_for_saving.clone(), - ) { - error!("Unable to update {}, {}", PROJECT_FILE, error); - if log_enabled!(Trace) { - trace!( - "Version {} Name: {}", - &version_for_saving.version, - &version_for_saving.name - ); - } - } - - if let Err(error) = - crate::repository::utils::update_project_in_repositories( - &storage, - &repository, - version_for_saving.name.clone(), + let user = caller.clone(); + if let Err(error) = self + .post_deploy( + project_folder, + version_folder, + user, + version_for_saving.into(), ) - { - error!("Unable to update repository.json, {}", error); - if log_enabled!(Trace) { - trace!( - "Version {} Name: {}", - &version_for_saving.version, - &version_for_saving.name - ); - } - } - let info = DeployInfo { - user: user.clone(), - version: version_for_saving.version.clone(), - name: version_for_saving.name.clone(), - version_folder: format!( - "{}/{}", - &project_folder, &version_for_saving.version - ), - }; - - debug!("Starting Post Deploy Tasks"); - if log_enabled!(Trace) { - trace!("Data {}", &info); - } - let deploy = handle_post_deploy(&storage, &repository, &info).await; - if let Err(error) = deploy { - error!("Error Handling Post Deploy Tasks {}", error); - } else { - debug!("All Post Deploy Tasks Completed and Happy :)"); - } - }); + .await + { + error!("Unable to complete post processing Tasks {}", error); + } } } - return Ok(RepoResponse::Ok); + return Ok(RepoResponse::PUTResponse( + exists, + format!( + "/storages/{}/{}/{}", + &self.storage.storage_config().name, + &self.config.name, + path + ), + )); } - Ok(BadRequest(format!("Bad Request {}", npm_command))) + Err(NPMHandler::bad_npm_command()) } else { - Ok(BadRequest("Missing NPM-Command".to_string())) - } - } - - fn handle_patch( - _request: &RepositoryRequest, - _http: &HttpRequest, - _conn: &MysqlConnection, - _bytes: Bytes, - ) -> RepoResult { - Ok(IAmATeapot("Patch is not handled in NPM".to_string())) - } - - fn handle_head( - _request: &RepositoryRequest, - _http: &HttpRequest, - _conn: &MysqlConnection, - ) -> RepoResult { - Ok(IAmATeapot("HEAD is not handled in NPM".to_string())) - } - - fn handle_versions( - request: &RepositoryRequest, - http: &HttpRequest, - conn: &MysqlConnection, - ) -> RepoResult { - if !can_read_basic_auth(http.headers(), &request.repository, conn)?.0 { - return RepoResult::Ok(NotAuthorized); + Err(NPMHandler::bad_npm_command()) } - - let vec = get_versions(&request.storage, &request.repository, request.value.clone())?; - Ok(RepoResponse::NitroVersionListingResponse(vec)) } +} - fn handle_version( - request: &RepositoryRequest, - version: String, - http: &HttpRequest, - conn: &MysqlConnection, - ) -> RepoResult { - if !can_read_basic_auth(http.headers(), &request.repository, conn)?.0 { - return RepoResult::Ok(NotAuthorized); - } - let project_dir = parse_project_to_directory(&request.value); - - let project_data = - get_project_data(&request.storage, &request.repository, project_dir.clone())?; - if let Some(project_data) = project_data { - let version_data = crate::repository::utils::get_version_data( - &request.storage, - &request.repository, - format!("{}/{}", project_dir, &version), - )?; - - let project = Project { - repo_summary: RepositorySummary::new(&request.repository), - project: project_data, - version: version_data, - frontend_response: None, - }; - return Ok(ProjectResponse(project)); - } - RepoResult::Ok(NotFound) +impl NitroRepositoryHandler for NPMHandler<'_> { + fn parse_project_to_directory>(path: S) -> String { + path.into().replace('.', "/").replace(':', "/") } - fn handle_project( - request: &RepositoryRequest, - http: &HttpRequest, - conn: &MysqlConnection, - ) -> RepoResult { - for x in http.headers() { - log::trace!("Header {}: {}", x.0, x.1.to_str().unwrap()); - } - log::trace!("URL: {}", request.value); - if !can_read_basic_auth(http.headers(), &request.repository, conn)?.0 { - return RepoResult::Ok(NotAuthorized); - } - let project_dir = parse_project_to_directory(&request.value); - - let project_data = - get_project_data(&request.storage, &request.repository, project_dir.clone())?; - if let Some(project_data) = project_data { - let version_data = crate::repository::utils::get_version_data( - &request.storage, - &request.repository, - format!("{}/{}", project_dir, &project_data.versions.latest_version), - )?; - - let project = Project { - repo_summary: RepositorySummary::new(&request.repository), - project: project_data, - version: version_data, - frontend_response: None, - }; - return Ok(ProjectResponse(project)); - } - RepoResult::Ok(NotFound) + fn storage(&self) -> &DynamicStorage { + &self.storage } - fn latest_version( - request: &RepositoryRequest, - http: &HttpRequest, - conn: &MysqlConnection, - ) -> Result, InternalError> { - if !can_read_basic_auth(http.headers(), &request.repository, conn)?.0 { - return Ok(None); - } - let project_dir = parse_project_to_directory(&request.value); - - let project_data = get_project_data(&request.storage, &request.repository, project_dir)?; - Ok(if let Some(project_data) = project_data { - let latest_release = project_data.versions.latest_release; - if latest_release.is_empty() { - Some(project_data.versions.latest_version) - } else { - Some(latest_release) - } - } else { - None - }) + fn repository(&self) -> &RepositoryConfig { + &self.config } } diff --git a/backend/src/repository/npm/models.rs b/backend/src/repository/npm/models.rs index af119a2a..9db25f0c 100644 --- a/backend/src/repository/npm/models.rs +++ b/backend/src/repository/npm/models.rs @@ -1,11 +1,23 @@ use std::collections::HashMap; +use crate::repository::data::RepositorySetting; +use crate::repository::nitro::VersionData; +use crate::utils::get_current_time; use serde::{Deserialize, Serialize}; use serde_json::Value; -#[derive(Debug, Serialize, Deserialize, Clone,Default)] -pub struct NPMSettings{ +#[derive(Debug, Serialize, Deserialize, Clone, Default)] +pub struct NPMSettings {} +impl TryFrom for NPMSettings { + type Error = serde_json::Error; + + fn try_from(value: Value) -> Result { + serde_json::from_value(value) + } } + +impl RepositorySetting for NPMSettings {} + #[derive(Debug, Serialize, Deserialize)] pub struct LoginRequest { pub password: String, @@ -40,11 +52,24 @@ pub struct Dist { pub struct Version { pub version: String, pub name: String, + #[serde(default)] + pub description: String, pub dist: Dist, #[serde(flatten)] pub other: HashMap, } - +impl Into for Version { + fn into(self) -> VersionData { + VersionData { + name: self.name, + description: self.description, + source: None, + licence: None, + version: self.version, + created: get_current_time(), + } + } +} #[derive(Debug, Serialize, Deserialize)] pub struct DistTags { pub latest: String, diff --git a/backend/src/repository/npm/utils.rs b/backend/src/repository/npm/utils.rs index 50921e3b..fb16ddc6 100644 --- a/backend/src/repository/npm/utils.rs +++ b/backend/src/repository/npm/utils.rs @@ -1,46 +1,18 @@ use std::collections::HashMap; -use log::{trace, warn}; +use log::warn; use chrono::{DateTime, NaiveDateTime, Utc}; -use crate::error::internal_error::InternalError; -use crate::repository::nitro::{NitroRepoVersions, ProjectData, VersionData}; - -use crate::repository::utils::get_project_data; -use crate::utils::get_current_time; +use crate::repository::nitro::{NitroRepoVersions, ProjectData}; -use crate::constants::{PROJECT_FILE, VERSION_DATA}; -use crate::repository::models::Repository; -use argon2::{Argon2, PasswordHash, PasswordVerifier}; -use diesel::MysqlConnection; +use crate::error::internal_error::InternalError; +use crate::repository::data::RepositoryConfig; +use crate::repository::nitro::utils::get_project_data; -use crate::repository::npm::models::{ - DistTags, GetResponse, LoginRequest, NPMTimes, NPMVersions, Version, -}; -use crate::storage::models::StringStorage; -use crate::system::action::get_user_by_username; - -pub fn is_valid( - username: &str, - request: &LoginRequest, - conn: &MysqlConnection, -) -> Result { - let result1 = get_user_by_username(username, conn)?; - if result1.is_none() { - return Ok(false); - } - let argon2 = Argon2::default(); - let user = result1.unwrap(); - let parsed_hash = PasswordHash::new(user.password.as_str())?; - if argon2 - .verify_password(request.password.as_bytes(), &parsed_hash) - .is_err() - { - return Ok(false); - } - Ok(true) -} +use crate::repository::npm::models::{DistTags, GetResponse, NPMTimes, NPMVersions, Version}; +use crate::storage::models::Storage; +use crate::storage::DynamicStorage; static NPM_TIME_FORMAT: &str = "%Y-%m-%dT%H:%M:%S.%3fZ"; @@ -63,61 +35,9 @@ impl From for HashMap { } } -pub fn update_project( - storage: &StringStorage, - repository: &Repository, - project_folder: &str, - version: Version, -) -> Result<(), InternalError> { - let project_file = format!("{}/{}", project_folder, PROJECT_FILE); - let version_folder = format!("{}/{}/{}", &project_folder, &version.version, VERSION_DATA); - - trace!("Project File Location {}", project_file); - let option = storage.get_file(repository, &project_file)?; - let mut project_data: ProjectData = if let Some(data) = option { - let string = String::from_utf8(data)?; - let value = serde_json::from_str(&string)?; - storage.delete_file(repository, &project_file)?; - value - } else { - ProjectData { - versions: Default::default(), - created: get_current_time(), - updated: get_current_time(), - } - }; - project_data.updated = get_current_time(); - let horrible_line_of_code = if let Some(desc) = version.other.get("description") { - desc.as_str().unwrap().to_string() - } else { - "".to_string() - }; - - let version_data = VersionData { - name: version.name, - description: horrible_line_of_code, - source: None, - licence: None, - version: version.version.clone(), - created: get_current_time(), - }; - project_data.versions.update_version(version.version); - storage.save_file( - repository, - serde_json::to_string_pretty(&project_data)?.as_bytes(), - &project_file, - )?; - storage.save_file( - repository, - serde_json::to_string_pretty(&version_data)?.as_bytes(), - &version_folder, - )?; - Ok(()) -} - -pub fn get_version_data( - storage: &StringStorage, - repository: &Repository, +pub async fn get_version_data( + storage: &DynamicStorage, + repository: &RepositoryConfig, project_folder: &str, project: &ProjectData, ) -> Result<(NPMTimes, DistTags, NPMVersions), InternalError> { @@ -136,7 +56,7 @@ pub fn get_version_data( .times .insert(version.version.clone(), format_time(version.time)); let version_path = format!("{}/{}/package.json", project_folder, &version.version); - let result = storage.get_file(repository, &version_path)?; + let result = storage.get_file(repository, &version_path).await?; if result.is_none() { warn!("{} not found", version_path); continue; @@ -149,20 +69,20 @@ pub fn get_version_data( Ok((times, dist_tags, npm_versions)) } -pub fn generate_get_response( - storage: &StringStorage, - repository: &Repository, +pub async fn generate_get_response( + storage: &DynamicStorage, + repository: &RepositoryConfig, project_folder: &str, ) -> Result, InternalError> { - let option = get_project_data(storage, repository, project_folder.to_string())?; + let option = get_project_data(storage, repository, project_folder).await?; if option.is_none() { return Ok(None); } let project_data = option.unwrap(); let (times, dist_tags, versions) = - get_version_data(storage, repository, project_folder, &project_data)?; + get_version_data(storage, repository, project_folder, &project_data).await?; let version_path = format!("{}/{}/package.json", project_folder, &dist_tags.latest); - let result = storage.get_file(repository, &version_path)?; + let result = storage.get_file(repository, &version_path).await?; if result.is_none() { warn!("{} not found", version_path); return Ok(None); @@ -176,7 +96,3 @@ pub fn generate_get_response( dist_tags, })) } - -pub fn parse_project_to_directory(value: &str) -> String { - value.replace('.', "/").replace(':', "/") -} diff --git a/backend/src/repository/public.rs b/backend/src/repository/public.rs deleted file mode 100644 index 787e7f43..00000000 --- a/backend/src/repository/public.rs +++ /dev/null @@ -1,62 +0,0 @@ -use actix_web::{get, web, HttpRequest}; -use serde::{Deserialize, Serialize}; - -use crate::api_response::{APIResponse, SiteResponse}; -use crate::database::DbPool; -use crate::error::response::{not_found, unauthorized}; -use crate::repository::models::{Repository}; -use crate::system::utils::can_read_basic_auth; -use crate::NitroRepoData; -use crate::repository::settings::Policy; -use crate::repository::settings::security::Visibility; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct PublicRepositoryResponse { - pub name: String, - pub repo_type: String, - pub storage: String, - pub description: String, - pub active: bool, - pub visibility: Visibility, - pub policy: Policy, - pub created: i64, -} - -impl From for PublicRepositoryResponse { - fn from(repo: Repository) -> Self { - PublicRepositoryResponse { - name: repo.name, - repo_type: repo.repo_type.to_string(), - storage: repo.storage, - description: repo.settings.description, - active: repo.settings.active, - visibility: repo.security.visibility, - policy: repo.settings.policy, - created: repo.created, - } - } -} - -#[get("/api/repositories/get/{storage}/{repo}")] -pub async fn get_repo( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, - path: web::Path<(String, String)>, -) -> SiteResponse { - let (storage, repo) = path.into_inner(); - let guard = site.storages.read().await; - if let Some(storage) = guard.get(&storage) { - let option = storage.get_repository(&repo)?; - if let Some(repository) = option { - if repository.security.visibility.eq(&Visibility::Private) { - let connection = pool.get()?; - if !can_read_basic_auth(r.headers(), &repository, &connection)?.0 { - return unauthorized(); - } - } - return APIResponse::respond_new(Some(PublicRepositoryResponse::from(repository)), &r); - } - } - not_found() -} diff --git a/backend/src/repository/response.rs b/backend/src/repository/response.rs new file mode 100644 index 00000000..e9fd7790 --- /dev/null +++ b/backend/src/repository/response.rs @@ -0,0 +1,79 @@ +use actix_web::body::BoxBody; +use actix_web::http::header::CONTENT_LOCATION; +use actix_web::http::StatusCode; +use actix_web::web::Json; +use actix_web::{HttpRequest, HttpResponse, Responder}; +use std::collections::HashMap; + +use crate::error::internal_error::InternalError; +use serde::{Deserialize, Serialize}; +use serde_json::Value; + +use crate::repository::data::RepositoryConfig; + +use crate::repository::frontend::FrontendResponse; + +use crate::repository::nitro::{NitroVersion, ProjectData, VersionData}; +use crate::storage::file::StorageFileResponse; + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct RepositoryFile { + pub name: String, + pub full_path: String, + pub directory: bool, + pub data: HashMap, +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct Project { + pub repo_summary: RepositoryConfig, + pub project: ProjectData, + /// Version Data will be latest if not specified + pub version: Option, + pub frontend_response: Option, +} + +/// Types of Valid Repo Responses +pub enum RepoResponse { + FileResponse(StorageFileResponse), + HttpResponse(HttpResponse), + Json(Value, StatusCode), + PUTResponse(bool, String), +} +impl TryFrom<(T, StatusCode)> for RepoResponse { + type Error = InternalError; + + fn try_from((value, status): (T, StatusCode)) -> Result { + let result = serde_json::to_value(value)?; + return Ok(Self::Json(result, status)); + } +} +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct VersionResponse { + pub version: NitroVersion, + #[serde(flatten)] + pub other: HashMap, +} +impl Responder for RepoResponse { + type Body = BoxBody; + + fn respond_to(self, req: &HttpRequest) -> HttpResponse { + match self { + RepoResponse::FileResponse(file) => file.respond_to(req), + RepoResponse::HttpResponse(http) => http, + RepoResponse::Json(value, status) => Json(value) + .customize() + .with_status(status) + .respond_to(req) + .map_into_boxed_body(), + RepoResponse::PUTResponse(exists, content_location) => { + let header = (CONTENT_LOCATION, content_location); + if exists { + return HttpResponse::Created().insert_header(header).finish(); + } else { + return HttpResponse::NoContent().insert_header(header).finish(); + } + } + } + } +} diff --git a/backend/src/repository/settings/frontend.rs b/backend/src/repository/settings/frontend.rs index 5a7b2a61..61fe5af2 100644 --- a/backend/src/repository/settings/frontend.rs +++ b/backend/src/repository/settings/frontend.rs @@ -1,5 +1,5 @@ use badge_maker::Style; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; fn default() -> bool { true @@ -7,13 +7,12 @@ fn default() -> bool { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Frontend { - #[serde(default = "default")] - pub enabled: bool, #[serde(default = "PageProvider::default")] pub page_provider: PageProvider, + #[serde(default)] + pub description: String, } - #[derive(Debug, Clone, Serialize, Deserialize)] pub enum BadgeStyle { Flat, @@ -79,12 +78,11 @@ impl PageProvider { } } - impl Default for Frontend { fn default() -> Self { Frontend { - enabled: true, page_provider: PageProvider::None, + description: "".to_string(), } } -} \ No newline at end of file +} diff --git a/backend/src/repository/settings/mod.rs b/backend/src/repository/settings/mod.rs index 033f51ad..9f7c4ff2 100644 --- a/backend/src/repository/settings/mod.rs +++ b/backend/src/repository/settings/mod.rs @@ -1,13 +1,12 @@ use crate::repository::settings::frontend::{BadgeSettings, Frontend}; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; -pub mod security; pub mod frontend; +pub mod security; pub mod webhook; -fn default() -> bool { - true -} +pub const WEBHOOK_CONFIG: &str = ".nitro_repo/webhook.json"; +pub const FRONTEND_CONFIG: &str = ".nitro_repo/frontend.json"; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, strum_macros::EnumString)] pub enum Policy { @@ -24,48 +23,19 @@ impl Default for Policy { #[derive(Debug, Deserialize, Serialize, Clone)] pub struct RepositorySettings { - #[serde(default = "default")] - pub active: bool, - #[serde(default)] - pub description: String, - #[serde(default)] - pub policy: Policy, #[serde(default)] pub frontend: Frontend, - #[serde(default )] + #[serde(default)] pub badge: BadgeSettings, } -impl Default for RepositorySettings { - fn default() -> Self { - RepositorySettings { - active: true, - description: "".to_string(), - policy: Policy::Mixed, - frontend: Default::default(), - badge: Default::default(), - } - } -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct UpdateSettings { - pub active: bool, - pub policy: Policy, -} - #[derive(Debug, Serialize, Deserialize)] pub struct UpdateFrontend { pub frontend: Frontend, pub badge: BadgeSettings, } - impl RepositorySettings { - pub fn update_general(&mut self, settings: UpdateSettings) { - self.policy = settings.policy; - self.active = settings.active; - } pub fn update_frontend(&mut self, settings: UpdateFrontend) { self.frontend = settings.frontend; self.badge = settings.badge; diff --git a/backend/src/repository/settings/security.rs b/backend/src/repository/settings/security.rs index 706b219b..cf5254e7 100644 --- a/backend/src/repository/settings/security.rs +++ b/backend/src/repository/settings/security.rs @@ -1,4 +1,4 @@ -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, strum_macros::EnumString)] pub enum Visibility { @@ -13,19 +13,5 @@ impl Default for Visibility { } } - #[derive(Debug, Deserialize, Serialize, Clone, Default)] -pub struct SecurityRules { - #[serde(default = "Visibility::default")] - pub visibility: Visibility, - -} - -impl SecurityRules { - pub fn update(&mut self, security: SecurityRules) { - self.visibility = security.visibility; - } - pub fn set_visibility(&mut self, visibility: Visibility) { - self.visibility = visibility; - } -} +pub struct SecurityRules {} diff --git a/backend/src/repository/settings/webhook.rs b/backend/src/repository/settings/webhook.rs index 9952a1d0..baf0fe9d 100644 --- a/backend/src/repository/settings/webhook.rs +++ b/backend/src/repository/settings/webhook.rs @@ -1,7 +1,7 @@ +use serde::{Deserialize, Serialize}; +use serde_json::Value; use std::collections::HashMap; use std::ops::Deref; -use serde::{Serialize, Deserialize}; -use serde_json::Value; #[derive(Serialize, Deserialize, Clone, Debug)] pub enum ReportValues { @@ -69,4 +69,4 @@ impl DeploySettings { None } } -} \ No newline at end of file +} diff --git a/backend/src/repository/types.rs b/backend/src/repository/types.rs deleted file mode 100644 index 004f2716..00000000 --- a/backend/src/repository/types.rs +++ /dev/null @@ -1,153 +0,0 @@ -use std::collections::HashMap; - -use actix_web::web::Bytes; -use actix_web::HttpRequest; -use diesel::MysqlConnection; - -use serde::{Deserialize, Serialize}; -use serde_json::Value; - -use crate::error::internal_error::InternalError; -use crate::repository::frontend::FrontendResponse; -use crate::repository::models::{Repository, RepositorySummary}; -use crate::repository::nitro::{ - NitroFileResponse, NitroRepoVersions, NitroVersion, ProjectData, VersionData, -}; -use crate::storage::models::Storage; -use crate::storage::StorageFile; -use crate::{SiteResponse, StringMap}; -use strum_macros::{Display, EnumString}; -use crate::repository::maven::models::MavenSettings; -use crate::repository::npm::models::NPMSettings; - -#[derive(Serialize, Deserialize, Clone, Debug, Display, EnumString)] -pub enum RepositoryType { - Maven(MavenSettings), - NPM(NPMSettings), -} - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct RepositoryFile { - pub name: String, - pub full_path: String, - pub directory: bool, - pub data: HashMap, -} - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct Project { - pub repo_summary: RepositorySummary, - pub project: ProjectData, - /// Version Data will be latest if not specified - pub version: Option, - pub frontend_response: Option, -} - -/// Types of Valid Repo Responses -pub enum RepoResponse { - FileList(Vec), - NitroFileList(NitroFileResponse), - /// Responds all the information about the project - ProjectResponse(Project), - /// Respond a file so it can be downloaded - FileResponse(SiteResponse), - /// Ok - Ok, - //Ok With Json - OkWithJSON(String), - /// CREATED WITH_JSON - CreatedWithJSON(String), - /// Not Found - NotFound, - /// Not Authorized - NotAuthorized, - /// Bad Request - BadRequest(String), - /// I am A Teapot. This is a joke. And is used inside Maven to state that Such as POST and PATCH - IAmATeapot(String), - /// A list of versions in a specific artifact. This is generated in Maven by bad code - VersionListingResponse(Vec), - /// Classic Version Response will be removed - NitroProjectResponse(ProjectData), - NitroVersionListingResponse(NitroRepoVersions), - NitroVersionResponse(VersionResponse), -} - -/// RepoResult -pub type RepoResult = Result; - -/// This is a Request to a Repository Handler -pub struct RepositoryRequest { - /// The Storage that the Repo needs to be in - pub storage: Storage, - /// The Repository it needs to be in - pub repository: Repository, - /// Everything in the URL path after /storages/{STORAGE}/{REPOSITORY} - pub value: String, -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct VersionResponse { - pub version: NitroVersion, - #[serde(flatten)] - pub other: HashMap, -} - -pub trait RepositoryHandler { - /// Handles a get request to a Repo - fn handle_get( - request: &RepositoryRequest, - http: &HttpRequest, - conn: &MysqlConnection, - ) -> RepoResult; - /// Handles a Post Request to a Repo - fn handle_post( - request: &RepositoryRequest, - http: &HttpRequest, - conn: &MysqlConnection, - bytes: Bytes, - ) -> RepoResult; - /// Handles a PUT Request to a Repo - fn handle_put( - request: &RepositoryRequest, - http: &HttpRequest, - conn: &MysqlConnection, - bytes: Bytes, - ) -> RepoResult; - /// Handles a PATCH Request to a Repo - fn handle_patch( - request: &RepositoryRequest, - http: &HttpRequest, - conn: &MysqlConnection, - bytes: Bytes, - ) -> RepoResult; - /// Handles a HEAD Request to a Repo - fn handle_head( - request: &RepositoryRequest, - http: &HttpRequest, - conn: &MysqlConnection, - ) -> RepoResult; - /// Handles a List of versions request - fn handle_versions( - request: &RepositoryRequest, - http: &HttpRequest, - conn: &MysqlConnection, - ) -> RepoResult; - fn handle_version( - request: &RepositoryRequest, - version: String, - http: &HttpRequest, - conn: &MysqlConnection, - ) -> RepoResult; - fn handle_project( - request: &RepositoryRequest, - http: &HttpRequest, - conn: &MysqlConnection, - ) -> RepoResult; - /// Returns the latest version published. - fn latest_version( - request: &RepositoryRequest, - http: &HttpRequest, - conn: &MysqlConnection, - ) -> Result, InternalError>; -} diff --git a/backend/src/repository/utils.rs b/backend/src/repository/utils.rs deleted file mode 100644 index ff4e3033..00000000 --- a/backend/src/repository/utils.rs +++ /dev/null @@ -1,206 +0,0 @@ -use crate::constants::{PROJECTS_FILE, PROJECT_FILE, VERSION_DATA}; -use crate::error::internal_error::{InternalError, NResult}; -use crate::repository::models::{Repository, RepositorySummary}; -use crate::repository::nitro::{ - NitroFile, NitroFileResponse, NitroRepoVersions, ProjectData, RepositoryListing, ResponseType, - VersionData, -}; -use crate::repository::types::{Project, VersionResponse}; -use crate::storage::models::StringStorage; -use crate::storage::StorageFile; -use log::debug; -use std::fs::read_to_string; -use std::path::Path; - -pub fn get_version( - storage: &StringStorage, - repository: &Repository, - project: String, - version: String, -) -> NResult> { - let versions_value = get_versions(storage, repository, project)?; - Ok(get_version_by_data(&versions_value, version)) -} - -pub fn process_storage_files( - storage: &StringStorage, - repo: &Repository, - storage_files: Vec, - requested_dir: &str, -) -> Result { - let mut nitro_files = Vec::new(); - for file in storage_files { - nitro_files.push(NitroFile { - //TODO Implement This - response_type: ResponseType::Other, - file, - }); - } - let active_dir = format!("{}/{}/{}", &storage.name, &repo.name, requested_dir); - let string = format!("{}/{}", &requested_dir, PROJECT_FILE); - let option = storage.get_file(repo, &string)?; - return if let Some(data) = option { - let mut data: ProjectData = serde_json::from_slice(data.as_slice())?; - if data.versions.latest_release.is_empty() { - data.versions.latest_release = data.versions.latest_version.clone(); - } - let version_data = get_version_data( - storage, - repo, - format!("{}/{}", requested_dir, data.versions.latest_release), - )?; - let project = Project { - repo_summary: RepositorySummary::new(repo), - project: data, - version: version_data, - frontend_response: None, - }; - Ok(NitroFileResponse { - files: nitro_files, - response_type: ResponseType::Project(Some(project)), - active_dir, - }) - } else { - let string = format!("{}/{}", &requested_dir, VERSION_DATA); - let option = storage.get_file(repo, &string)?; - - if let Some(version) = option { - let version: VersionData = serde_json::from_slice(version.as_slice())?; - - let x = Path::new(&requested_dir).parent().unwrap(); - let string = format!("{}/{}", x.to_str().unwrap(), PROJECT_FILE); - let option = storage.get_file(repo, &string)?; - - let mut project_data: ProjectData = serde_json::from_slice(option.unwrap().as_slice())?; - if project_data.versions.latest_release.is_empty() { - project_data.versions.latest_release = project_data.versions.latest_version.clone(); - } - let project = Project { - repo_summary: RepositorySummary::new(repo), - project: project_data, - version: Some(version), - frontend_response: None, - }; - - Ok(NitroFileResponse { - files: nitro_files, - active_dir, - - response_type: ResponseType::Project(Some(project)), - }) - } else { - Ok(NitroFileResponse { - active_dir, - files: nitro_files, - response_type: ResponseType::Repository(RepositorySummary::new(repo)), - }) - } - }; -} - -pub fn get_version_by_data( - versions_value: &NitroRepoVersions, - version: String, -) -> Option { - for x in &versions_value.versions { - if x.version.eq(&version) { - return Some(VersionResponse { - version: x.clone(), - other: Default::default(), - }); - } - } - None -} - -pub fn update_project_in_repositories( - storage: &StringStorage, - repository: &Repository, - project: String, -) -> Result<(), InternalError> { - let option = storage.get_file(repository, PROJECTS_FILE)?; - let mut repo_listing: RepositoryListing = if let Some(data) = option { - let data = String::from_utf8(data)?; - storage.delete_file(repository, PROJECTS_FILE)?; - serde_json::from_str(&data)? - } else { - RepositoryListing { values: vec![] } - }; - - repo_listing.add_value(project); - let string = serde_json::to_string_pretty(&repo_listing)?; - storage.save_file(repository, string.as_bytes(), PROJECTS_FILE)?; - Ok(()) -} - -pub fn get_versions( - storage: &StringStorage, - repository: &Repository, - path: String, -) -> Result { - let string = format!("{}/{}", path, PROJECT_FILE); - let option = storage.get_file(repository, &string)?; - Ok(if let Some(vec) = option { - let data: ProjectData = serde_json::from_str(&String::from_utf8(vec)?)?; - data.versions - } else { - Default::default() - }) -} - -pub fn get_latest_version(path: &Path, release: bool) -> Option { - let versions = path.join(".nitro.versions.json"); - if versions.exists() { - let option: NitroRepoVersions = - serde_json::from_str(&read_to_string(&versions).unwrap()).unwrap(); - get_latest_version_data(&option, release) - } else { - None - } -} - -pub fn get_latest_version_data( - versions_value: &NitroRepoVersions, - release: bool, -) -> Option { - if release { - Some(versions_value.latest_release.clone()) - } else { - Some(versions_value.latest_version.clone()) - } -} - -pub fn get_project_data( - storage: &StringStorage, - repository: &Repository, - project: String, -) -> Result, InternalError> { - let string = format!("{}/{}", project, PROJECT_FILE); - debug!("Project Data Location {}", &string); - let option = storage.get_file(repository, &string)?; - Ok(if let Some(vec) = option { - let mut data: ProjectData = serde_json::from_str(&String::from_utf8(vec)?)?; - if data.versions.latest_release.is_empty() { - data.versions.latest_release = data.versions.latest_version.clone(); - } - Some(data) - } else { - None - }) -} -pub fn get_version_data( - storage: &StringStorage, - repository: &Repository, - folder: String, -) -> Result, InternalError> { - let string = format!("{}/{}", folder, VERSION_DATA); - debug!("Version Data Location {}", &string); - let option = storage.get_file(repository, &string)?; - Ok(if let Some(vec) = option { - let data: VersionData = serde_json::from_str(&String::from_utf8(vec)?)?; - - Some(data) - } else { - None - }) -} diff --git a/backend/src/schema.rs b/backend/src/schema.rs deleted file mode 100644 index 7c3a4172..00000000 --- a/backend/src/schema.rs +++ /dev/null @@ -1,39 +0,0 @@ -table! { - users (id) { - id -> Bigint, - name -> Text, - username -> Text, - email -> Text, - password -> Text, - permissions -> Text, - created ->Bigint, - - } -} -table! { - session_tokens (id) { - id -> Bigint, - user -> Bigint, - token -> Text, - expiration ->Bigint, - created ->Bigint, - } -} -table! { - auth_tokens (id) { - id -> Bigint, - user -> Bigint, - token -> Text, - expiration ->Bigint, - created ->Bigint, - } -} -table! { - forgot_passwords (id) { - id -> Bigint, - user -> Bigint, - token -> Text, - expiration ->Bigint, - created ->Bigint, - } -} diff --git a/backend/src/settings/controller.rs b/backend/src/settings/controller.rs deleted file mode 100644 index 28f793cb..00000000 --- a/backend/src/settings/controller.rs +++ /dev/null @@ -1,24 +0,0 @@ -use actix_web::web::Data; -use actix_web::{get, HttpRequest}; -use std::ops::Deref; - -use crate::api_response::{APIResponse, SiteResponse}; -use crate::error::response::unauthorized; -use crate::system::utils::get_user_by_header; -use crate::{Database, NitroRepo}; - -#[get("/api/settings/report")] -pub async fn setting_report( - site: Data, - database: Database, - r: HttpRequest, -) -> SiteResponse { - let connection = database.get()?; - - let user = get_user_by_header(r.headers(), &connection)?; - if user.is_none() || !user.unwrap().permissions.admin { - return unauthorized(); - } - let settings = site.settings.read().await; - APIResponse::from(Some(settings.deref())).respond(&r) -} diff --git a/backend/src/settings/mod.rs b/backend/src/settings/mod.rs index c952ea1d..268e7d6c 100644 --- a/backend/src/settings/mod.rs +++ b/backend/src/settings/mod.rs @@ -1,8 +1,22 @@ -use actix_web::web; +use std::fs::create_dir_all; +use crate::settings::models::{EmailSetting, SecuritySettings, SiteSetting}; +use crate::Settings; + +use std::path::{Path, PathBuf}; +use tokio::fs::read_to_string; -pub mod controller; pub mod models; -pub fn init(cfg: &mut web::ServiceConfig) { - cfg.service(controller::setting_report); + +pub async fn load_configs(configs: PathBuf) -> anyhow::Result { + let security: SecuritySettings = + toml::from_str(&read_to_string(configs.join("security.toml")).await?)?; + let site: SiteSetting = toml::from_str(&read_to_string(configs.join("site.toml")).await?)?; + let email: EmailSetting = toml::from_str(&read_to_string(configs.join("email.toml")).await?)?; + + Ok(Settings { + email, + site, + security, + }) } diff --git a/backend/src/settings/models.rs b/backend/src/settings/models.rs index 1aa4f51a..b13aafb3 100644 --- a/backend/src/settings/models.rs +++ b/backend/src/settings/models.rs @@ -1,7 +1,11 @@ use crate::error::internal_error::InternalError; + +use semver::{Error, Version}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::fmt::{Display, Formatter}; +use sea_orm::ConnectOptions; +use sea_orm::DbErr::Conn; #[derive(Debug, Deserialize, Serialize, Clone)] pub enum Mode { @@ -29,6 +33,12 @@ pub struct Internal { pub version: String, } +impl Internal { + pub fn parse_version(&self) -> Result { + semver::Version::parse(&self.version) + } +} + impl Default for Internal { fn default() -> Self { Self { @@ -39,15 +49,22 @@ impl Default for Internal { } #[derive(Debug, Deserialize, Serialize, Clone)] -pub struct Database { - #[serde(rename = "type")] - pub db_type: String, - #[serde(flatten)] - pub settings: T, +#[serde(tag = "type", content = "settings")] +pub enum Database { + Mysql(MysqlSettings) +} + +impl Into for Database { + fn into(self) -> ConnectOptions { + match self { + Database::Mysql(mysql) => { + ConnectOptions::new(mysql.to_string()) + } + } + } } pub type StringMap = HashMap; -pub type GenericDatabase = Database; impl Display for MysqlSettings { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { @@ -59,31 +76,6 @@ impl Display for MysqlSettings { } } -impl TryFrom for MysqlSettings { - type Error = InternalError; - - fn try_from(mut value: StringMap) -> Result { - let user = value - .remove("user") - .ok_or_else(|| InternalError::ConfigError("database.user".to_string()))?; - let password = value - .remove("password") - .ok_or_else(|| InternalError::ConfigError("database.password".to_string()))?; - let host = value - .remove("host") - .ok_or_else(|| InternalError::ConfigError("database.host".to_string()))?; - let database = value - .remove("database") - .ok_or_else(|| InternalError::ConfigError("database.database".to_string()))?; - Ok(MysqlSettings { - user, - password, - host, - database, - }) - } -} - #[derive(Debug, Deserialize, Serialize, Clone)] pub struct MysqlSettings { pub user: String, @@ -105,11 +97,11 @@ pub struct Application { #[derive(Debug, Deserialize, Serialize, Clone)] pub struct GeneralSettings { - pub database: Database, + pub database: Database, pub application: Application, pub internal: Internal, #[serde(default)] - pub env: HashMap + pub session: SessionSettings, } #[derive(Debug, Deserialize, Serialize, Clone)] @@ -118,6 +110,11 @@ pub struct SiteSetting { pub description: String, } +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct SessionSettings { + pub manager: String, +} + #[derive(Debug, Deserialize, Serialize, Clone)] pub struct SecuritySettings {} @@ -130,6 +127,7 @@ pub struct EmailSetting { pub from: String, pub port: u16, } + #[allow(clippy::derivable_impls)] impl Default for SecuritySettings { fn default() -> Self { @@ -158,3 +156,11 @@ impl Default for EmailSetting { } } } + +impl Default for SessionSettings { + fn default() -> Self { + SessionSettings { + manager: "BasicSessionManager".to_string(), + } + } +} diff --git a/backend/src/storage/admin/controller.rs b/backend/src/storage/admin/controller.rs deleted file mode 100644 index dd0ef5a8..00000000 --- a/backend/src/storage/admin/controller.rs +++ /dev/null @@ -1,116 +0,0 @@ -use actix_web::{delete, get, post, web, HttpRequest, HttpResponse}; -use serde::{Deserialize, Serialize}; -use std::collections::HashMap; - -use crate::api_response::{APIResponse, SiteResponse}; - -use crate::database::DbPool; -use crate::error::internal_error::InternalError; -use crate::error::response::{already_exists, unauthorized}; -use crate::storage::models::{save_storages, LocationType, Storage}; -use crate::system::utils::get_user_by_header; -use crate::utils::get_current_time; -use crate::{NitroRepoData, StringMap}; -use log::warn; -use std::fs::{canonicalize, create_dir_all}; -use std::ops::Deref; -use std::path::Path; -use crate::system::permissions::options::CanIDo; - -#[get("/api/storages/list")] -pub async fn list_storages( - pool: web::Data, - site: NitroRepoData, - r: HttpRequest, -) -> Result { - let connection = pool.get()?; - if get_user_by_header(r.headers(), &connection)?.can_i_edit_repos().is_err() { - return unauthorized(); - } - let guard = site.storages.read().await; - let values: Vec> = guard.values().cloned().collect(); - APIResponse::new(true, Some(values)).respond(&r) -} - -#[delete("/api/admin/storages/{id}")] -pub async fn delete_by_id( - pool: web::Data, - r: HttpRequest, - site: NitroRepoData, - id: web::Path, -) -> SiteResponse { - let connection = pool.get()?; - if get_user_by_header(r.headers(), &connection)?.can_i_edit_repos().is_err() { - return unauthorized(); - } - let mut guard = site.storages.write().await; - if let Some(storage) = guard.remove(&id.into_inner()) { - //Yes I am exporting everything being deleted - warn!( - " Deleted Storage {}", - serde_json::to_string(&storage).unwrap() - ); - save_storages(guard.deref())?; - APIResponse::from(true).respond(&r) - } else { - APIResponse::from(false).respond(&r) - } -} - -#[get("/api/storages/id/{id}")] -pub async fn get_by_id( - pool: web::Data, - r: HttpRequest, - site: NitroRepoData, - id: web::Path, -) -> SiteResponse { - let connection = pool.get()?; - if get_user_by_header(r.headers(), &connection)?.can_i_edit_repos().is_err() { - return unauthorized(); - } - let guard = site.storages.read().await; - - return APIResponse::new(true, guard.get(&id.into_inner())).respond(&r); -} - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct NewStorage { - pub name: String, - pub public_name: String, -} - -#[post("/api/admin/storages/add")] -pub async fn add_storage( - pool: web::Data, - r: HttpRequest, - nc: web::Json, - site: NitroRepoData, -) -> SiteResponse { - let connection = pool.get()?; - if get_user_by_header(r.headers(), &connection)?.can_i_edit_repos().is_err() { - return unauthorized(); - } - let mut guard = site.storages.write().await; - for (_, storage) in guard.iter() { - if storage.name.eq(&nc.name) || storage.public_name.eq(&nc.public_name) { - return already_exists(); - } - } - let path = Path::new("storages").join(&nc.0.name); - if !path.exists() { - create_dir_all(&path)?; - } - let path = canonicalize(path)?; - let string = nc.0.name; - let storage = Storage { - public_name: nc.0.public_name, - name: string.clone(), - created: get_current_time(), - location_type: LocationType::LocalStorage, - location: HashMap::from([("location".to_string(), path.to_str().unwrap().to_string())]), - }; - guard.insert(string.clone(), storage); - save_storages(guard.deref())?; - - APIResponse::new(true, guard.get(&string)).respond(&r) -} diff --git a/backend/src/storage/admin/mod.rs b/backend/src/storage/admin/mod.rs deleted file mode 100644 index 9f4f5e8b..00000000 --- a/backend/src/storage/admin/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -use actix_web::web; - -pub mod controller; - -pub fn init(cfg: &mut web::ServiceConfig) { - cfg.service(controller::add_storage) - .service(controller::delete_by_id) - .service(controller::list_storages) - .service(controller::get_by_id); -} diff --git a/backend/src/storage/bad_storage.rs b/backend/src/storage/bad_storage.rs new file mode 100644 index 00000000..11fdcf7b --- /dev/null +++ b/backend/src/storage/bad_storage.rs @@ -0,0 +1,160 @@ +use crate::storage::models::{ + Storage, StorageConfig, StorageFactory, StorageSaver, StorageStatus, StorageType, +}; + +use log::warn; + +use crate::repository::data::{RepositoryConfig, RepositoryType}; +use crate::storage::error::StorageError; +use async_trait::async_trait; + +use serde_json::Value; + +use crate::storage::file::{StorageFile, StorageFileResponse}; +use tokio::sync::RwLockReadGuard; + +/// This is a storage that is here to represent a storage that failed to load from the config stage +#[derive(Debug)] +pub struct BadStorage { + pub factory: StorageFactory, + pub status: StorageStatus, +} +impl BadStorage { + pub fn create(factory: StorageFactory, error: StorageError) -> BadStorage { + BadStorage { + factory, + status: StorageStatus::CreateError(error), + } + } +} +#[async_trait] +impl Storage for BadStorage { + fn new(_: StorageFactory) -> Result + where + Self: Sized, + { + panic!("This should not be called!") + } + async fn load(&mut self) -> Result<(), StorageError> { + warn!("Unable to load Storage Error {}", self.status); + Ok(()) + } + + fn unload(&mut self) -> Result<(), StorageError> { + warn!("Unloaded the Bad Storage"); + Ok(()) + } + + fn config_for_saving(&self) -> StorageSaver { + StorageSaver { + storage_type: self.factory.storage_type.clone(), + generic_config: self.factory.generic_config.clone(), + handler_config: self.factory.handler_config.clone(), + } + } + + fn storage_config(&self) -> &StorageConfig { + &self.factory.generic_config + } + + fn impl_config(&self) -> Value { + self.factory.handler_config.clone() + } + + fn storage_type(&self) -> &StorageType { + &self.factory.storage_type + } + + fn status(&self) -> &StorageStatus { + &self.status + } + + async fn create_repository( + &self, + _name: String, + _repository_type: RepositoryType, + ) -> Result<(), StorageError> { + panic!("This should not be called!") + } + + async fn delete_repository( + &self, + _repository: &RepositoryConfig, + _delete_files: bool, + ) -> Result<(), StorageError> { + panic!("This should not be called!") + } + + async fn get_repositories(&self) -> Result, StorageError> { + panic!("This should not be called!") + } + + async fn get_repository( + &self, + _repository: &str, + ) -> Result>, StorageError> { + panic!("This should not be called!") + } + + async fn update_repository(&self, _repository: RepositoryConfig) -> Result<(), StorageError> { + panic!("This should not be called!") + } + + async fn update_repository_config( + &self, + _repository: &RepositoryConfig, + _file: &str, + _data: &Option, + ) -> Result<(), StorageError> { + panic!("This should not be called!") + } + + async fn get_repository_config( + &self, + _repository: &RepositoryConfig, + _file: &str, + ) -> Result, StorageError> { + panic!("This should not be called!") + } + + async fn save_file( + &self, + _repository: &RepositoryConfig, + _file: &[u8], + _location: &str, + ) -> Result { + panic!("This should not be called!") + } + + async fn delete_file( + &self, + _repository: &RepositoryConfig, + _location: &str, + ) -> Result<(), StorageError> { + panic!("This should not be called!") + } + + async fn get_file_as_response( + &self, + _repository: &RepositoryConfig, + _location: &str, + ) -> Result { + panic!("This should not be called!") + } + + async fn get_file_information( + &self, + _repository: &RepositoryConfig, + _location: &str, + ) -> Result, StorageError> { + panic!("This should not be called!") + } + + async fn get_file( + &self, + _repository: &RepositoryConfig, + _location: &str, + ) -> Result>, StorageError> { + panic!("This should not be called!") + } +} diff --git a/backend/src/storage/error.rs b/backend/src/storage/error.rs new file mode 100644 index 00000000..e23c776c --- /dev/null +++ b/backend/src/storage/error.rs @@ -0,0 +1,39 @@ +use std::time::SystemTimeError; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum StorageError { + #[error("{0}")] + LoadFailure(String), + #[error("IO error {0}")] + IOError(std::io::Error), + #[error("JSON error {0}")] + JSONError(serde_json::Error), + #[error("Storage Already Exists!")] + StorageAlreadyExist, + #[error("Repository Already Exists")] + RepositoryAlreadyExists, + #[error("Missing Repository")] + RepositoryMissing, + #[error("Unable to find Parent Directory")] + ParentIssue, + #[error("Internal Error: {0}")] + InternalError(String), +} + +impl From for StorageError { + fn from(err: std::io::Error) -> StorageError { + StorageError::IOError(err) + } +} +impl From for StorageError { + fn from(err: SystemTimeError) -> StorageError { + StorageError::InternalError(err.to_string()) + } +} + +impl From for StorageError { + fn from(err: serde_json::Error) -> StorageError { + StorageError::JSONError(err) + } +} diff --git a/backend/src/storage/file.rs b/backend/src/storage/file.rs new file mode 100644 index 00000000..462087ab --- /dev/null +++ b/backend/src/storage/file.rs @@ -0,0 +1,180 @@ +use crate::error::api_error::APIError; + +use crate::storage::error::StorageError; +use actix_files::NamedFile; +use actix_web::body::BoxBody; +use actix_web::http::header::ACCEPT; +use actix_web::http::{Method, StatusCode}; +use actix_web::{HttpRequest, HttpResponse, Responder, ResponseError}; +use log::error; +use serde::Serialize; +use std::fs::{DirEntry, Metadata}; +use std::path::PathBuf; +use std::time::SystemTime; +use tokio::fs::OpenOptions; + +///Storage Files are just a data container holding the file name, directory relative to the root of nitro_repo and if its a directory +#[derive(Serialize, Clone, Debug)] +pub struct StorageFile { + pub name: String, + pub full_path: String, + pub mime: String, + pub directory: bool, + pub file_size: u64, + pub modified: u128, + pub created: u128, +} + +impl StorageFile { + fn meta_data(metadata: Metadata) -> (u128, u128, u64, bool) { + let created = metadata + .created() + .unwrap_or(SystemTime::now()) + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() + .as_micros(); + + let modified = if let Ok(modified) = metadata.modified() { + modified + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() + .as_micros() + } else { + created + }; + let directory = metadata.file_type().is_dir(); + let size = metadata.len(); + (created, modified, size, directory) + } + pub async fn create_from_entry>( + relative_path: S, + entry: &DirEntry, + ) -> Result { + let metadata = entry.metadata()?; + let (created, modified, file_size, directory) = Self::meta_data(metadata); + + let mime = mime_guess::from_path(entry.path()) + .first_or_octet_stream() + .to_string(); + let name = entry.file_name().to_str().unwrap().to_string(); + let file = StorageFile { + name, + full_path: relative_path.into(), + mime, + directory, + file_size, + modified, + created, + }; + Ok(file) + } + pub async fn create>( + relative_path: S, + file_location: &PathBuf, + ) -> Result { + let file = OpenOptions::new().read(true).open(&file_location).await?; + let metadata = file.metadata().await?; + let (created, modified, file_size, directory) = Self::meta_data(metadata); + + let mime = mime_guess::from_path(file_location) + .first_or_octet_stream() + .to_string(); + let name = file_location + .file_name() + .unwrap() + .to_str() + .unwrap() + .to_string(); + let file = StorageFile { + name, + full_path: relative_path.into(), + mime, + directory, + file_size, + modified, + created, + }; + Ok(file) + } +} +pub struct StorageDirectoryResponse { + pub files: Vec, + pub directory: StorageFile, +} +/// The Types of Storage File web responses it can have +pub enum StorageFileResponse { + /// A Location to a Local File + File(PathBuf), + /// A list of StorageFiles. Usually Responded when a directory + /// First Value is the Information About the directory + List(StorageDirectoryResponse), + /// Not Found + NotFound, +} +/// A Simple trait for handling file List responses +pub trait FileListResponder { + /// Parses the Accept the header(badly) to decide the Response Type + fn listing(self, request: &HttpRequest) -> Result + where + Self: std::marker::Sized, + { + if request.method() == Method::HEAD {} + return if let Some(accept) = request.headers().get(ACCEPT) { + let x = accept.to_str().map_err(APIError::bad_request)?; + if x.contains("application/json") { + self.json_listing(request) + } else if x.contains("text/html") { + self.html_listing(request) + } else { + Err(Self::invalid_accept_type().into()) + } + } else { + self.html_listing(request) + }; + } + /// Converts Self into a JSOn based Http Response + fn json_listing(self, request: &HttpRequest) -> Result + where + Self: std::marker::Sized; + /// Converts Self Into a HTML based HTTP Response + fn html_listing(self, _request: &HttpRequest) -> Result + where + Self: std::marker::Sized, + { + Err(Self::invalid_accept_type().into()) + } + /// For Internal Use + /// Invalid Data Type + fn invalid_accept_type() -> APIError { + APIError::from(("Invalid Accept Header", StatusCode::BAD_REQUEST)) + } +} +impl FileListResponder for StorageDirectoryResponse { + fn json_listing(self, request: &HttpRequest) -> Result + where + Self: std::marker::Sized, + { + Ok(HttpResponse::Ok().json(self.files).respond_to(request)) + } +} + +impl Responder for StorageFileResponse { + type Body = BoxBody; + + fn respond_to(self, req: &HttpRequest) -> HttpResponse { + match self { + StorageFileResponse::File(file) => match NamedFile::open(file) { + Ok(success) => success.respond_to(req), + Err(error) => { + error!("Unable to Respond with File {}", error); + HttpResponse::from_error(error).respond_to(req) + } + }, + StorageFileResponse::List(list) => match list.listing(req) { + Ok(response) => response, + Err(response) => response.error_response(), + }, + StorageFileResponse::NotFound => APIError::not_found().error_response(), + } + } +} diff --git a/backend/src/storage/local_storage.rs b/backend/src/storage/local_storage.rs deleted file mode 100644 index 1adc6d04..00000000 --- a/backend/src/storage/local_storage.rs +++ /dev/null @@ -1,342 +0,0 @@ -use crate::error::internal_error::InternalError; -use crate::repository::models::{Repository, RepositorySummary}; -use crate::repository::{REPOSITORY_CONF, REPOSITORY_CONF_BAK}; -use crate::storage::models::{LocationType, Storage}; -use crate::storage::{ - FileResponse, LocationHandler, RepositoriesFile, StorageFile, StorageFileResponse, - STORAGE_CONFIG, -}; -use crate::utils::get_current_time; -use crate::{SiteResponse, StringMap}; -use actix_files::NamedFile; -use actix_web::HttpRequest; -use either::Either; -use log::{debug, info, trace, warn}; -use serde::{Deserialize, Serialize}; -use std::collections::HashMap; -use std::fs; -use std::fs::{ - create_dir_all, read_dir, read_to_string, remove_dir_all, remove_file, File, OpenOptions, -}; -use std::io::{Read, Write}; -use std::path::{Path, PathBuf}; -use std::time::UNIX_EPOCH; -use crate::repository::types::RepositoryType; -use std::str::FromStr; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct LocalStorage { - pub location: String, -} - -pub struct LocalFile { - pub path: PathBuf, -} - -impl StorageFileResponse for LocalFile { - fn to_request(self, request: &HttpRequest) -> SiteResponse { - Ok(NamedFile::open(self.path)?.into_response(request)) - } -} - -impl LocalStorage { - pub fn get_storage_folder(storage: &Storage) -> PathBuf { - let location = storage.location.get("location").unwrap(); - PathBuf::from(location.clone()) - } - pub fn get_repository_folder(storage: &Storage, repository: &str) -> PathBuf { - LocalStorage::get_storage_folder(storage).join(repository) - } -} - -impl LocationHandler for LocalStorage { - fn init(storage: &Storage) -> Result<(), InternalError> { - let location = storage.location.get("location").unwrap(); - let path = Path::new(location); - if !path.exists() { - create_dir_all(&path)?; - } - let buf = path.join(STORAGE_CONFIG); - if buf.exists() { - remove_file(&buf)? - } - - Ok(()) - } - - fn create_repository( - storage: &Storage, - repository: RepositorySummary, - ) -> Result { - let location = storage.location.get("location").unwrap(); - let storages = Path::new(location); - let location = storages.join(&repository.name); - - { - let storage_config = storages.join(STORAGE_CONFIG); - info!( - "Adding Value to Storage Config {}", - storage_config.to_str().unwrap() - ); - let mut repos = if storage_config.exists() { - let string = read_to_string(&storage_config)?; - remove_file(&storage_config)?; - serde_json::from_str(&string)? - } else { - HashMap::::new() - }; - repos.insert(repository.name.clone(), repository.clone()); - let result = serde_json::to_string_pretty(&repos)?; - - let mut file = OpenOptions::new() - .write(true) - .create(true) - .open(storage_config)?; - file.write_all(result.as_bytes())?; - } - info!("Creating Directory {}", location.to_str().unwrap()); - let typ: RepositoryType = RepositoryType::from_str(&repository.repo_type).map_err(|typ| { - InternalError::InvalidRepositoryType(typ.to_string()) - })?; - create_dir_all(&location)?; - let repo = Repository { - name: repository.name, - repo_type: typ, - storage: repository.storage, - settings: Default::default(), - security: Default::default(), - deploy_settings: Default::default(), - created: get_current_time(), - }; - let result = serde_json::to_string_pretty(&repo)?; - - let config = location.join(REPOSITORY_CONF); - let mut file = OpenOptions::new().write(true).create(true).open(config)?; - file.write_all(result.as_bytes())?; - Ok(repo) - } - - fn delete_repository( - storage: &Storage, - repository: &Repository, - delete_files: bool, - ) -> Result<(), InternalError> { - let location = storage.location.get("location").unwrap(); - let storage_location = Path::new(location); - - let storage_config = storage_location.join(STORAGE_CONFIG); - let mut repos = if storage_config.exists() { - let string = read_to_string(&storage_config)?; - remove_file(&storage_config)?; - serde_json::from_str(&string)? - } else { - HashMap::::new() - }; - repos.remove(&repository.name); - let result = serde_json::to_string_pretty(&repos)?; - - let mut file = OpenOptions::new() - .write(true) - .create(true) - .open(storage_config)?; - file.write_all(result.as_bytes())?; - let path = storage_location.join(&repository.name); - - if delete_files { - warn!( - "All Files for {} are being deleted", - &path.to_str().unwrap() - ); - remove_dir_all(&path)?; - } else { - let config = storage_location - .join(&repository.name) - .join(REPOSITORY_CONF); - remove_file(config)?; - } - Ok(()) - } - - fn get_repositories(storage: &Storage) -> Result { - let location = storage.location.get("location").unwrap(); - - let path = Path::new(location).join(STORAGE_CONFIG); - if !path.exists() { - return Ok(HashMap::new()); - } - let string = read_to_string(&path)?; - let result: RepositoriesFile = serde_json::from_str(&string)?; - Ok(result) - } - - fn get_repository( - storage: &Storage, - repository: &str, - ) -> Result, InternalError> { - let location = storage.location.get("location").unwrap(); - let path = Path::new(location).join(repository).join(REPOSITORY_CONF); - - if !path.exists() { - return Ok(None); - } - let string = read_to_string(&path)?; - let result: Repository = serde_json::from_str(&string)?; - Ok(Some(result)) - } - - fn update_repository( - storage: &Storage, - repository: &Repository, - ) -> Result<(), InternalError> { - let location = storage.location.get("location").unwrap(); - let location = Path::new(location).join(&repository.name); - let config = location.join(REPOSITORY_CONF); - let bak = location.join(REPOSITORY_CONF_BAK); - if !config.exists() { - return Err(InternalError::NotFound); - } - if bak.exists() { - fs::remove_file(&bak)?; - } - fs::rename(&config, bak)?; - let result = serde_json::to_string(repository)?; - let mut file = OpenOptions::new().write(true).create(true).open(config)?; - file.write_all(result.as_bytes())?; - Ok(()) - } - - fn save_file( - storage: &Storage, - repository: &Repository, - data: &[u8], - location: &str, - ) -> Result<(), InternalError> { - let file_location = - LocalStorage::get_repository_folder(storage, &repository.name).join(location); - trace!("Saving File {:?}", &file_location); - create_dir_all( - file_location - .parent() - .ok_or_else(|| InternalError::from("Unable to Find Parent Location"))?, - )?; - - if file_location.exists() { - remove_file(&file_location)?; - } - let mut file = OpenOptions::new() - .write(true) - .create_new(true) - .create(true) - .open(&file_location)?; - file.write_all(data)?; - Ok(()) - } - - fn delete_file( - storage: &Storage, - repository: &Repository, - location: &str, - ) -> Result<(), InternalError> { - let file_location = - LocalStorage::get_repository_folder(storage, &repository.name).join(location); - remove_file(file_location)?; - Ok(()) - } - - fn get_file_as_response( - storage: &Storage, - repository: &Repository, - location: &str, - ) -> Result, InternalError> { - let file_location = - LocalStorage::get_repository_folder(storage, &repository.name).join(location); - if !file_location.exists() { - return Ok(Either::Right(vec![])); - } - if file_location.is_dir() { - let mut path = format!("{}/{}", storage.name, repository.name); - - for x in location.split('/') { - if !x.is_empty() { - path = format!("{}/{}", path, x); - } - } - trace!("Directory Listing at {:?}", &path); - - let dir = read_dir(&file_location)?; - let mut files = Vec::new(); - for x in dir { - let entry = x?; - let string = entry.file_name().into_string().unwrap(); - if string.ends_with(".nitro_repo") || string.starts_with(".nitro_repo") { - //Hide All .nitro_repo files from File Listings - continue; - } - let full = format!("{}/{}", path, &string); - let metadata = entry.metadata().unwrap(); - let time = metadata - .created() - .unwrap() - .duration_since(UNIX_EPOCH)? - .as_millis(); - let file = StorageFile { - name: string, - full_path: full, - directory: entry.file_type()?.is_dir(), - file_size: metadata.len(), - created: time, - }; - files.push(file); - } - - return Ok(Either::Right(files)); - } - trace!("Returning File {:?}", &file_location); - Ok(Either::Left(LocalFile { - path: file_location, - })) - } - fn get_file( - storage: &Storage, - repository: &Repository, - location: &str, - ) -> Result>, InternalError> { - let file_location = - LocalStorage::get_repository_folder(storage, &repository.name).join(location); - - debug!("Storage File Request {}", file_location.to_str().unwrap()); - if !file_location.exists() { - return Ok(None); - } - let mut file = File::open(file_location)?; - let mut bytes = Vec::new(); - file.read_to_end(&mut bytes)?; - Ok(Some(bytes)) - } -} - -impl TryFrom> for Storage { - type Error = InternalError; - - fn try_from(value: Storage) -> Result { - Ok(Self { - public_name: value.public_name, - name: value.name, - created: value.created, - location_type: LocationType::LocalStorage, - location: LocalStorage::try_from(value.location)?, - }) - } -} - -impl TryFrom for LocalStorage { - type Error = InternalError; - - fn try_from(mut value: StringMap) -> Result { - let location = value - .remove("location") - .ok_or_else(|| InternalError::ConfigError("storage missing location".to_string()))?; - - Ok(LocalStorage { location }) - } -} diff --git a/backend/src/storage/local_storage/mod.rs b/backend/src/storage/local_storage/mod.rs new file mode 100644 index 00000000..6c531f64 --- /dev/null +++ b/backend/src/storage/local_storage/mod.rs @@ -0,0 +1,407 @@ +use crate::repository::REPOSITORY_CONF_FOLDER; +use crate::storage::models::{ + Storage, StorageConfig, StorageFactory, StorageSaver, StorageStatus, StorageType, +}; +use crate::storage::STORAGE_CONFIG; +use crate::utils::get_current_time; + +use log::{debug, trace, warn}; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +use std::path::PathBuf; + +use crate::repository::data::{RepositoryConfig, RepositoryType}; +use crate::storage::error::StorageError; +use crate::storage::error::StorageError::RepositoryMissing; +use async_trait::async_trait; + +use serde_json::Value; + +use crate::storage::file::{StorageDirectoryResponse, StorageFile, StorageFileResponse}; +use tokio::fs::{create_dir, create_dir_all, read_to_string, remove_dir, remove_file, OpenOptions}; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tokio::sync::{RwLock, RwLockReadGuard}; + +#[derive(Debug)] +pub struct LocalStorage { + pub config: LocalConfig, + pub storage_config: StorageConfig, + pub status: StorageStatus, + pub repositories: RwLock>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct LocalConfig { + pub location: String, +} + +pub struct LocalFile { + pub path: PathBuf, +} + +impl LocalStorage { + pub fn get_storage_folder(&self) -> PathBuf { + PathBuf::from(&self.config.location) + } + pub fn get_repository_folder(&self, repository: &str) -> PathBuf { + self.get_storage_folder().join(repository) + } +} + +impl LocalStorage { + async fn load_repositories( + path: PathBuf, + ) -> Result, StorageError> { + if !path.exists() { + return Ok(HashMap::new()); + } + let string = read_to_string(&path).await?; + let result: Vec = serde_json::from_str(&string)?; + let mut values = HashMap::new(); + for x in result { + values.insert(x.name.clone(), x); + } + Ok(values) + } + async fn save_repositories(&self) -> Result<(), StorageError> { + let repositories = self.repositories.read().await; + let conf = self.get_storage_folder().join(STORAGE_CONFIG); + + let file = OpenOptions::new() + .create(true) + .open(conf) + .await? + .into_std() + .await; + let values: Vec<&RepositoryConfig> = repositories.values().collect(); + serde_json::to_writer_pretty(file, &values)?; + Ok(()) + } +} + +#[async_trait] +impl Storage for LocalStorage { + fn new(config: StorageFactory) -> Result + where + Self: Sized, + { + match serde_json::from_value::(config.handler_config.clone()) { + Ok(local) => { + let storage = LocalStorage { + storage_config: config.generic_config, + config: local, + repositories: RwLock::new(Default::default()), + status: StorageStatus::Unloaded, + }; + Ok(storage) + } + Err(error) => Err((StorageError::JSONError(error), config)), + } + } + async fn load(&mut self) -> Result<(), StorageError> { + if self.status == StorageStatus::Loaded { + return Err(StorageError::LoadFailure( + "Attempted Double Load".to_string(), + )); + } + let repositories = + Self::load_repositories(PathBuf::from(&self.config.location).join(STORAGE_CONFIG)) + .await?; + self.repositories = RwLock::new(repositories); + return Ok(()); + } + + fn unload(&mut self) -> Result<(), StorageError> { + let mut repositories = self.repositories.blocking_write(); + //repositories.drain() <--- Note to self. if we add a repository closing. Use this + repositories.clear(); + self.status = StorageStatus::Unloaded; + Ok(()) + } + fn config_for_saving(&self) -> StorageSaver { + let value = serde_json::to_value(self.config.clone()).unwrap(); + StorageSaver { + storage_type: StorageType::LocalStorage, + generic_config: self.storage_config.clone(), + handler_config: value, + } + } + + fn storage_config(&self) -> &StorageConfig { + &self.storage_config + } + + fn impl_config(&self) -> Value { + serde_json::to_value(self.config.clone()).unwrap() + } + + fn storage_type(&self) -> &StorageType { + &StorageType::LocalStorage + } + + fn status(&self) -> &StorageStatus { + &self.status + } + + async fn create_repository( + &self, + name: String, + repository_type: RepositoryType, + ) -> Result<(), StorageError> { + let mut repositories = self.repositories.write().await; + let repository_folder = self.get_repository_folder(&name); + if repositories.contains_key(&name) { + return Err(StorageError::RepositoryAlreadyExists); + } + if repository_folder.exists() { + warn!( + "Creating {:?} on already existing files. This could result in unexpected behavior", + &repository_folder + ); + } else { + create_dir_all(&repository_folder).await?; + } + let config = RepositoryConfig { + name: name.clone(), + repository_type, + storage: self.storage_config.name.clone(), + visibility: Default::default(), + active: true, + policy: Default::default(), + created: get_current_time(), + }; + let conf_folder = self + .get_repository_folder(&name) + .join(REPOSITORY_CONF_FOLDER); + if !conf_folder.exists() { + create_dir(&conf_folder).await?; + } + repositories.insert(name.clone(), config); + drop(repositories); + self.save_repositories().await?; + Ok(()) + } + + async fn delete_repository( + &self, + repository: &RepositoryConfig, + delete_files: bool, + ) -> Result<(), StorageError> { + let mut repositories = self.repositories.write().await; + if repositories.remove(&repository.name).is_none() { + return Err(RepositoryMissing); + } + let repository_folder = self.get_repository_folder(&repository.name); + + if delete_files { + remove_dir(repository_folder).await?; + } else { + let conf_folder = repository_folder.join(REPOSITORY_CONF_FOLDER); + if conf_folder.exists() { + remove_dir(conf_folder).await?; + } + } + drop(repositories); + self.save_repositories().await?; + Ok(()) + } + + async fn get_repositories(&self) -> Result, StorageError> { + let mut repositories_res = Vec::new(); + + let repositories = self.repositories.read().await; + for (_, config) in repositories.iter() { + repositories_res.push(config.clone()); + } + return Ok(repositories_res); + } + + async fn get_repository( + &self, + repository: &str, + ) -> Result>, StorageError> { + let repositories = self.repositories.read().await; + if !repositories.contains_key(repository) { + return Ok(None); + } + Ok(Some(RwLockReadGuard::map(repositories, |repos| { + repos.get(repository).unwrap() + }))) + } + + async fn update_repository(&self, repository: RepositoryConfig) -> Result<(), StorageError> { + let mut repositories = self.repositories.write().await; + if !repositories.contains_key(&repository.name) { + return Err(RepositoryMissing); + } + repositories.insert(repository.name.clone(), repository); + self.save_repositories().await?; + return Ok(()); + } + + async fn update_repository_config( + &self, + repository: &RepositoryConfig, + file: &str, + data: &Option, + ) -> Result<(), StorageError> { + let repositories = self.repositories.write().await; + if !repositories.contains_key(&repository.name) { + return Err(RepositoryMissing); + } + let conf = self + .get_repository_folder(&repository.name) + .join(REPOSITORY_CONF_FOLDER) + .join(file); + + if data.is_none() { + remove_file(&conf).await?; + } else if let Some(value) = data { + let file = OpenOptions::new() + .create(true) + .open(&conf) + .await? + .into_std() + .await; + serde_json::to_writer_pretty(file, value)?; + } + return Ok(()); + } + + async fn get_repository_config( + &self, + repository: &RepositoryConfig, + file: &str, + ) -> Result, StorageError> { + let repositories = self.repositories.write().await; + if !repositories.contains_key(&repository.name) { + return Err(RepositoryMissing); + } + let conf = self + .get_repository_folder(&repository.name) + .join(REPOSITORY_CONF_FOLDER) + .join(file); + if !conf.exists() { + return Ok(None); + } + let file = OpenOptions::new() + .read(true) + .open(&conf) + .await? + .into_std() + .await; + + Ok(serde_json::from_reader(file)?) + } + + async fn save_file( + &self, + repository: &RepositoryConfig, + data: &[u8], + location: &str, + ) -> Result { + let file_location = self.get_repository_folder(&repository.name).join(location); + trace!("Saving File {:?}", &file_location); + create_dir_all(file_location.parent().ok_or(StorageError::ParentIssue)?).await?; + + let exists = if file_location.exists() { + remove_file(&file_location).await?; + true + } else { + false + }; + let mut file = OpenOptions::new() + .create_new(true) + .open(&file_location) + .await?; + file.write_all(data).await?; + + Ok(exists) + } + + async fn delete_file( + &self, + repository: &RepositoryConfig, + location: &str, + ) -> Result<(), StorageError> { + let file_location = self.get_repository_folder(&repository.name).join(location); + remove_file(file_location) + .await + .map_err(StorageError::IOError) + } + + async fn get_file_as_response( + &self, + repository: &RepositoryConfig, + location: &str, + ) -> Result { + let file_location = self.get_repository_folder(&repository.name).join(location); + if !file_location.exists() { + return Ok(StorageFileResponse::NotFound); + } + if file_location.is_dir() { + let mut path = format!("{}/{}", self.storage_config.name, repository.name); + + for x in location.split('/') { + if !x.is_empty() { + path = format!("{}/{}", path, x); + } + } + trace!("Directory Listing at {:?}", &path); + let directory = StorageFile::create(&path, &file_location).await?; + //Using STD because Into Iterator is missing + let dir = std::fs::read_dir(&file_location)?; + let mut files = Vec::new(); + for x in dir { + let entry = x?; + + let name = entry.file_name().into_string(); + if name.is_err() { + continue; + } + let name = name.unwrap(); + if name.ends_with(".nitro_repo") || name.starts_with(".nitro_repo") { + //Hide All .nitro_repo files from File Listings + continue; + } + let relative_path = format!("{}/{}", path, &name); + let result = StorageFile::create_from_entry(relative_path, &entry).await?; + files.push(result); + } + let response = StorageDirectoryResponse { files, directory }; + return Ok(StorageFileResponse::List(response)); + } + trace!("Returning File {:?}", &file_location); + Ok(StorageFileResponse::File(file_location)) + } + + async fn get_file_information( + &self, + repository: &RepositoryConfig, + location: &str, + ) -> Result, StorageError> { + let file_location = self.get_repository_folder(&repository.name).join(&location); + if !file_location.exists() { + return Ok(None); + } + + return Ok(Some(StorageFile::create(location, &file_location).await?)); + } + + async fn get_file( + &self, + repository: &RepositoryConfig, + location: &str, + ) -> Result>, StorageError> { + let file_location = self.get_repository_folder(&repository.name).join(location); + debug!("Storage File Request {}", file_location.to_str().unwrap()); + if !file_location.exists() { + return Ok(None); + } + let mut file = OpenOptions::new().read(true).open(file_location).await?; + let mut bytes = Vec::new(); + file.read_to_end(&mut bytes).await?; + Ok(Some(bytes)) + } +} diff --git a/backend/src/storage/mod.rs b/backend/src/storage/mod.rs index 04da66a0..adec4fc2 100644 --- a/backend/src/storage/mod.rs +++ b/backend/src/storage/mod.rs @@ -1,79 +1,229 @@ -use crate::error::internal_error::InternalError; -use crate::repository::models::{Repository, RepositorySummary}; -use crate::storage::models::Storage; -use crate::{SiteResponse, StringMap}; -use actix_web::HttpRequest; -use either::Either; -use serde::{Deserialize, Serialize}; -use std::collections::HashMap; - -pub mod admin; +use crate::repository::data::{RepositoryConfig, RepositoryType}; +use crate::storage::bad_storage::BadStorage; +use crate::storage::error::StorageError; +use crate::storage::file::{StorageFile, StorageFileResponse}; +use crate::storage::local_storage::LocalStorage; +use crate::storage::models::{ + Storage, StorageConfig, StorageFactory, StorageSaver, StorageStatus, StorageType, +}; +use async_trait::async_trait; +use serde_json::Value; +use tokio::sync::RwLockReadGuard; + +pub mod bad_storage; +pub mod error; +pub mod file; pub mod local_storage; pub mod models; +pub mod multi; pub static STORAGES_CONFIG: &str = "storages.nitro_repo"; pub static STORAGE_CONFIG: &str = "storage.nitro_repo"; -pub type RepositoriesFile = HashMap; -pub type FileResponse = Either>; - -///Storage Files are just a data container holding the file name, directory relative to the root of nitro_repo and if its a directory -/// -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct StorageFile { - pub name: String, - pub full_path: String, - pub directory: bool, - pub file_size: u64, - pub created: u128, +#[derive(Debug)] +pub enum DynamicStorage { + LocalStorage(LocalStorage), + BadStorage(BadStorage), } -/// StorageFileResponse is a trait that can be turned into a SiteResponse for example if its LocalFile it will return into Actix's NamedFile response -pub trait StorageFileResponse { - fn to_request(self, request: &HttpRequest) -> SiteResponse; -} +#[async_trait] +impl Storage for DynamicStorage { + fn new(_config: StorageFactory) -> Result + where + Self: Sized, + { + panic!("Illegal Call") + } + + async fn load(&mut self) -> Result<(), StorageError> { + match self { + DynamicStorage::LocalStorage(local) => local.load().await, + DynamicStorage::BadStorage(bad) => bad.load().await, + } + } + + fn unload(&mut self) -> Result<(), StorageError> { + match self { + DynamicStorage::LocalStorage(local) => local.unload(), + DynamicStorage::BadStorage(bad) => bad.unload(), + } + } + + fn config_for_saving(&self) -> StorageSaver { + match self { + DynamicStorage::LocalStorage(local) => local.config_for_saving(), + DynamicStorage::BadStorage(bad) => bad.config_for_saving(), + } + } + + fn storage_config(&self) -> &StorageConfig { + match self { + DynamicStorage::LocalStorage(local) => local.storage_config(), + DynamicStorage::BadStorage(bad) => bad.storage_config(), + } + } -pub trait LocationHandler { - fn init(storage: &Storage) -> Result<(), InternalError>; - // Repository Handlers - fn create_repository( - storage: &Storage, - repository: RepositorySummary, - ) -> Result; - fn delete_repository( - storage: &Storage, - repository: &Repository, + fn impl_config(&self) -> Value { + match self { + DynamicStorage::LocalStorage(local) => local.impl_config(), + DynamicStorage::BadStorage(bad) => bad.impl_config(), + } + } + + fn storage_type(&self) -> &StorageType { + match self { + DynamicStorage::LocalStorage(local) => local.storage_type(), + DynamicStorage::BadStorage(bad) => bad.storage_type(), + } + } + + fn status(&self) -> &StorageStatus { + match self { + DynamicStorage::LocalStorage(local) => local.status(), + DynamicStorage::BadStorage(bad) => bad.status(), + } + } + + async fn create_repository( + &self, + name: String, + repository_type: RepositoryType, + ) -> Result<(), StorageError> { + match self { + DynamicStorage::LocalStorage(local) => { + local.create_repository(name, repository_type).await + } + DynamicStorage::BadStorage(bad) => bad.create_repository(name, repository_type).await, + } + } + + async fn delete_repository( + &self, + repository: &RepositoryConfig, delete_files: bool, - ) -> Result<(), InternalError>; - fn get_repositories(storage: &Storage) -> Result; - fn get_repository( - storage: &Storage, - uuid: &str, - ) -> Result, InternalError>; - fn update_repository( - storage: &Storage, - repository: &Repository, - ) -> Result<(), InternalError>; - //File Handlers - fn save_file( - storage: &Storage, - repository: &Repository, + ) -> Result<(), StorageError> { + match self { + DynamicStorage::LocalStorage(local) => { + local.delete_repository(repository, delete_files).await + } + DynamicStorage::BadStorage(bad) => { + bad.delete_repository(repository, delete_files).await + } + } + } + + async fn get_repositories(&self) -> Result, StorageError> { + match self { + DynamicStorage::LocalStorage(local) => local.get_repositories().await, + DynamicStorage::BadStorage(bad) => bad.get_repositories().await, + } + } + + async fn get_repository( + &self, + repository: &str, + ) -> Result>, StorageError> { + match self { + DynamicStorage::LocalStorage(local) => local.get_repository(repository).await, + DynamicStorage::BadStorage(bad) => bad.get_repository(repository).await, + } + } + + async fn update_repository(&self, repository: RepositoryConfig) -> Result<(), StorageError> { + match self { + DynamicStorage::LocalStorage(local) => local.update_repository(repository).await, + DynamicStorage::BadStorage(bad) => bad.update_repository(repository).await, + } + } + + async fn update_repository_config( + &self, + repository: &RepositoryConfig, + file: &str, + data: &Option, + ) -> Result<(), StorageError> { + match self { + DynamicStorage::LocalStorage(local) => { + local.update_repository_config(repository, file, data).await + } + DynamicStorage::BadStorage(bad) => { + bad.update_repository_config(repository, file, data).await + } + } + } + + async fn get_repository_config( + &self, + repository: &RepositoryConfig, + file: &str, + ) -> Result, StorageError> { + match self { + DynamicStorage::LocalStorage(local) => { + local.get_repository_config(repository, file).await + } + DynamicStorage::BadStorage(bad) => bad.get_repository_config(repository, file).await, + } + } + + async fn save_file( + &self, + repository: &RepositoryConfig, file: &[u8], location: &str, - ) -> Result<(), InternalError>; - fn delete_file( - storage: &Storage, - repository: &Repository, + ) -> Result { + match self { + DynamicStorage::LocalStorage(local) => { + local.save_file(repository, file, location).await + } + DynamicStorage::BadStorage(bad) => bad.save_file(repository, file, location).await, + } + } + + async fn delete_file( + &self, + repository: &RepositoryConfig, location: &str, - ) -> Result<(), InternalError>; - fn get_file_as_response( - storage: &Storage, - repository: &Repository, + ) -> Result<(), StorageError> { + match self { + DynamicStorage::LocalStorage(local) => local.delete_file(repository, location).await, + DynamicStorage::BadStorage(bad) => bad.delete_file(repository, location).await, + } + } + + async fn get_file_as_response( + &self, + repository: &RepositoryConfig, location: &str, - ) -> Result, InternalError>; - fn get_file( - storage: &Storage, - repository: &Repository, + ) -> Result { + match self { + DynamicStorage::LocalStorage(local) => { + local.get_file_as_response(repository, location).await + } + DynamicStorage::BadStorage(bad) => bad.get_file_as_response(repository, location).await, + } + } + + async fn get_file_information( + &self, + repository: &RepositoryConfig, + location: &str, + ) -> Result, StorageError> { + match self { + DynamicStorage::LocalStorage(local) => { + local.get_file_information(repository, location).await + } + DynamicStorage::BadStorage(bad) => bad.get_file_information(repository, location).await, + } + } + + async fn get_file( + &self, + repository: &RepositoryConfig, location: &str, - ) -> Result>, InternalError>; + ) -> Result>, StorageError> { + match self { + DynamicStorage::LocalStorage(local) => local.get_file(repository, location).await, + DynamicStorage::BadStorage(bad) => bad.get_file(repository, location).await, + } + } } diff --git a/backend/src/storage/models.rs b/backend/src/storage/models.rs index 585d1a1c..cb25119e 100644 --- a/backend/src/storage/models.rs +++ b/backend/src/storage/models.rs @@ -1,151 +1,202 @@ -use actix_web::HttpRequest; -use either::{Either, Left, Right}; -use std::collections::HashMap; -use std::fmt::Debug; -use std::fs; -use std::fs::{read_to_string, OpenOptions}; -use std::io::Write; -use std::path::Path; - -use crate::error::internal_error::InternalError; -use crate::repository::models::{Repository, RepositorySummary}; -use crate::storage::local_storage::LocalStorage; -use crate::storage::{LocationHandler, RepositoriesFile, StorageFile, StorageFileResponse}; -use crate::{SiteResponse, StringMap}; +use std::fmt::{Debug, Display, Formatter}; + use serde::{Deserialize, Serialize}; +use async_trait::async_trait; + +use serde_json::Value; +use tokio::sync::RwLockReadGuard; + +use crate::repository::data::{RepositoryConfig, RepositoryType}; +use crate::storage::error::StorageError; +use crate::storage::file::{StorageFile, StorageFileResponse}; +use crate::storage::local_storage::LocalStorage; +use crate::storage::DynamicStorage; + pub static STORAGE_FILE: &str = "storages.json"; pub static STORAGE_FILE_BAK: &str = "storages.json.bak"; -pub fn load_storages() -> anyhow::Result { - let path = Path::new(STORAGE_FILE); - if !path.exists() { - return Ok(HashMap::new()); - } - let string = read_to_string(&path)?; - let result: Storages = serde_json::from_str(&string)?; - Ok(result) +/// Types of Storages +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum StorageType { + LocalStorage, +} + +/// Storage Status +#[derive(Debug)] +pub enum StorageStatus { + /// The storage is unloaded. + Unloaded, + /// Storage has successfully loaded + Loaded, + /// Storage Errored out during loading + Error(StorageError), + /// Storage Errored out during creation. Usually meaning bad config + CreateError(StorageError), } -pub fn save_storages(storages: &Storages) -> Result<(), InternalError> { - let result = serde_json::to_string(&storages)?; - let path = Path::new(STORAGE_FILE); - let bak = Path::new(STORAGE_FILE_BAK); - if bak.exists() { - fs::remove_file(bak)?; +impl PartialEq for StorageStatus { + fn eq(&self, other: &Self) -> bool { + self.to_string() == other.to_string() } - if path.exists() { - fs::rename(path, bak)?; +} + +impl Display for StorageStatus { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + StorageStatus::Unloaded => { + write!(f, "Unloaded") + } + StorageStatus::Loaded => { + write!(f, "Loaded") + } + StorageStatus::Error(error) => { + write!(f, "{}", error) + } + StorageStatus::CreateError(error) => { + write!(f, "{}", error) + } + } } - let mut file = OpenOptions::new().write(true).create(true).open(path)?; - file.write_all(result.as_bytes())?; - Ok(()) } #[derive(Debug, Clone, Serialize, Deserialize)] -pub enum LocationType { - LocalStorage, +pub struct StorageSaver { + pub storage_type: StorageType, + #[serde(flatten)] + pub generic_config: StorageConfig, + /// Storage Handler Config + pub handler_config: Value, } -pub type Storages = HashMap>; - #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Storage { +pub struct StorageConfig { pub public_name: String, pub name: String, + #[serde(default="crate::utils::get_current_time")] pub created: i64, - pub location_type: LocationType, - #[serde(flatten)] - pub location: T, } -pub type StringStorage = Storage; +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct StorageFactory { + pub storage_type: StorageType, + #[serde(flatten)] + pub generic_config: StorageConfig, + /// Storage Handler Config + pub handler_config: Value, +} -impl Storage { - pub fn create_repository( - &self, - repository: RepositorySummary, - ) -> Result { - match self.location_type { - LocationType::LocalStorage => LocalStorage::create_repository(self, repository), +impl StorageFactory { + pub fn config_for_saving(&self) -> StorageSaver { + StorageSaver { + storage_type: self.storage_type.clone(), + generic_config: self.generic_config.clone(), + handler_config: self.handler_config.clone(), } } +} - pub fn delete_repository( - &self, - repository: &Repository, - delete_files: bool, - ) -> Result<(), InternalError> { - match self.location_type { - LocationType::LocalStorage => { - LocalStorage::delete_repository(self, repository, delete_files) +impl StorageFactory { + pub async fn build(self) -> Result { + match &self.storage_type { + StorageType::LocalStorage => { + LocalStorage::new(self).map(|v| DynamicStorage::LocalStorage(v)) } } } - pub fn get_repositories(&self) -> Result { - match self.location_type { - LocationType::LocalStorage => LocalStorage::get_repositories(self), - } - } +} - pub fn get_repository(&self, name: &str) -> Result, InternalError> { - match self.location_type { - LocationType::LocalStorage => LocalStorage::get_repository(self, name), - } - } +#[async_trait] +pub trait Storage: Send + Sync { + /// Initialize the Storage at Storage start. + fn new(config: StorageFactory) -> Result + where + Self: Sized; + // Attempts to Load the Storage + async fn load(&mut self) -> Result<(), StorageError>; + /// Unload the storage + fn unload(&mut self) -> Result<(), StorageError>; + /// Returns a StorageSaver + /// I would like this to be a data reference in the future + fn config_for_saving(&self) -> StorageSaver; + + fn storage_config(&self) -> &StorageConfig; + /// Returns a Owned copy of the Implementation of Type Config. As a serde_json::Value + fn impl_config(&self) -> Value; + /// Returns the Storage Type + fn storage_type(&self) -> &StorageType; + /// The current status of the Storage + fn status(&self) -> &StorageStatus; + /// Creates a new Repository + /// Requires just the name and RepositoryType + async fn create_repository( + &self, + name: String, + repository_type: RepositoryType, + ) -> Result<(), StorageError>; + /// Deletes a Repository + /// delete_files rather or not to clean out the Repository Data + async fn delete_repository( + &self, + repository: &RepositoryConfig, + delete_files: bool, + ) -> Result<(), StorageError>; + /// Gets a Owned Vec of Repositories + async fn get_repositories(&self) -> Result, StorageError>; + /// Returns a RwLockReadGuard of the RepositoryConfig + async fn get_repository( + &self, + repository: &str, + ) -> Result>, StorageError>; - pub fn update_repository(&self, repository: &Repository) -> Result<(), InternalError> { - match self.location_type { - LocationType::LocalStorage => LocalStorage::update_repository(self, repository), - } - } + async fn update_repository(&self, repository: RepositoryConfig) -> Result<(), StorageError>; + /// Locks the Repositories for updating + /// Keeps all config files in .config + async fn update_repository_config( + &self, + repository: &RepositoryConfig, + file: &str, + data: &Option, + ) -> Result<(), StorageError>; + /// Gets a Repository Config + async fn get_repository_config( + &self, + repository: &RepositoryConfig, + file: &str, + ) -> Result, StorageError>; - pub fn save_file( + /// Saves a File to a location + /// Will overwrite any data found + async fn save_file( &self, - repository: &Repository, + repository: &RepositoryConfig, file: &[u8], location: &str, - ) -> Result<(), InternalError> { - match self.location_type { - LocationType::LocalStorage => LocalStorage::save_file(self, repository, file, location), - } - } - - pub fn delete_file( + ) -> Result; + /// Deletes a file at a given location + async fn delete_file( &self, - repository: &Repository, + repository: &RepositoryConfig, location: &str, - ) -> Result<(), InternalError> { - match self.location_type { - LocationType::LocalStorage => LocalStorage::delete_file(self, repository, location), - } - } - - pub fn get_file_as_response( + ) -> Result<(), StorageError>; + /// Gets tje File as a StorageFileResponse + /// Can be converted for Web Responses + async fn get_file_as_response( &self, - repository: &Repository, + repository: &RepositoryConfig, location: &str, - request: &HttpRequest, - ) -> Result>, InternalError> { - match self.location_type { - LocationType::LocalStorage => { - let response = LocalStorage::get_file_as_response(self, repository, location)?; - if response.is_left() { - Ok(Left(response.left().unwrap().to_request(request))) - } else { - Ok(Right(response.right().unwrap())) - } - } - } - } - - pub fn get_file( + ) -> Result; + /// Returns Information about the file + async fn get_file_information( &self, - repository: &Repository, + repository: &RepositoryConfig, location: &str, - ) -> Result>, InternalError> { - match self.location_type { - LocationType::LocalStorage => LocalStorage::get_file(self, repository, location), - } - } + ) -> Result, StorageError>; + /// Gets the File as an Array of Bytes + /// Used for internal processing + async fn get_file( + &self, + repository: &RepositoryConfig, + location: &str, + ) -> Result>, StorageError>; } diff --git a/backend/src/storage/multi/mod.rs b/backend/src/storage/multi/mod.rs new file mode 100644 index 00000000..d61256a7 --- /dev/null +++ b/backend/src/storage/multi/mod.rs @@ -0,0 +1,176 @@ +pub mod web; + +use log::{error, info}; +use std::collections::HashMap; +use std::path::{Path, PathBuf}; + +use tokio::fs; +use tokio::fs::{read_to_string, OpenOptions}; + +use crate::storage::models::{ + Storage, StorageFactory, StorageSaver, StorageStatus, STORAGE_FILE, STORAGE_FILE_BAK, +}; + +use crate::storage::bad_storage::BadStorage; +use crate::storage::error::StorageError; +use crate::storage::file::StorageFile; +use crate::storage::DynamicStorage; +use tokio::io::AsyncWriteExt; +use tokio::sync::{RwLock, RwLockReadGuard}; + +async fn load_storages(storages_file: PathBuf) -> Result, StorageError> { + if !storages_file.exists() { + return Ok(HashMap::new()); + } + let string = read_to_string(&storages_file).await?; + let result: Vec = serde_json::from_str(&string)?; + let mut values: HashMap = HashMap::new(); + for factory in result { + let name = factory.generic_config.name.clone(); + let storage = match factory.build().await { + Ok(value) => value, + Err((error, factory)) => DynamicStorage::BadStorage(BadStorage::create(factory, error)), + }; + values.insert(name, storage); + } + Ok(values) +} + +pub async fn save_storages(storages: &Vec) -> Result<(), StorageError> { + let result = serde_json::to_string(&storages)?; + let path = Path::new(STORAGE_FILE); + let bak = Path::new(STORAGE_FILE_BAK); + if bak.exists() { + fs::remove_file(bak).await?; + } + if path.exists() { + fs::rename(path, bak).await?; + } + let mut file = OpenOptions::new() + .write(true) + .create(true) + .open(path) + .await?; + file.write_all(result.as_bytes()).await?; + Ok(()) +} + +pub struct MultiStorageController { + pub storages: RwLock>, +} + +impl MultiStorageController { + pub async fn init(storages_file: PathBuf) -> Result { + info!("Loading Storages"); + let result = load_storages(storages_file).await?; + Ok(MultiStorageController { + storages: RwLock::new(result), + }) + } +} + +impl MultiStorageController { + pub async fn get_storage_by_name( + &self, + name: &str, + ) -> Result>, StorageError> { + let storages = self.storages.read().await; + if storages.contains_key(name) { + return Ok(None); + } + let storage = RwLockReadGuard::map(storages, |storages| { + let storage = storages.get(name).unwrap(); + storage + }); + Ok(Some(storage)) + } + pub async fn does_storage_exist(&self, name: &str) -> Result { + let storages = self.storages.read().await; + Ok(storages.contains_key(name)) + } + + pub async fn create_storage<'a>(&self, storage: StorageFactory) -> Result<(), StorageError> { + let mut storages = self.storages.write().await; + let name = storage.generic_config.name.clone(); + + if storages.contains_key(&name) { + return Err(StorageError::StorageAlreadyExist); + } + { + let mut storages_saving = Vec::new(); + for (_, storage) in storages.iter() { + storages_saving.push(storage.config_for_saving()); + } + storages_saving.push(storage.config_for_saving()); + save_storages(&storages_saving).await?; + } + let storage_name = name.clone(); + + let storage_handler = storage.build().await.unwrap(); + storages.insert(storage_name.clone(), storage_handler); + Ok(()) + } + /// Attempts to run the storage load on any storages that are unloaded. + /// This will include the Error storages + pub async fn load_unloaded_storages<'a>(&self) -> Result<(), StorageError> { + let mut guard = self.storages.write().await; + for (name, storage) in guard.iter_mut() { + match storage.status() { + StorageStatus::Unloaded => { + info!("Loading Storage {}", name); + storage.load().await?; + } + StorageStatus::Error(_) => { + info!("Loading Storage {}", name); + storage.load().await?; + } + _ => {} + } + } + Ok(()) + } + + pub async fn delete_storage(&self, storage: &str) -> Result { + let mut storages = self.storages.write().await; + let option = storages.remove(storage); + if option.is_none() { + return Ok(false); + } + let mut storage = option.unwrap(); + drop(storages); + // Save the new storages + save_storages(self.storage_savers().await.as_ref()).await?; + if let Err(error) = storage.unload() { + error!( + "Storage has been removed config. However, it failed to unload properly {}", + error + ); + } + Ok(true) + } + pub async fn storage_savers(&self) -> Vec { + let storages = self.storages.read().await; + + let mut storages_saving = Vec::new(); + for (_, storage) in storages.iter() { + storages_saving.push(storage.config_for_saving().clone()); + } + storages_saving + } + pub async fn storages_as_file_list(&self) -> Result, StorageError> { + let storages = self.storages.read().await; + let mut files = Vec::new(); + for (name, storage) in storages.iter() { + files.push(StorageFile { + name: name.clone(), + full_path: name.clone(), + mime: "text/directory".to_string(), + directory: true, + file_size: 0, + modified: 0, + created: storage.config_for_saving().generic_config.created as u128, + }); + } + Ok(files) + } +} diff --git a/backend/src/storage/multi/web/admin.rs b/backend/src/storage/multi/web/admin.rs new file mode 100644 index 00000000..805d0c3e --- /dev/null +++ b/backend/src/storage/multi/web/admin.rs @@ -0,0 +1,37 @@ +use actix_web::{get, HttpResponse, post, ResponseError, web}; +use actix_web::http::StatusCode; +use sea_orm::DatabaseConnection; +use serde_json::json; +use crate::authentication::Authentication; +use crate::error::api_error::APIError; +use crate::error::internal_error::InternalError; +use crate::storage::error::StorageError; +use crate::storage::models::StorageFactory; +use crate::storage::multi::{MultiStorageController}; +use crate::system::user::UserModel; +use crate::system::permissions::options::CanIDo; + +/// API handler for getting storages +#[get("/storages")] +pub async fn get_storages(storage_handler: web::Data, database: web::Data, auth: Authentication) -> actix_web::Result { + let user: UserModel = auth.get_user(&database).await??; + user.can_i_edit_repos()?; + + Ok(HttpResponse::Ok().json(storage_handler.storage_savers().await)) +} + +#[post("/storage/new")] +pub async fn new_storage(storage_handler: web::Data, new_storage: web::Json, database: web::Data, auth: Authentication) -> actix_web::Result { + let user: UserModel = auth.get_user(&database).await??; + user.can_i_edit_repos()?; + if let Err(error) = storage_handler.create_storage(new_storage.0).await { + match error { + StorageError::StorageAlreadyExist => { + Ok(APIError::from(("Storage already exist", StatusCode::CONFLICT)).error_response()) + } + _ => { Err(InternalError::from(error).into()) } + } + } else { + Ok(HttpResponse::Ok().finish()) + } +} diff --git a/backend/src/storage/multi/web/mod.rs b/backend/src/storage/multi/web/mod.rs new file mode 100644 index 00000000..8c74d271 --- /dev/null +++ b/backend/src/storage/multi/web/mod.rs @@ -0,0 +1,7 @@ +use actix_web::web::ServiceConfig; + +pub mod admin; + +pub fn init_admin_routes(cfg: &mut ServiceConfig) { + cfg.service(admin::get_storages).service(admin::new_storage); +} \ No newline at end of file diff --git a/backend/src/system/action.rs b/backend/src/system/action.rs deleted file mode 100644 index 66bd029d..00000000 --- a/backend/src/system/action.rs +++ /dev/null @@ -1,181 +0,0 @@ -use diesel::prelude::*; -use diesel::MysqlConnection; - -use crate::system::models::{ - AuthToken, SessionToken, User, UserListResponse, UserResponse, -}; -use crate::{system, utils}; -use crate::system::permissions::UserPermissions; - -pub fn get_users(conn: &MysqlConnection) -> Result, diesel::result::Error> { - use crate::schema::users::dsl::*; - users.select((id, name)).load::(conn) -} - -pub fn update_user( - user: i64, - e: &str, - n: &str, - conn: &MysqlConnection, -) -> Result<(), diesel::result::Error> { - use crate::schema::users::dsl::*; - let _result1 = diesel::update(users.filter(id.eq(user))) - .set((email.eq(e), name.eq(n))) - .execute(conn); - Ok(()) -} -pub fn update_user_permissions( - user: &i64, - perms: &UserPermissions, - conn: &MysqlConnection, -) -> Result<(), diesel::result::Error> { - use crate::schema::users::dsl::*; - let _result1 = diesel::update(users.filter(id.eq(user))) - .set((permissions.eq(perms),)) - .execute(conn); - Ok(()) -} - -pub fn update_user_password( - user: &i64, - p: String, - conn: &MysqlConnection, -) -> Result<(), diesel::result::Error> { - use crate::schema::users::dsl::*; - let _result1 = diesel::update(users.filter(id.eq(user))) - .set((password.eq(p),)) - .execute(conn); - Ok(()) -} - -pub fn get_user_by_id( - d: &i64, - conn: &MysqlConnection, -) -> Result, diesel::result::Error> { - use crate::schema::users::dsl::*; - - let found_mod = users - .filter(id.eq(d)) - .first::(conn) - .optional()?; - - Ok(found_mod) -} - -pub fn get_user_by_id_response( - d: &i64, - conn: &MysqlConnection, -) -> Result, diesel::result::Error> { - use crate::schema::users::dsl::*; - - users - .filter(id.eq(d)) - .select((id, name, username, email, permissions, created)) - .first::(conn) - .optional() -} - -pub fn get_user_by_email( - d: &str, - conn: &MysqlConnection, -) -> Result, diesel::result::Error> { - use crate::schema::users::dsl::*; - - let found_mod = users - .filter(email.like(d)) - .first::(conn) - .optional()?; - - Ok(found_mod) -} - -pub fn delete_user_db(d: &i64, conn: &MysqlConnection) -> Result { - use crate::schema::users::dsl::*; - let x = diesel::delete(users).filter(id.eq(d)).execute(conn)?; - Ok(x >= 1) -} - -pub fn get_user_by_username( - d: &str, - conn: &MysqlConnection, -) -> Result, diesel::result::Error> { - use crate::schema::users::dsl::*; - - let found_mod = users - .filter(username.like(d)) - .first::(conn) - .optional()?; - - Ok(found_mod) -} - -pub fn add_new_user(s: &User, conn: &MysqlConnection) -> Result<(), diesel::result::Error> { - use crate::schema::users::dsl::*; - diesel::insert_into(users).values(s).execute(conn).unwrap(); - Ok(()) -} - -//Session Token -pub fn get_session_token( - a_token: &str, - conn: &MysqlConnection, -) -> Result, diesel::result::Error> { - use crate::schema::session_tokens::dsl::*; - let found_token = session_tokens - .filter(token.eq(a_token)) - .first::(conn) - .optional()?; - Ok(found_token) -} - -pub fn add_new_session_token( - t: &SessionToken, - conn: &MysqlConnection, -) -> Result<(), diesel::result::Error> { - use crate::schema::session_tokens::dsl::*; - diesel::insert_into(session_tokens) - .values(t) - .execute(conn) - .unwrap(); - Ok(()) -} - -pub fn get_user_from_session_token( - token: &str, - conn: &MysqlConnection, -) -> Result, diesel::result::Error> { - let result = get_session_token(token, conn)?; - if result.is_none() { - return Ok(None); - } - let result = result.unwrap(); - if result.expiration <= utils::get_current_time() { - return Ok(None); - } - get_user_by_id(&result.user, conn) -} - -//Session Token - -pub fn add_new_auth_token( - t: &AuthToken, - conn: &MysqlConnection, -) -> Result<(), diesel::result::Error> { - use crate::schema::auth_tokens::dsl::*; - diesel::insert_into(auth_tokens) - .values(t) - .execute(conn) - .unwrap(); - Ok(()) -} - -pub fn get_tokens( - user_id: &i64, - conn: &MysqlConnection, -) -> Result, diesel::result::Error> { - use crate::schema::session_tokens::dsl::*; - let found_token = session_tokens - .filter(user.eq(user_id)) - .load::(conn)?; - Ok(found_token) -} diff --git a/backend/src/system/controllers/me.rs b/backend/src/system/controllers/me.rs deleted file mode 100644 index 21a1a005..00000000 --- a/backend/src/system/controllers/me.rs +++ /dev/null @@ -1,37 +0,0 @@ -use actix_web::{get, post, web, HttpRequest}; - -use crate::api_response::{APIResponse, SiteResponse}; -use crate::database::DbPool; -use crate::error::response::unauthorized; -use crate::system::action::update_user_password; -use crate::system::utils::{get_user_by_header, hash, NewPassword}; - -#[get("/api/me")] -pub async fn me(pool: web::Data, r: HttpRequest) -> SiteResponse { - let connection = pool.get()?; - - let user = get_user_by_header(r.headers(), &connection)?; - if user.is_none() { - return unauthorized(); - } - - APIResponse::respond_new(user, &r) -} - -#[post("/api/me/user/password")] -pub async fn change_my_password( - pool: web::Data, - r: HttpRequest, - nc: web::Json, -) -> SiteResponse { - let connection = pool.get()?; - - let user = get_user_by_header(r.headers(), &connection)?; - if user.is_none() { - return unauthorized(); - } - let user = user.unwrap(); - let string = hash(nc.0.password)?; - update_user_password(&user.id, string, &connection)?; - APIResponse::from(Some(user)).respond(&r) -} diff --git a/backend/src/system/controllers/mod.rs b/backend/src/system/controllers/mod.rs deleted file mode 100644 index f1a3dd1b..00000000 --- a/backend/src/system/controllers/mod.rs +++ /dev/null @@ -1,18 +0,0 @@ -use actix_web::web; - -pub mod me; -pub mod public; -pub mod user; - -pub fn init(cfg: &mut web::ServiceConfig) { - cfg.service(public::login) - .service(user::add_user) - .service(user::list_users) - .service(user::get_user) - .service(user::delete_user) - .service(user::modify_user) - .service(user::update_permission) - .service(user::change_password) - .service(me::change_my_password) - .service(me::me); -} diff --git a/backend/src/system/controllers/public.rs b/backend/src/system/controllers/public.rs deleted file mode 100644 index a00efdf9..00000000 --- a/backend/src/system/controllers/public.rs +++ /dev/null @@ -1,50 +0,0 @@ -use actix_web::{post, web, HttpRequest}; - -use crate::api_response::{APIResponse, SiteResponse}; - -use crate::database::DbPool; -use crate::error::response::unauthorized; -use crate::system::action::{add_new_session_token, get_user_by_email, get_user_by_username}; -use crate::system::models::SessionToken; -use crate::system::utils::generate_session_token; -use crate::utils::{default_expiration, get_current_time}; -use argon2::{Argon2, PasswordHash, PasswordVerifier}; -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct Login { - pub username: String, - pub password: String, -} - -#[post("/api/login")] -pub async fn login(pool: web::Data, r: HttpRequest, nc: web::Json) -> SiteResponse { - let connection = pool.get()?; - - let username = nc.username.clone(); - let user = if username.contains('@') { - get_user_by_email(&username, &connection)? - } else { - get_user_by_username(&username, &connection)? - }; - if user.is_none() { - return unauthorized(); - } - let user = user.unwrap(); - let argon2 = Argon2::default(); - let parsed_hash = PasswordHash::new(user.password.as_str())?; - let x = argon2.verify_password(nc.password.clone().as_bytes(), &parsed_hash); - if x.is_err() { - return unauthorized(); - } - let token = SessionToken { - id: 0, - user: user.id, - token: generate_session_token(&connection)?, - expiration: default_expiration(), - created: get_current_time(), - }; - add_new_session_token(&token, &connection)?; - - APIResponse::respond_new(Some(token), &r) -} diff --git a/backend/src/system/controllers/user.rs b/backend/src/system/controllers/user.rs deleted file mode 100644 index bcad13ca..00000000 --- a/backend/src/system/controllers/user.rs +++ /dev/null @@ -1,172 +0,0 @@ -use actix_web::{get, patch, post, web, HttpRequest}; -use serde::{Deserialize, Serialize}; - -use crate::api_response::{APIResponse, SiteResponse}; -use crate::database::DbPool; -use crate::error::response::{already_exists_what, not_found, unauthorized}; -use crate::system::action::{ - add_new_user, delete_user_db, get_user_by_email, get_user_by_id_response, get_user_by_username, - get_users, update_user, update_user_password, update_user_permissions, -}; -use crate::system::models::{User, UserListResponse}; -use crate::system::permissions::options::CanIDo; -use crate::system::permissions::UserPermissions; -use crate::system::utils::{get_user_by_header, hash, ModifyUser, NewPassword, NewUser}; -use crate::utils::get_current_time; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ListUsers { - pub users: Vec, -} - -#[get("/api/admin/user/list")] -pub async fn list_users(pool: web::Data, r: HttpRequest) -> SiteResponse { - let connection = pool.get()?; - - if get_user_by_header(r.headers(), &connection)?.can_i_edit_users().is_err() { - return unauthorized(); - } - let vec = get_users(&connection)?; - - let response = ListUsers { users: vec }; - APIResponse::respond_new(Some(response), &r) -} - -#[get("/api/admin/user/get/{user}")] -pub async fn get_user( - pool: web::Data, - r: HttpRequest, - path: web::Path, -) -> SiteResponse { - let connection = pool.get()?; - - if get_user_by_header(r.headers(), &connection)?.can_i_edit_users().is_err() { - return unauthorized(); - } - let repo = get_user_by_id_response(&path.into_inner(), &connection)?; - - APIResponse::respond_new(repo, &r) -} - -#[post("/api/admin/user/add")] -pub async fn add_user( - pool: web::Data, - r: HttpRequest, - nc: web::Json, -) -> SiteResponse { - let connection = pool.get()?; - if get_user_by_header(r.headers(), &connection)?.can_i_edit_users().is_err() { - return unauthorized(); - } - if get_user_by_username(&nc.username, &connection)?.is_some() { - return already_exists_what("username"); - } - if get_user_by_email(&nc.email, &connection)?.is_some() { - return already_exists_what("email"); - } - let user = User { - id: 0, - name: nc.0.name, - username: nc.0.username, - email: nc.0.email, - password: hash(nc.0.password)?, - permissions: UserPermissions::default(), - created: get_current_time(), - }; - add_new_user(&user, &connection)?; - APIResponse::from(get_user_by_username(&user.username, &connection)?).respond(&r) -} - -#[patch("/api/admin/user/{user}/modify")] -pub async fn modify_user( - pool: web::Data, - r: HttpRequest, - name: web::Path, - nc: web::Json, -) -> SiteResponse { - let connection = pool.get()?; - - if get_user_by_header(r.headers(), &connection)?.can_i_edit_users().is_err() { - return unauthorized(); - } - let name = name.into_inner(); - - let user = get_user_by_username(&name, &connection)?; - if user.is_none() { - return not_found(); - } - update_user(user.unwrap().id, &nc.email, &nc.name, &connection)?; - APIResponse::from(get_user_by_username(&name, &connection)?).respond(&r) -} - -#[patch("/api/admin/user/{user}/modify/permissions")] -pub async fn update_permission( - pool: web::Data, - r: HttpRequest, - permissions: web::Json, - path: web::Path, -) -> SiteResponse { - let connection = pool.get()?; - - if get_user_by_header(r.headers(), &connection)?.can_i_edit_users().is_err() { - return unauthorized(); - } - let user = path.into_inner(); - - let user = get_user_by_username(&user, &connection)?; - if user.is_none() { - return not_found(); - } - let user = user.unwrap(); - update_user_permissions(&user.id, &permissions.into_inner(), &connection)?; - APIResponse::from(true).respond(&r) -} - -#[post("/api/admin/user/{user}/password")] -pub async fn change_password( - pool: web::Data, - r: HttpRequest, - user: web::Path, - nc: web::Json, -) -> SiteResponse { - let connection = pool.get()?; - - if get_user_by_header(r.headers(), &connection)?.can_i_edit_users().is_err() { - return unauthorized(); - } - let connection = pool.get()?; - let user = user.into_inner(); - - let user = get_user_by_username(&user, &connection)?; - if user.is_none() { - return not_found(); - } - let user = user.unwrap(); - let string = hash(nc.0.password)?; - - update_user_password(&user.id, string, &connection)?; - APIResponse::from(Some(user)).respond(&r) -} - -#[get("/api/admin/user/{user}/delete")] -pub async fn delete_user( - pool: web::Data, - r: HttpRequest, - user: web::Path, -) -> SiteResponse { - let connection = pool.get()?; - - if get_user_by_header(r.headers(), &connection)?.can_i_edit_users().is_err() { - return unauthorized(); - } - let connection = pool.get()?; - - let user = user.into_inner(); - - let option = get_user_by_username(&user, &connection)?; - if option.is_none() { - return not_found(); - } - delete_user_db(&option.unwrap().id, &connection)?; - APIResponse::new(true, Some(true)).respond(&r) -} diff --git a/backend/src/system/mod.rs b/backend/src/system/mod.rs index 86bf6b21..c46e09fb 100644 --- a/backend/src/system/mod.rs +++ b/backend/src/system/mod.rs @@ -1,5 +1,5 @@ -pub mod action; -pub mod controllers; pub mod models; -pub mod utils; pub mod permissions; +pub mod user; +pub mod utils; +pub mod web; diff --git a/backend/src/system/models.rs b/backend/src/system/models.rs index b14d7cf7..c49ed8a0 100644 --- a/backend/src/system/models.rs +++ b/backend/src/system/models.rs @@ -1,74 +1,20 @@ use std::fmt::Debug; +use sea_orm::{FromQueryResult, JsonValue}; use serde::{Deserialize, Serialize}; -use crate::schema::*; -use crate::system::permissions::UserPermissions; - -#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Insertable)] -#[table_name = "users"] -pub struct User { - pub id: i64, - pub name: String, - pub username: String, - pub email: String, - #[serde(skip_serializing)] - pub password: String, - pub permissions: UserPermissions, - pub created: i64, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Queryable)] +#[derive(Debug, Clone, Serialize, Deserialize, FromQueryResult)] pub struct UserListResponse { pub id: i64, pub name: String, } -#[derive(Debug, Clone, Serialize, Deserialize, Queryable)] +#[derive(Debug, Clone, Serialize, Deserialize, FromQueryResult)] pub struct UserResponse { pub id: i64, pub name: String, pub username: String, pub email: String, - pub permissions: UserPermissions, - pub created: i64, -} - -impl User { - pub fn set_password(&mut self, password: String) { - self.password = password; - } -} - - - - -#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Insertable)] -pub struct ForgotPassword { - pub id: i64, - pub user: i64, - pub token: String, - pub expiration: i64, - pub created: i64, -} - -// Represents a Session of an active user -#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Insertable)] -pub struct SessionToken { - pub id: i64, - pub user: i64, - pub token: String, - pub expiration: i64, - pub created: i64, -} - -// Unlike a SessionToken this is a token sent with the users username to be used as a password. -// If the user sets up Google Authentication with their account they will need to generate one of these to do deploys -#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Insertable)] -pub struct AuthToken { - pub id: i64, - pub user: i64, - pub token: String, - pub expiration: i64, + pub permissions: JsonValue, pub created: i64, } diff --git a/backend/src/system/permissions/mod.rs b/backend/src/system/permissions/mod.rs index 70405025..3c6d9584 100644 --- a/backend/src/system/permissions/mod.rs +++ b/backend/src/system/permissions/mod.rs @@ -1,19 +1,12 @@ pub mod options; +pub mod orm; -use serde::{Serialize, Deserialize}; -use crate::repository::models::{Repository}; -use thiserror::Error; -use crate::repository::settings::Policy; +use crate::repository::data::RepositoryConfig; use crate::repository::settings::security::Visibility; +use crate::repository::settings::Policy; use crate::system::permissions::PermissionError::{RepositoryClassifier, StorageClassifier}; -use std::io::Write; - -use diesel::backend::Backend; -use diesel::deserialize::FromSql; -use diesel::mysql::Mysql; -use diesel::serialize::{Output, ToSql}; -use diesel::sql_types::Text; -use diesel::{deserialize, serialize}; +use serde::{Deserialize, Serialize}; +use thiserror::Error; #[derive(Error, Debug)] pub enum PermissionError { @@ -34,8 +27,7 @@ impl From for PermissionError { } } -#[derive(AsExpression, Debug, Deserialize, Serialize, FromSqlRow, Clone, Default)] -#[sql_type = "Text"] +#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Default)] pub struct UserPermissions { pub disabled: bool, pub admin: bool, @@ -45,47 +37,29 @@ pub struct UserPermissions { pub viewer: Option, } -impl UserPermissions { - pub fn can_access_repository(&self) -> bool { - self.admin || self.repository_manager - } -} - -impl FromSql for UserPermissions { - fn from_sql( - bytes: Option<&::RawValue>, - ) -> deserialize::Result { - let t = >::from_sql(bytes)?; - let result: UserPermissions = serde_json::from_str(t.as_str())?; - Ok(result) - } -} - -impl ToSql for UserPermissions { - fn to_sql(&self, out: &mut Output) -> serialize::Result { - let s = serde_json::to_string(&self)?; - >::to_sql(&s, out) - } -} - - -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] pub struct RepositoryPermission { pub permissions: Vec, } -#[derive(Serialize, Deserialize, Debug, Default)] +#[derive(Serialize, Deserialize, Debug)] pub struct RepositoryPermissionValue { pub policy: Option, #[serde(rename = "type")] pub repo_type: Option, } - +impl Default for RepositoryPermission { + fn default() -> Self { + RepositoryPermission { + permissions: vec![], + } + } +} pub fn can_deploy( user_perms: &UserPermissions, - repo: &Repository, + repo: &RepositoryConfig, ) -> Result { if user_perms.disabled { return Ok(false); @@ -100,10 +74,9 @@ pub fn can_deploy( Ok(false) } - pub fn can_read( user_perms: &UserPermissions, - repo: &Repository, + repo: &RepositoryConfig, ) -> Result { if user_perms.disabled { return Ok(false); @@ -112,7 +85,7 @@ pub fn can_read( return Ok(true); } - match repo.security.visibility { + match repo.visibility { Visibility::Public => Ok(true), Visibility::Private => { if let Some(perms) = &user_perms.viewer { @@ -126,7 +99,7 @@ pub fn can_read( } } -pub fn can(repo: &Repository, perms: &RepositoryPermission) -> Result { +pub fn can(repo: &RepositoryConfig, perms: &RepositoryPermission) -> Result { if perms.permissions.is_empty() { // If nothing is set. It is a all view type of scenario return Ok(true); @@ -147,12 +120,12 @@ pub fn can(repo: &Repository, perms: &RepositoryPermission) -> Result Result for MissingPermission { - fn from(value: &str) -> Self { - MissingPermission(value.to_string()) +impl Debug for MissingPermission { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "Forbidden: Missing Permission {}", &self.0) } } -impl fmt::Display for MissingPermission { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Missing permission: {}", self.0) +impl Display for MissingPermission { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "Forbidden: Missing Permission {}", &self.0) } } -impl std::error::Error for MissingPermission {} +impl ResponseError for MissingPermission { + fn status_code(&self) -> StatusCode { + StatusCode::FORBIDDEN + } +} +impl From<&str> for MissingPermission { + fn from(value: &str) -> Self { + MissingPermission(format!("Missing Permission `{}`", value)) + } +} pub trait CanIDo { - fn can_i_edit_repos(self) -> Result; - fn can_i_edit_users(self) -> Result; - fn can_i_admin(self) -> Result; + fn can_i_edit_repos(&self) -> Result<(), MissingPermission>; + fn can_i_edit_users(&self) -> Result<(), MissingPermission>; + fn can_i_admin(&self) -> Result<(), MissingPermission>; + fn can_deploy_to( + &self, + repo: &RepositoryConfig, + ) -> Result, InternalError>; + fn can_read_from( + &self, + repo: &RepositoryConfig, + ) -> Result, InternalError>; } -impl CanIDo for Option { - fn can_i_edit_repos(self) -> Result { - if self.is_none() { - return Err("Not Logged In".into()); - } - let user = self.unwrap(); - if !user.permissions.admin && !user.permissions.repository_manager { +impl CanIDo for UserModel { + fn can_i_edit_repos(&self) -> Result<(), MissingPermission> { + let permissions: UserPermissions = self.permissions.clone().try_into().unwrap(); + + if !permissions.admin && !permissions.repository_manager { return Err("repository_manager".into()); } - Ok(user) + Ok(()) } - fn can_i_edit_users(self) -> Result { - if self.is_none() { - return Err("Not Logged In".into()); - } - let user = self.unwrap(); - if !user.permissions.admin && !user.permissions.user_manager { + fn can_i_edit_users(&self) -> Result<(), MissingPermission> { + let permissions: UserPermissions = self.permissions.clone().try_into().unwrap(); + if !permissions.admin && !permissions.user_manager { return Err("user_manager".into()); } - Ok(user) + Ok(()) } - fn can_i_admin(self) -> Result { - if self.is_none() { - return Err("Not Logged In".into()); - } - let user = self.unwrap(); - if !user.permissions.admin { + fn can_i_admin(&self) -> Result<(), MissingPermission> { + let permissions: UserPermissions = self.permissions.clone().try_into().unwrap(); + + if !permissions.admin { return Err("admin".into()); } - Ok(user) + Ok(()) } -} \ No newline at end of file + + fn can_deploy_to( + &self, + repo: &RepositoryConfig, + ) -> Result, InternalError> { + let can_read = can_deploy(&self.permissions, repo)?; + if can_read { + Ok(None) + } else { + Ok(Some(MissingPermission("Write Repository".to_string()))) + } + } + + fn can_read_from( + &self, + repo: &RepositoryConfig, + ) -> Result, InternalError> { + match repo.visibility { + Visibility::Public => Ok(None), + Visibility::Private => { + let can_read = can_read(&self.permissions, repo)?; + if can_read { + Ok(None) + } else { + Ok(Some(MissingPermission("Read Repository".to_string()))) + } + } + Visibility::Hidden => Ok(None), + } + } +} diff --git a/backend/src/system/permissions/orm.rs b/backend/src/system/permissions/orm.rs new file mode 100644 index 00000000..bd4572c5 --- /dev/null +++ b/backend/src/system/permissions/orm.rs @@ -0,0 +1,47 @@ +use crate::system::permissions::UserPermissions; +use sea_orm::{DbErr, JsonValue}; + +impl From for JsonValue { + fn from(auth: UserPermissions) -> Self { + serde_json::to_value(auth).unwrap() + } +} + +impl From for sea_orm::Value { + fn from(source: UserPermissions) -> Self { + sea_orm::Value::Json(Some(Box::new(source.into()))) + } +} + +impl sea_orm::TryGetable for UserPermissions { + fn try_get( + res: &sea_orm::QueryResult, + pre: &str, + col: &str, + ) -> Result { + let val: JsonValue = res.try_get(pre, col).map_err(sea_orm::TryGetError::DbErr)?; + serde_json::from_value(val) + .map_err(|e| sea_orm::TryGetError::DbErr(DbErr::Json(e.to_string()))) + } +} + +impl sea_orm::sea_query::ValueType for UserPermissions { + fn try_from(v: sea_orm::Value) -> Result { + match v { + sea_orm::Value::Json(Some(x)) => { + let auth_properties: UserPermissions = serde_json::from_value(*x) + .map_err(|_error| sea_orm::sea_query::ValueTypeErr)?; + Ok(auth_properties) + } + _ => Err(sea_orm::sea_query::ValueTypeErr), + } + } + + fn type_name() -> String { + stringify!(UserPermissions).to_owned() + } + + fn column_type() -> sea_orm::sea_query::ColumnType { + sea_orm::sea_query::ColumnType::Json + } +} diff --git a/backend/src/system/user/database.rs b/backend/src/system/user/database.rs new file mode 100644 index 00000000..674d95fb --- /dev/null +++ b/backend/src/system/user/database.rs @@ -0,0 +1,38 @@ +use crate::system::permissions::UserPermissions; +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] +#[sea_orm(table_name = "users")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i64, + pub name: String, + pub username: String, + pub email: String, + #[serde(skip_serializing)] + pub password: String, + #[sea_orm(column_type = "Json")] + pub permissions: UserPermissions, + pub created: i64, +} + +#[derive(Serialize, Deserialize, Clone, Debug, DeriveIntoActiveModel)] +pub struct ModifyUser { + pub name: String, + pub email: String, +} + +impl ActiveModelBehavior for ActiveModel {} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "crate::authentication::auth_token::database::Entity")] + AuthToken, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::AuthToken.def() + } +} diff --git a/backend/src/system/user/mod.rs b/backend/src/system/user/mod.rs new file mode 100644 index 00000000..296de198 --- /dev/null +++ b/backend/src/system/user/mod.rs @@ -0,0 +1,15 @@ +pub mod database; + +pub use database::Entity as UserEntity; +pub use database::Model as UserModel; +use sea_orm::{ColumnTrait, DatabaseConnection, DbErr, EntityTrait, QueryFilter}; + +pub async fn get_by_username( + username: &str, + connection: &DatabaseConnection, +) -> Result, DbErr> { + UserEntity::find() + .filter(database::Column::Username.eq(username)) + .one(connection) + .await +} diff --git a/backend/src/system/utils.rs b/backend/src/system/utils.rs index 77b82d3f..3dfab4c3 100644 --- a/backend/src/system/utils.rs +++ b/backend/src/system/utils.rs @@ -1,105 +1,10 @@ -use actix_web::http::header::HeaderMap; use argon2::password_hash::rand_core::OsRng; use argon2::password_hash::SaltString; -use argon2::{Argon2, PasswordHash, PasswordHasher, PasswordVerifier}; -use diesel::MysqlConnection; -use rand::distributions::Alphanumeric; -use rand::Rng; +use argon2::{Argon2, PasswordHasher}; + use serde::{Deserialize, Serialize}; use crate::error::internal_error::InternalError; -use crate::repository::models::{Repository}; -use crate::repository::settings::security::Visibility; -use crate::system; -use crate::system::action::{get_session_token, get_user_by_username}; -use crate::system::models::User; -use crate::system::permissions::{can_deploy, can_read}; - -pub fn get_user_by_header( - header_map: &HeaderMap, - conn: &MysqlConnection, -) -> Result, InternalError> { - let option = header_map.get("Authorization"); - if option.is_none() { - return Ok(None); - } - let x = option.unwrap().to_str(); - if x.is_err() {} - let header = x.unwrap().to_string(); - - let split = header.split(' ').collect::>(); - - let option = split.get(0); - if option.is_none() { - return Ok(None); - } - let value = split.get(1); - if value.is_none() { - return Ok(None); - } - let value = value.unwrap().to_string(); - let key = option.unwrap().to_string(); - if key.eq("Bearer") { - let result = system::action::get_user_from_session_token(&value, conn)?; - return Ok(result); - } else if key.eq("Basic") { - let result = base64::decode(value)?; - let string = String::from_utf8(result)?; - let split = string.split(':').collect::>(); - - if !split.len().eq(&2) { - return Ok(None); - } - let result1 = get_user_by_username(split.get(0).unwrap(), conn)?; - if result1.is_none() { - return Ok(None); - } - let argon2 = Argon2::default(); - let user = result1.unwrap(); - let parsed_hash = PasswordHash::new(user.password.as_str())?; - if argon2 - .verify_password(split.get(1).unwrap().as_bytes(), &parsed_hash) - .is_err() - { - return Ok(None); - } - return Ok(Some(user)); - } - Ok(None) -} - -pub fn can_deploy_basic_auth( - header_map: &HeaderMap, - repo: &Repository, - conn: &MysqlConnection, -) -> Result<(bool, Option), InternalError> { - let option = get_user_by_header(header_map, conn)?; - if option.is_none() { - return Ok((false, None)); - } - let user = option.unwrap(); - Ok((can_deploy(&user.permissions, repo)?, Some(user))) -} - -pub fn can_read_basic_auth( - header_map: &HeaderMap, - repo: &Repository, - conn: &MysqlConnection, -) -> Result<(bool, Option), InternalError> { - match repo.security.visibility { - Visibility::Public => Ok((true, None)), - Visibility::Private => { - let option = get_user_by_header(header_map, conn)?; - if option.is_none() { - return Ok((false, None)); - } - let user = option.unwrap(); - Ok((can_read(&user.permissions, repo)?, Some(user))) - } - Visibility::Hidden => Ok((true, None)), - } -} - #[derive(Serialize, Deserialize, Clone, Debug)] pub struct NewUser { @@ -119,7 +24,6 @@ pub struct ModifyUser { pub struct NewPassword { pub password: String, } - #[derive(Serialize, Deserialize, Clone, Debug)] pub enum NewUserError { UsernameAlreadyExists, @@ -139,26 +43,3 @@ pub fn hash(password: String) -> Result { .to_string(); Ok(password_hash) } - -pub fn generate_session_token(connection: &MysqlConnection) -> Result { - loop { - let x: String = OsRng - .sample_iter(&Alphanumeric) - .take(128) - .map(char::from) - .collect(); - let result = get_session_token(&x, connection)?; - if result.is_none() { - return Ok(x); - } - } -} - -pub fn generate_auth_token() -> String { - let x: String = OsRng - .sample_iter(&Alphanumeric) - .take(64) - .map(char::from) - .collect(); - return format!("ntr_{}", x); -} diff --git a/backend/src/system/web/mod.rs b/backend/src/system/web/mod.rs new file mode 100644 index 00000000..b0303575 --- /dev/null +++ b/backend/src/system/web/mod.rs @@ -0,0 +1,14 @@ +pub mod public; +pub mod user; + +use actix_web::web::ServiceConfig; + +pub fn init_public_routes(cfg: &mut ServiceConfig) { + cfg.service(public::login); +} + +pub fn user_routes(cfg: &mut ServiceConfig) { + cfg.service(user::me); +} + +pub fn init_user_manager_routes(cfg: &mut ServiceConfig) {} \ No newline at end of file diff --git a/backend/src/system/web/public.rs b/backend/src/system/web/public.rs new file mode 100644 index 00000000..253fcb70 --- /dev/null +++ b/backend/src/system/web/public.rs @@ -0,0 +1,36 @@ +use actix_web::{HttpRequest, HttpResponse, HttpResponseBuilder, post}; +use actix_web::cookie::Cookie; +use actix_web::web; +use log::error; +use sea_orm::DatabaseConnection; +use serde::{Deserialize, Serialize}; +use crate::authentication::session::SessionManager; +use crate::authentication::session::SessionManagerType; +use crate::authentication::verify_login; +use crate::system::user::UserModel; +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct Login { + pub username: String, + pub password: String, +} + +#[post("/login")] +pub async fn login( + connection: web::Data, + session_manager: web::Data, + r: HttpRequest, + nc: web::Json, +) -> actix_web::Result { + let user = verify_login(nc.username.clone(), nc.password.clone(), &connection).await??; + let cookie: Cookie = r.cookie("session").unwrap(); + actix_web::rt::spawn(async move { + if (session_manager.set_user(cookie.value(), user.id).await).is_err() { + error!( + "Unable to save user {} to cookie {}", + user.id, + cookie.value() + ); + } + }); + Ok(HttpResponse::Ok().finish()) +} diff --git a/backend/src/system/web/user.rs b/backend/src/system/web/user.rs new file mode 100644 index 00000000..5223be73 --- /dev/null +++ b/backend/src/system/web/user.rs @@ -0,0 +1,15 @@ +use actix_web::{HttpRequest, HttpResponse, web}; +use actix_web::web::JsonBody; +use sea_orm::DatabaseConnection; +use crate::authentication::Authentication; +use crate::system::user::UserModel; +use actix_web::get; + +#[get("/me")] +pub async fn me( + database: web::Data, + auth: Authentication, +) -> actix_web::Result { + let user: UserModel = auth.get_user(&database).await??; + Ok(HttpResponse::Ok().json(user)) +} \ No newline at end of file diff --git a/backend/src/updater/mod.rs b/backend/src/updater/mod.rs new file mode 100644 index 00000000..a0b957bf --- /dev/null +++ b/backend/src/updater/mod.rs @@ -0,0 +1,11 @@ +#[cfg(feature = "updater_one-one")] +pub mod one_one; + +use thiserror::Error; + +#[derive(Error, Clone, Debug)] +pub enum UpdateError {} + +pub async fn update(_version: String) -> Result<(), UpdateError> { + Ok(()) +} diff --git a/backend/src/updater/one_one/mod.rs b/backend/src/updater/one_one/mod.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/backend/src/updater/one_one/mod.rs @@ -0,0 +1 @@ + diff --git a/backend/src/utils.rs b/backend/src/utils.rs index b008afdc..e39bc1bd 100644 --- a/backend/src/utils.rs +++ b/backend/src/utils.rs @@ -4,11 +4,23 @@ use std::path::{Path, PathBuf}; use actix_web::http::header::HeaderMap; use chrono::{DateTime, Duration, Local}; +use nitro_log::config::Config; +use nitro_log::{LoggerBuilders, NitroLogger}; use rust_embed::RustEmbed; use serde::{Deserialize, Serialize}; use crate::error::internal_error::InternalError; +use crate::settings::models::Mode; +pub fn load_logger>(logger: T) { + let file = match logger.as_ref() { + Mode::Debug => "log-debug.json", + Mode::Release => "log-release.json", + Mode::Install => "log-install.json", + }; + let config: Config = serde_json::from_str(Resources::file_get_string(file).as_str()).unwrap(); + NitroLogger::load(config, LoggerBuilders::default()).unwrap(); +} #[derive(RustEmbed)] #[folder = "$CARGO_MANIFEST_DIR/resources"] pub struct Resources; diff --git a/backend/src/webhook/mod.rs b/backend/src/webhook/mod.rs deleted file mode 100644 index 04048013..00000000 --- a/backend/src/webhook/mod.rs +++ /dev/null @@ -1,44 +0,0 @@ -use async_trait::async_trait; -use log::error; -use serde::{Deserialize, Serialize}; - -use crate::error::internal_error::InternalError; -use crate::repository::deploy::DeployInfo; - -#[async_trait] -pub trait WebhookHandler { - type WebhookConfig; - async fn handle( - config: &Self::WebhookConfig, - deploy_event: &DeployInfo, - ) -> Result<(), InternalError>; -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct DiscordConfig { - pub url: String, -} - -pub struct DiscordHandler; -#[allow(clippy::redundant_pattern_matching)] -#[async_trait] -impl WebhookHandler for DiscordHandler { - type WebhookConfig = DiscordConfig; - - async fn handle( - config: &Self::WebhookConfig, - _deploy_event: &DeployInfo, - ) -> Result<(), InternalError> { - let d_hook = webhook::client::WebhookClient::new(&config.url); - let result = d_hook.send(|x| x.content("Deploy Happening!")).await; - if let Err(error) = result { - //TODO more details - error!( - "Unable to Call Discord Webhook {}. Error {}", - config.url, error - ); - return Err(InternalError::Error("Bad Webhook".to_string())); - } - return Ok(()); - } -} diff --git a/frontend/README.md b/frontend/README.md index ec0f8417..4812f8f5 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -1,29 +1 @@ -# site - -## Project setup - -``` -npm install -``` - -### Compiles and hot-reloads for development - -``` -npm run serve -``` - -### Compiles and minifies for production - -``` -npm run build -``` - -### Lints and fixes files - -``` -npm run lint -``` - -### Customize configuration - -See [Configuration Reference](https://cli.vuejs.org/config/). +# Nitro Repo Frontend \ No newline at end of file diff --git a/frontend/config.json.example b/frontend/config.json.example deleted file mode 100644 index 3af82561..00000000 --- a/frontend/config.json.example +++ /dev/null @@ -1,3 +0,0 @@ -{ - "API_URL": "http://127.0.0.1:6742" -} From 51d8a0ad0b88359f8c41448af3c61a1433010c48 Mon Sep 17 00:00:00 2001 From: Wyatt Jacob Herkamp Date: Sat, 28 May 2022 09:47:32 -0400 Subject: [PATCH 02/76] Updates --- backend/resources/log-debug.json | 5 +- .../src/authentication/session/basic/mod.rs | 5 +- backend/src/bin/nitro_repo_full.rs | 4 +- backend/src/install/mod.rs | 3 +- backend/src/system/mod.rs | 17 ++- backend/src/system/models.rs | 20 ---- backend/src/system/utils.rs | 45 ------- backend/src/system/web/public.rs | 2 +- backend/src/utils.rs | 9 -- frontend/package-lock.json | 111 +----------------- frontend/package.json | 7 +- frontend/src/components/user/LoginComp.vue | 35 +++--- frontend/src/http-common.ts | 18 ++- frontend/src/store/user.ts | 22 ++-- nitro_repo-api-wrapper/src/Generic.ts | 40 ------- nitro_repo-api-wrapper/src/NitroRepoAPI.d.ts | 12 -- nitro_repo-api-wrapper/src/NitroRepoAPI.js | 45 ------- .../src/NitroRepoAPI.js.map | 1 - nitro_repo-api-wrapper/src/index.ts | 1 - 19 files changed, 70 insertions(+), 332 deletions(-) delete mode 100644 backend/src/system/models.rs delete mode 100644 backend/src/system/utils.rs delete mode 100644 nitro_repo-api-wrapper/src/Generic.ts delete mode 100644 nitro_repo-api-wrapper/src/NitroRepoAPI.d.ts delete mode 100644 nitro_repo-api-wrapper/src/NitroRepoAPI.js delete mode 100644 nitro_repo-api-wrapper/src/NitroRepoAPI.js.map diff --git a/backend/resources/log-debug.json b/backend/resources/log-debug.json index 8af4018f..db26dd3d 100644 --- a/backend/resources/log-debug.json +++ b/backend/resources/log-debug.json @@ -24,7 +24,8 @@ ], "loggers": [ { - "module": "nitro_repo", + "module": "api", + "always_execute": true, "levels": [ "TRACE", "DEBUG", @@ -47,7 +48,7 @@ ] }, { - "module": "nitro_repo", + "module": "api", "levels": [ "TRACE", "DEBUG", diff --git a/backend/src/authentication/session/basic/mod.rs b/backend/src/authentication/session/basic/mod.rs index 8b0450b2..7ea13c64 100644 --- a/backend/src/authentication/session/basic/mod.rs +++ b/backend/src/authentication/session/basic/mod.rs @@ -3,6 +3,7 @@ use rand::distributions::Alphanumeric; use rand::Rng; use std::collections::HashMap; use std::ops::Add; +use log::trace; use crate::authentication::session::{Session, SessionManagerType}; use time::{Duration, OffsetDateTime}; @@ -43,8 +44,8 @@ impl SessionManagerType for BasicSessionManager { async fn retrieve_session(&self, token: &str) -> Result, Self::Error> { let guard = self.sessions.read().await; - for x in guard.iter() { - println!("{:?}", x.0); + for (session, value) in guard.iter() { + trace!("Session {}: {:?}", session, value); } return Ok(guard.get(token).cloned()); } diff --git a/backend/src/bin/nitro_repo_full.rs b/backend/src/bin/nitro_repo_full.rs index 1bfa0956..5aded949 100644 --- a/backend/src/bin/nitro_repo_full.rs +++ b/backend/src/bin/nitro_repo_full.rs @@ -80,9 +80,9 @@ async fn main() -> std::io::Result<()> { .allow_any_method() .allow_any_origin().supports_credentials(), ) + .service( - web::scope("/api") - .wrap(HandleSession {}) + web::scope("/api").wrap(HandleSession {}) .configure(system::web::init_public_routes) .configure(system::web::user_routes) .service(web::scope("/admin") diff --git a/backend/src/install/mod.rs b/backend/src/install/mod.rs index 78b00083..356fdfca 100644 --- a/backend/src/install/mod.rs +++ b/backend/src/install/mod.rs @@ -23,9 +23,8 @@ use thiserror::Error; use crate::settings::models::{Application, Database, EmailSetting, Mode, MysqlSettings, SecuritySettings, SiteSetting, StringMap}; use crate::system::permissions::UserPermissions; -use crate::system::user; +use crate::system::{hash, user}; use crate::system::user::UserEntity; -use crate::system::utils::hash; use crate::utils::get_current_time; use crate::{authentication, GeneralSettings}; use sea_orm::ConnectionTrait; diff --git a/backend/src/system/mod.rs b/backend/src/system/mod.rs index c46e09fb..4358e24a 100644 --- a/backend/src/system/mod.rs +++ b/backend/src/system/mod.rs @@ -1,5 +1,18 @@ -pub mod models; +use argon2::{Argon2, PasswordHasher}; +use argon2::password_hash::SaltString; +use rand_core::OsRng; +use crate::error::internal_error::InternalError; + pub mod permissions; pub mod user; -pub mod utils; pub mod web; + +pub fn hash(password: String) -> Result { + let salt = SaltString::generate(&mut OsRng); + + let argon2 = Argon2::default(); + let password_hash = argon2 + .hash_password(password.as_bytes(), salt.as_ref())? + .to_string(); + Ok(password_hash) +} diff --git a/backend/src/system/models.rs b/backend/src/system/models.rs deleted file mode 100644 index c49ed8a0..00000000 --- a/backend/src/system/models.rs +++ /dev/null @@ -1,20 +0,0 @@ -use std::fmt::Debug; - -use sea_orm::{FromQueryResult, JsonValue}; -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Clone, Serialize, Deserialize, FromQueryResult)] -pub struct UserListResponse { - pub id: i64, - pub name: String, -} - -#[derive(Debug, Clone, Serialize, Deserialize, FromQueryResult)] -pub struct UserResponse { - pub id: i64, - pub name: String, - pub username: String, - pub email: String, - pub permissions: JsonValue, - pub created: i64, -} diff --git a/backend/src/system/utils.rs b/backend/src/system/utils.rs deleted file mode 100644 index 3dfab4c3..00000000 --- a/backend/src/system/utils.rs +++ /dev/null @@ -1,45 +0,0 @@ -use argon2::password_hash::rand_core::OsRng; -use argon2::password_hash::SaltString; -use argon2::{Argon2, PasswordHasher}; - -use serde::{Deserialize, Serialize}; - -use crate::error::internal_error::InternalError; - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct NewUser { - pub name: String, - pub username: String, - pub email: String, - pub password: String, -} - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct ModifyUser { - pub name: String, - pub email: String, -} - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct NewPassword { - pub password: String, -} -#[derive(Serialize, Deserialize, Clone, Debug)] -pub enum NewUserError { - UsernameAlreadyExists, - UsernameMissing, - EmailAlreadyExists, - EmailMissing, - PasswordDoesNotMatch, - PasswordMissing, -} - -pub fn hash(password: String) -> Result { - let salt = SaltString::generate(&mut OsRng); - - let argon2 = Argon2::default(); - let password_hash = argon2 - .hash_password(password.as_bytes(), salt.as_ref())? - .to_string(); - Ok(password_hash) -} diff --git a/backend/src/system/web/public.rs b/backend/src/system/web/public.rs index 253fcb70..6cae0e94 100644 --- a/backend/src/system/web/public.rs +++ b/backend/src/system/web/public.rs @@ -32,5 +32,5 @@ pub async fn login( ); } }); - Ok(HttpResponse::Ok().finish()) + Ok(HttpResponse::Ok().json(user)) } diff --git a/backend/src/utils.rs b/backend/src/utils.rs index e39bc1bd..971d2233 100644 --- a/backend/src/utils.rs +++ b/backend/src/utils.rs @@ -55,15 +55,6 @@ pub fn default_expiration() -> i64 { time.add(Duration::days(30)).timestamp_millis() } -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct EmailChangeRequest { - pub email_username: Option, - pub email_password: Option, - pub email_host: Option, - pub encryption: Option, - pub from: Option, - pub port: Option, -} pub fn get_accept(header_map: &HeaderMap) -> Result, InternalError> { let option = header_map.get("accept"); diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c4a2dd63..ca55a900 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -19,7 +19,7 @@ "fast-xml-parser": "^4.0.7", "pinia": "^2.0.14", "prismjs": "^1.28.0", - "ts-results": "^3.3.0", + "ts-results": "3.3.0", "vite-plugin-ejs": "^1.4.4", "vue": "^3.2.36", "vue-axios": "^3.4.1", @@ -43,7 +43,6 @@ "@vue/cli-service": "~5.0.4", "@vue/compiler-sfc": "^3.2.36", "@vue/eslint-config-prettier": "^7.0.0", - "@vue/eslint-config-typescript": "^10.0.0", "eslint": "^8.16.0", "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-vue": "^9.0.1", @@ -3295,24 +3294,6 @@ "prettier": ">= 2.0.0" } }, - "node_modules/@vue/eslint-config-typescript": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-10.0.0.tgz", - "integrity": "sha512-F94cL8ug3FaYXlCfU5/wiGjk1qeadmoBpRGAOBq+qre3Smdupa59dd6ZJrsfRODpsMPyTG7330juMDsUvpZ3Rw==", - "dev": true, - "dependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0", - "@typescript-eslint/parser": "^5.0.0", - "vue-eslint-parser": "^8.0.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0", - "eslint-plugin-vue": "^8.0.1" - } - }, "node_modules/@vue/reactivity": { "version": "3.2.36", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.36.tgz", @@ -12793,52 +12774,6 @@ "vue": "^3.0.5" } }, - "node_modules/vue-eslint-parser": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz", - "integrity": "sha512-dzHGG3+sYwSf6zFBa0Gi9ZDshD7+ad14DGOdTLjruRVgZXe2J+DcZ9iUhyR48z5g1PqRa20yt3Njna/veLJL/g==", - "dev": true, - "dependencies": { - "debug": "^4.3.2", - "eslint-scope": "^7.0.0", - "eslint-visitor-keys": "^3.1.0", - "espree": "^9.0.0", - "esquery": "^1.4.0", - "lodash": "^4.17.21", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=6.0.0" - } - }, - "node_modules/vue-eslint-parser/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/vue-eslint-parser/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/vue-final-modal": { "version": "3.4.4", "resolved": "https://registry.npmjs.org/vue-final-modal/-/vue-final-modal-3.4.4.tgz", @@ -16240,17 +16175,6 @@ "eslint-plugin-prettier": "^4.0.0" } }, - "@vue/eslint-config-typescript": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-10.0.0.tgz", - "integrity": "sha512-F94cL8ug3FaYXlCfU5/wiGjk1qeadmoBpRGAOBq+qre3Smdupa59dd6ZJrsfRODpsMPyTG7330juMDsUvpZ3Rw==", - "dev": true, - "requires": { - "@typescript-eslint/eslint-plugin": "^5.0.0", - "@typescript-eslint/parser": "^5.0.0", - "vue-eslint-parser": "^8.0.0" - } - }, "@vue/reactivity": { "version": "3.2.36", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.36.tgz", @@ -23170,39 +23094,6 @@ "integrity": "sha512-PUQzqdpI7672YYuoHdTLENHldieVMis0u9g2n7NAxiLGdiaqCD/QaYtbDOvtASpN5oSIfKxQgPV+i45MOlkKnw==", "requires": {} }, - "vue-eslint-parser": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz", - "integrity": "sha512-dzHGG3+sYwSf6zFBa0Gi9ZDshD7+ad14DGOdTLjruRVgZXe2J+DcZ9iUhyR48z5g1PqRa20yt3Njna/veLJL/g==", - "dev": true, - "requires": { - "debug": "^4.3.2", - "eslint-scope": "^7.0.0", - "eslint-visitor-keys": "^3.1.0", - "espree": "^9.0.0", - "esquery": "^1.4.0", - "lodash": "^4.17.21", - "semver": "^7.3.5" - }, - "dependencies": { - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, "vue-final-modal": { "version": "3.4.4", "resolved": "https://registry.npmjs.org/vue-final-modal/-/vue-final-modal-3.4.4.tgz", diff --git a/frontend/package.json b/frontend/package.json index d912a7a7..efaa0882 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -20,7 +20,6 @@ "fast-xml-parser": "^4.0.7", "pinia": "^2.0.14", "prismjs": "^1.28.0", - "ts-results": "^3.3.0", "vite-plugin-ejs": "^1.4.4", "vue": "^3.2.36", "vue-axios": "^3.4.1", @@ -30,7 +29,8 @@ "vue-meta": "3.0.0-alpha.10", "vue-prism-editor": "^2.0.0-alpha.2", "vue-router": "^4.0.15", - "vue3-cookies": "^1.0.6" + "vue3-cookies": "^1.0.6", + "ts-results": "3.3.0" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^5.26.0", @@ -44,7 +44,6 @@ "@vue/cli-service": "~5.0.4", "@vue/compiler-sfc": "^3.2.36", "@vue/eslint-config-prettier": "^7.0.0", - "@vue/eslint-config-typescript": "^10.0.0", "eslint": "^8.16.0", "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-vue": "^9.0.1", @@ -55,4 +54,4 @@ "unplugin-vue-components": "^0.19.6", "vite": "^2.9.9" } -} +} \ No newline at end of file diff --git a/frontend/src/components/user/LoginComp.vue b/frontend/src/components/user/LoginComp.vue index ff7bc089..65c04abe 100644 --- a/frontend/src/components/user/LoginComp.vue +++ b/frontend/src/components/user/LoginComp.vue @@ -38,6 +38,9 @@ import { defineComponent, ref } from "vue"; import { login } from "@nitro_repo/nitro_repo-api-wrapper"; import { AuthToken } from "@nitro_repo/nitro_repo-api-wrapper"; import { useCookies } from "vue3-cookies"; +import apiClient from "@/http-common"; +import { Result } from "ts-results"; +import { valueToNode } from "@babel/types"; export default defineComponent({ setup() { @@ -51,26 +54,20 @@ export default defineComponent({ }, methods: { async onSubmit(username: string, password: string) { - const value = await login(username, password); - if (value.ok) { - let loginRequest = value.val as AuthToken; - let date = new Date(loginRequest.expiration * 1000); - this.cookies.set( - "token", - loginRequest.token, - date, - undefined, - undefined, - undefined, - "Lax" - ); + let response: Result = await apiClient.post("api/login", { + username: username, + password: password, + }); + if (response.ok) { location.reload(); - } else { - this.form.password = ""; - this.$notify({ - title: value.val.user_friendly_message, - type: "warn", - }); + } else if (response.err) { + if (response.val) { + this.form.password = ""; + this.$notify({ + title: response.val.data.error, + type: "warn", + }); + } } }, }, diff --git a/frontend/src/http-common.ts b/frontend/src/http-common.ts index f3e451d8..3db3dbee 100644 --- a/frontend/src/http-common.ts +++ b/frontend/src/http-common.ts @@ -1,5 +1,5 @@ import axios, { AxiosInstance } from "axios"; - +import { Ok, Err } from "ts-results"; export let apiURL: string; if (import.meta.env.VITE_API_URL == undefined) { apiURL = appURL; @@ -9,10 +9,26 @@ if (import.meta.env.VITE_API_URL == undefined) { const apiClient: AxiosInstance = axios.create({ baseURL: apiURL, + withCredentials: true, headers: { "Content-Type": "application/json", Accept: "application/json", }, }); +apiClient.interceptors.response.use(function (response) { + return new Ok(response.data); + +}, function (error) { + if (error.response) { + return Err(error.response) + } else if (error.request) { + console.log('Error', error); + return Err(undefined); +} else { + // Something happened in setting up the request that triggered an Error + console.log('Error', error); + return Err(undefined); +} +}) export default apiClient; diff --git a/frontend/src/store/user.ts b/frontend/src/store/user.ts index 251ea0a6..f2f05b35 100644 --- a/frontend/src/store/user.ts +++ b/frontend/src/store/user.ts @@ -1,31 +1,25 @@ import { getUser, User } from '@nitro_repo/nitro_repo-api-wrapper'; import { defineStore, acceptHMRUpdate } from 'pinia' import { inject } from 'vue'; - +import apiClient from '@/http-common'; +import { Result } from 'ts-results'; export const useUserStore = defineStore({ id: 'user', state: () => ({ - user: undefined, - date: new Date() + user: undefined }), actions: { logout() { - this.$patch({ user: undefined, date: new Date() }) + this.$patch({ user: undefined }) }, async loadUser() { - const token: string | undefined = inject('token') - if (token == undefined) { - return; - } - const user = await getUser(token); - if (user.err) return; - this.$patch({ - user: user.val, - date: new Date(user.val.created).toLocaleDateString("en-US") - }) + const user: Result = await apiClient.get('api/me'); + if (user.ok) { + this.$patch({ user: user.val }); + } }, }, }) diff --git a/nitro_repo-api-wrapper/src/Generic.ts b/nitro_repo-api-wrapper/src/Generic.ts deleted file mode 100644 index 1c8460fb..00000000 --- a/nitro_repo-api-wrapper/src/Generic.ts +++ /dev/null @@ -1,40 +0,0 @@ -import {apiClient, BasicResponse} from "./NitroRepoAPI"; -import {Err, Ok} from "ts-results"; -import {INTERNAL_ERROR, NOT_AUTHORIZED,} from "./NitroRepoAPI"; - -export interface SiteInfo { - name: string; - description: string; -} - - -export async function getSiteInfo() { - return apiClient - .get("/api/info/site") - .then( - (result) => { - const resultData = result.data; - let value = JSON.stringify(resultData); - - let response: BasicResponse = JSON.parse(value); - - if (response.success) { - return Ok(response.data as SiteInfo); - } else { - return Err(INTERNAL_ERROR); - } - }, - (err) => { - if (err.response) { - if ((err.response.status = 401)) { - return Err(NOT_AUTHORIZED); - } - return Err(INTERNAL_ERROR); - } else if (err.request) { - return Err(INTERNAL_ERROR); - } else { - return Err(INTERNAL_ERROR); - } - } - ); -} diff --git a/nitro_repo-api-wrapper/src/NitroRepoAPI.d.ts b/nitro_repo-api-wrapper/src/NitroRepoAPI.d.ts deleted file mode 100644 index 100cae6e..00000000 --- a/nitro_repo-api-wrapper/src/NitroRepoAPI.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { AxiosInstance } from "axios"; -export declare let apiURL: string; -export declare let apiClient: AxiosInstance; -export declare function init(myURL: string): void; -export interface APIError { - user_friendly_message: string; - code: number; -} -export declare const INVALID_LOGIN: APIError; -export declare const NOT_AUTHORIZED: APIError; -export declare const INTERNAL_ERROR: APIError; -export declare function createAPIError(code: number, message: string): APIError; diff --git a/nitro_repo-api-wrapper/src/NitroRepoAPI.js b/nitro_repo-api-wrapper/src/NitroRepoAPI.js deleted file mode 100644 index af1dd664..00000000 --- a/nitro_repo-api-wrapper/src/NitroRepoAPI.js +++ /dev/null @@ -1,45 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.createAPIError = exports.INTERNAL_ERROR = exports.NOT_AUTHORIZED = exports.INVALID_LOGIN = exports.init = exports.apiClient = exports.apiURL = void 0; -var axios_1 = __importDefault(require("axios")); -exports.apiClient = axios_1.default.create({ - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, -}); -function init(myURL) { - exports.apiURL = myURL; - exports.apiClient = axios_1.default.create({ - baseURL: myURL, - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - }); -} -exports.init = init; -exports.INVALID_LOGIN = { - user_friendly_message: "Invalid Username or Password", - code: 401, -}; -exports.NOT_AUTHORIZED = { - user_friendly_message: "Not Authorized for that action", - code: 401, -}; -exports.INTERNAL_ERROR = { - user_friendly_message: "Internal Error Occured ", - code: 500, -}; -function createAPIError(code, message) { - var value = { - user_friendly_message: message, - code: code, - }; - return value; -} -exports.createAPIError = createAPIError; -//# sourceMappingURL=NitroRepoAPI.js.map \ No newline at end of file diff --git a/nitro_repo-api-wrapper/src/NitroRepoAPI.js.map b/nitro_repo-api-wrapper/src/NitroRepoAPI.js.map deleted file mode 100644 index e50a963e..00000000 --- a/nitro_repo-api-wrapper/src/NitroRepoAPI.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"NitroRepoAPI.js","sourceRoot":"","sources":["NitroRepoAPI.ts"],"names":[],"mappings":";;;;;;AAAA,gDAA2C;AAIhC,QAAA,SAAS,GAAkB,eAAK,CAAC,MAAM,CAAC;IAC/C,OAAO,EAAE;QACL,cAAc,EAAE,kBAAkB;QAClC,MAAM,EAAE,kBAAkB;KAC7B;CACJ,CAAC,CAAC;AAEH,SAAgB,IAAI,CAAC,KAAa;IAC9B,cAAM,GAAG,KAAK,CAAA;IACd,iBAAS,GAAG,eAAK,CAAC,MAAM,CAAC;QACrB,OAAO,EAAE,KAAK;QACd,OAAO,EAAE;YACL,cAAc,EAAE,kBAAkB;YAClC,MAAM,EAAE,kBAAkB;SAC7B;KACJ,CAAC,CAAC;AACP,CAAC;AATD,oBASC;AAQY,QAAA,aAAa,GAAa;IACnC,qBAAqB,EAAE,8BAA8B;IACrD,IAAI,EAAE,GAAG;CACZ,CAAC;AACW,QAAA,cAAc,GAAa;IACpC,qBAAqB,EAAE,gCAAgC;IACvD,IAAI,EAAE,GAAG;CACZ,CAAC;AACW,QAAA,cAAc,GAAa;IACpC,qBAAqB,EAAE,yBAAyB;IAChD,IAAI,EAAE,GAAG;CACZ,CAAC;AAEF,SAAgB,cAAc,CAAC,IAAY,EAAE,OAAe;IACxD,IAAI,KAAK,GAAa;QAClB,qBAAqB,EAAE,OAAO;QAC9B,IAAI,EAAE,IAAI;KACb,CAAC;IACF,OAAO,KAAK,CAAC;AACjB,CAAC;AAND,wCAMC"} \ No newline at end of file diff --git a/nitro_repo-api-wrapper/src/index.ts b/nitro_repo-api-wrapper/src/index.ts index 11198892..1aacd35b 100644 --- a/nitro_repo-api-wrapper/src/index.ts +++ b/nitro_repo-api-wrapper/src/index.ts @@ -1,5 +1,4 @@ export * from "./NitroRepoAPI" -export *from "./Generic" export * from "./repository/repositoryAdminAPI" export * from "./repository/repositoryTypes" export *from "./repository/repositoryUserAPI" From 65a7d1809e704cf384467585ac95c037ea544a25 Mon Sep 17 00:00:00 2001 From: Wyatt Jacob Herkamp Date: Mon, 30 May 2022 08:40:25 -0400 Subject: [PATCH 03/76] Code Cleanup --- backend/Cargo.toml | 2 +- backend/src/authentication/middleware.rs | 14 ++-- .../src/authentication/session/basic/mod.rs | 11 +-- backend/src/bin/nitro_repo_full.rs | 69 ++++++++++--------- backend/src/cli/mod.rs | 9 +-- backend/src/error/api_error.rs | 24 ++----- backend/src/error/handlers/json_error.rs | 3 +- backend/src/install/mod.rs | 38 +++++----- backend/src/repository/data/mod.rs | 10 ++- backend/src/repository/response.rs | 10 ++- backend/src/repository/settings/frontend.rs | 4 -- backend/src/settings/mod.rs | 9 ++- backend/src/settings/models.rs | 16 ++--- backend/src/storage/file.rs | 18 +++-- backend/src/storage/models.rs | 10 +-- backend/src/storage/multi/mod.rs | 21 +++--- backend/src/storage/multi/web/admin.rs | 31 ++++++--- backend/src/storage/multi/web/mod.rs | 2 +- backend/src/system/mod.rs | 3 +- backend/src/system/permissions/mod.rs | 19 ++--- backend/src/system/permissions/options.rs | 18 ++--- backend/src/system/web/mod.rs | 6 +- backend/src/system/web/public.rs | 5 +- backend/src/system/web/user.rs | 8 +-- backend/src/utils.rs | 2 - 25 files changed, 176 insertions(+), 186 deletions(-) diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 3ae20ba7..0d016ec6 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -51,7 +51,7 @@ style-term = "1.0.0" mime_guess = "2.0.4" # Log nitro_log = { git = "https://github.com/wyatt-herkamp/nitro_log", features = ["chrono", "style-term"] } -log = "0.4.17" +log = { version = "0.4.17", features = ["kv_unstable", "kv_unstable_std", "kv_unstable_serde"] } # Rust Internal strum = { version = "0.24.0", features = ["derive"] } strum_macros = "0.24.0" diff --git a/backend/src/authentication/middleware.rs b/backend/src/authentication/middleware.rs index cd15d1a9..4f90cecf 100644 --- a/backend/src/authentication/middleware.rs +++ b/backend/src/authentication/middleware.rs @@ -1,13 +1,8 @@ use std::fmt; use std::future::{ready, Ready}; use std::rc::Rc; - use std::time::SystemTime; -use crate::authentication::{ - auth_token, session::Session, session::SessionManager, verify_login, Authentication, -}; - use actix_web::cookie::{Cookie, SameSite}; use actix_web::http::header::{HeaderValue, AUTHORIZATION, ORIGIN, SET_COOKIE}; use actix_web::http::Method; @@ -15,12 +10,14 @@ use actix_web::{ dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform}, web, Error, HttpMessage, }; - use futures_util::future::LocalBoxFuture; use log::{debug, trace, warn}; use sea_orm::DatabaseConnection; use crate::authentication::session::SessionManagerType; +use crate::authentication::{ + auth_token, session::Session, session::SessionManager, verify_login, Authentication, +}; pub struct HandleSession; @@ -97,8 +94,7 @@ where } else { (Authentication::NoIdentification, Option::None) } - } else { - let mut session = session.unwrap(); + } else if let Some(mut session) = session { if session.expiration <= SystemTime::UNIX_EPOCH { session = session_manager .re_create_session(&session.token) @@ -106,6 +102,8 @@ where .unwrap(); } (Authentication::Session(session.clone()), Option::None) + } else { + (Authentication::NoIdentification, Option::None) } } else if let Some(header) = req.headers().get(AUTHORIZATION) { //If it is an Authorization Header pull Database from App Data diff --git a/backend/src/authentication/session/basic/mod.rs b/backend/src/authentication/session/basic/mod.rs index 7ea13c64..8e2c25ed 100644 --- a/backend/src/authentication/session/basic/mod.rs +++ b/backend/src/authentication/session/basic/mod.rs @@ -1,14 +1,15 @@ -use async_trait::async_trait; -use rand::distributions::Alphanumeric; -use rand::Rng; use std::collections::HashMap; use std::ops::Add; -use log::trace; -use crate::authentication::session::{Session, SessionManagerType}; +use async_trait::async_trait; +use log::trace; +use rand::distributions::Alphanumeric; +use rand::Rng; use time::{Duration, OffsetDateTime}; use tokio::sync::RwLock; +use crate::authentication::session::{Session, SessionManagerType}; + pub struct BasicSessionManager { pub sessions: RwLock>, } diff --git a/backend/src/bin/nitro_repo_full.rs b/backend/src/bin/nitro_repo_full.rs index 5aded949..b16b285a 100644 --- a/backend/src/bin/nitro_repo_full.rs +++ b/backend/src/bin/nitro_repo_full.rs @@ -1,27 +1,25 @@ use std::env::current_dir; use std::error::Error; use std::io::ErrorKind; -use std::net::ToSocketAddrs; use std::process::exit; -use std::rc::Rc; + use actix_cors::Cors; -use actix_web::{App, HttpServer, web}; -use actix_web::guard::GuardContext; -use actix_web::web::Data; -use log::{info, trace}; +use actix_web::main; +use actix_web::web::{Data, PayloadConfig}; +use actix_web::{web, App, HttpServer}; +use log::info; use semver::Version; use tokio::fs::read_to_string; use tokio::sync::RwLock; + +use api::authentication::middleware::HandleSession; +use api::authentication::session::SessionManager; use api::cli::handle_cli; -use api::{frontend, NitroRepo, storage, system}; use api::settings::load_configs; use api::settings::models::GeneralSettings; use api::storage::multi::MultiStorageController; use api::utils::load_logger; -use actix_web::main; -use sea_orm::DatabaseConnection; -use api::authentication::middleware::HandleSession; -use api::authentication::session::SessionManager; +use api::{frontend, storage, system, NitroRepo}; #[main] async fn main() -> std::io::Result<()> { @@ -32,25 +30,32 @@ async fn main() -> std::io::Result<()> { let configs = current_dir.join("cfg"); let main_config = current_dir.join("nitro_repo.toml"); if !main_config.exists() { - eprintln!("Config not found. Should be at {:?}", main_config.as_os_str()); + eprintln!( + "Config not found. Should be at {:?}", + main_config.as_os_str() + ); exit(1) } - let init_settings: GeneralSettings = toml::from_str(&read_to_string(&main_config).await?).map_err(convert_error)?; + let init_settings: GeneralSettings = + toml::from_str(&read_to_string(&main_config).await?).map_err(convert_error)?; let version = Version::parse(&init_settings.internal.version).map_err(convert_error)?; // Sets the Log Location std::env::set_var("LOG_LOCATION", &init_settings.application.log); load_logger(&init_settings.application.mode); info!("Initializing Database Connection"); - let connection = sea_orm::Database::connect(init_settings.database.clone()).await.map_err(convert_error)?; + let connection = sea_orm::Database::connect(init_settings.database.clone()) + .await + .map_err(convert_error)?; info!("Initializing Session and Authorization"); let session_manager = SessionManager::try_from(init_settings.session.clone()).unwrap(); info!("Initializing State"); let settings = load_configs(configs).await.map_err(convert_error)?; - let storages = current_dir.join("storages.json"); - let storages = MultiStorageController::init(storages).await.map_err(convert_error)?; + let storages = MultiStorageController::init(storages) + .await + .map_err(convert_error)?; let nitro_repo = NitroRepo { settings: RwLock::new(settings), @@ -60,7 +65,7 @@ async fn main() -> std::io::Result<()> { let application = nitro_repo.core.application.clone(); - let max_upload = application.max_upload; + let max_upload = Data::new(PayloadConfig::default().limit(application.max_upload)); let address = application.address.clone(); let storages_data = Data::new(storages); @@ -69,26 +74,29 @@ async fn main() -> std::io::Result<()> { let session_data = Data::new(session_manager); let server = HttpServer::new(move || { - App::new(). - app_data(storages_data.clone()). - app_data(site_state.clone()). - app_data(database_data.clone()). - app_data(session_data.clone()) + App::new() + .app_data(storages_data.clone()) + .app_data(site_state.clone()) + .app_data(database_data.clone()) + .app_data(session_data.clone()) + .app_data(max_upload.clone()) .wrap( Cors::default() .allow_any_header() .allow_any_method() - .allow_any_origin().supports_credentials(), + .allow_any_origin() + .supports_credentials(), ) - .service( - web::scope("/api").wrap(HandleSession {}) + web::scope("/api") + .wrap(HandleSession {}) .configure(system::web::init_public_routes) .configure(system::web::user_routes) - .service(web::scope("/admin") - .configure(system::web::init_user_manager_routes) - .configure(storage::multi::web::init_admin_routes) - ) + .service( + web::scope("/admin") + .configure(system::web::init_user_manager_routes) + .configure(storage::multi::web::init_admin_routes), + ), ) .configure(frontend::init) }); @@ -112,7 +120,6 @@ async fn main() -> std::io::Result<()> { return server.bind(address)?.run().await; } - fn convert_error>>(e: E) -> std::io::Error { std::io::Error::new(ErrorKind::Other, e) -} \ No newline at end of file +} diff --git a/backend/src/cli/mod.rs b/backend/src/cli/mod.rs index 70eac3d9..c2e99329 100644 --- a/backend/src/cli/mod.rs +++ b/backend/src/cli/mod.rs @@ -1,12 +1,13 @@ use std::env::current_dir; + +use clap::Parser; +use log::error; +use style_term::{DefaultColor, StyleString}; + use crate::install::load_installer; use crate::settings::models::Mode; use crate::updater; use crate::utils::load_logger; -use clap::Parser; -use log::error; -use std::path::Path; -use style_term::{DefaultColor, StyleString}; #[derive(Parser, Debug)] #[clap(author, version, about, long_about = None)] diff --git a/backend/src/error/api_error.rs b/backend/src/error/api_error.rs index 8193735a..7e1780dc 100644 --- a/backend/src/error/api_error.rs +++ b/backend/src/error/api_error.rs @@ -1,10 +1,10 @@ +use std::error::Error; +use std::fmt::{Debug, Display, Formatter}; + use actix_web::body::BoxBody; use actix_web::http::StatusCode; - use actix_web::{HttpResponse, HttpResponseBuilder, ResponseError}; use serde_json::json; -use std::error::Error; -use std::fmt::{Debug, Display, Formatter}; pub struct APIError { pub message: Option, @@ -41,14 +41,9 @@ impl From<(&str, StatusCode)> for APIError { impl Debug for APIError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { if let Some(message) = &self.message { - write!( - f, - "Status Code: {} Error: {}", - self.status_code.to_string(), - message - ) + write!(f, "Status Code: {} Error: {}", self.status_code, message) } else { - write!(f, "Status Code: {}", self.status_code.to_string(),) + write!(f, "Status Code: {}", self.status_code,) } } } @@ -56,14 +51,9 @@ impl Debug for APIError { impl Display for APIError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { if let Some(message) = &self.message { - write!( - f, - "Status Code: {} Error: {}", - self.status_code.to_string(), - message - ) + write!(f, "Status Code: {} Error: {}", self.status_code, message) } else { - write!(f, "Status Code: {}", self.status_code.to_string(),) + write!(f, "Status Code: {}", self.status_code,) } } } diff --git a/backend/src/error/handlers/json_error.rs b/backend/src/error/handlers/json_error.rs index c81ea8ba..c9ba76ca 100644 --- a/backend/src/error/handlers/json_error.rs +++ b/backend/src/error/handlers/json_error.rs @@ -1,5 +1,4 @@ use actix_web::error::{ErrorBadRequest, JsonPayloadError}; - use actix_web::web::JsonConfig; use actix_web::HttpRequest; use log::trace; @@ -10,5 +9,5 @@ pub fn json_config() -> JsonConfig { pub fn handle(payload: JsonPayloadError, _request: &HttpRequest) -> actix_web::Error { trace!("JSON Error: {}", payload); - ErrorBadRequest(format!("Bad Json Payload {}", payload.to_string())) + ErrorBadRequest(format!("Bad Json Payload {}", payload)) } diff --git a/backend/src/install/mod.rs b/backend/src/install/mod.rs index 356fdfca..14c221c9 100644 --- a/backend/src/install/mod.rs +++ b/backend/src/install/mod.rs @@ -1,15 +1,20 @@ +use std::fmt::{Display, Formatter}; +use std::fs::{create_dir_all, OpenOptions}; use std::io; +use std::io::{Stdout, Write}; +use std::path::PathBuf; +use crossterm::{ + event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, + execute, + terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, +}; use log::{error, info, trace}; -use serde::{Deserialize, Serialize}; - -use crossterm::{event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, ExecutableCommand, execute, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}}; use sea_orm::ActiveValue::Set; +use sea_orm::ConnectionTrait; use sea_orm::{DatabaseConnection, EntityTrait, Schema}; -use std::fmt::{Display, Formatter}; -use std::fs::{create_dir_all, OpenOptions}; -use std::io::{Stdout, Write}; -use std::path::{Path, PathBuf}; +use serde::{Deserialize, Serialize}; +use thiserror::Error; use tui::{ backend::{Backend, CrosstermBackend}, layout::{Constraint, Direction, Layout}, @@ -18,17 +23,16 @@ use tui::{ widgets::{Block, Borders, List, ListItem, Paragraph}, Frame, Terminal, }; +use unicode_width::UnicodeWidthStr; -use thiserror::Error; - -use crate::settings::models::{Application, Database, EmailSetting, Mode, MysqlSettings, SecuritySettings, SiteSetting, StringMap}; +use crate::settings::models::{ + Application, Database, EmailSetting, Mode, MysqlSettings, SecuritySettings, SiteSetting, +}; use crate::system::permissions::UserPermissions; -use crate::system::{hash, user}; use crate::system::user::UserEntity; +use crate::system::{hash, user}; use crate::utils::get_current_time; use crate::{authentication, GeneralSettings}; -use sea_orm::ConnectionTrait; -use unicode_width::UnicodeWidthStr; #[derive(Error, Debug)] pub enum InstallError { @@ -115,9 +119,7 @@ impl From for user::database::ActiveModel { repository_manager: true, deployer: None, viewer: None, - } - .try_into() - .unwrap()), + }), created: Set(get_current_time()), } } @@ -380,7 +382,7 @@ fn ui(f: &mut Frame, app: &App) { Constraint::Length(1), Constraint::Length(3), ] - .as_ref(), + .as_ref(), ) .split(f.size()); let mut messages: Vec = Vec::new(); @@ -561,6 +563,6 @@ fn close(mut terminal: Terminal>) { LeaveAlternateScreen, DisableMouseCapture ) - .unwrap(); + .unwrap(); terminal.show_cursor().unwrap(); } diff --git a/backend/src/repository/data/mod.rs b/backend/src/repository/data/mod.rs index 9962e125..87a2a5c8 100644 --- a/backend/src/repository/data/mod.rs +++ b/backend/src/repository/data/mod.rs @@ -1,16 +1,14 @@ use std::fmt::Debug; +use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; +use crate::error::internal_error::InternalError; use crate::repository::settings::frontend::Frontend; use crate::repository::settings::security::Visibility; - use crate::repository::settings::{Policy, FRONTEND_CONFIG}; use crate::storage::models::Storage; -use crate::error::internal_error::InternalError; -use serde::de::DeserializeOwned; - /// Types of Repositories that can exist. #[derive(Serialize, Deserialize, Clone, Debug, strum_macros::Display, strum_macros::EnumString)] pub enum RepositoryType { @@ -43,7 +41,7 @@ impl RepositoryConfig { /// Pull the Frontend Config pub async fn get_frontend_config( &self, - storage: &Box, + storage: &dyn Storage, ) -> Result, InternalError> { let option = storage.get_file(self, FRONTEND_CONFIG).await?; if option.is_none() { @@ -56,7 +54,7 @@ impl RepositoryConfig { /// Update the frontend config async fn save_frontend_config( &self, - storage: &Box, + storage: &dyn Storage, frontend: Option, ) -> Result<(), InternalError> { if frontend.is_none() { diff --git a/backend/src/repository/response.rs b/backend/src/repository/response.rs index e9fd7790..2a077f70 100644 --- a/backend/src/repository/response.rs +++ b/backend/src/repository/response.rs @@ -1,18 +1,16 @@ +use std::collections::HashMap; + use actix_web::body::BoxBody; use actix_web::http::header::CONTENT_LOCATION; use actix_web::http::StatusCode; use actix_web::web::Json; use actix_web::{HttpRequest, HttpResponse, Responder}; -use std::collections::HashMap; - -use crate::error::internal_error::InternalError; use serde::{Deserialize, Serialize}; use serde_json::Value; +use crate::error::internal_error::InternalError; use crate::repository::data::RepositoryConfig; - use crate::repository::frontend::FrontendResponse; - use crate::repository::nitro::{NitroVersion, ProjectData, VersionData}; use crate::storage::file::StorageFileResponse; @@ -45,7 +43,7 @@ impl TryFrom<(T, StatusCode)> for RepoResponse { fn try_from((value, status): (T, StatusCode)) -> Result { let result = serde_json::to_value(value)?; - return Ok(Self::Json(result, status)); + Ok(Self::Json(result, status)) } } #[derive(Debug, Serialize, Deserialize, Clone)] diff --git a/backend/src/repository/settings/frontend.rs b/backend/src/repository/settings/frontend.rs index 61fe5af2..109dc3a5 100644 --- a/backend/src/repository/settings/frontend.rs +++ b/backend/src/repository/settings/frontend.rs @@ -1,10 +1,6 @@ use badge_maker::Style; use serde::{Deserialize, Serialize}; -fn default() -> bool { - true -} - #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Frontend { #[serde(default = "PageProvider::default")] diff --git a/backend/src/settings/mod.rs b/backend/src/settings/mod.rs index 268e7d6c..adbae9c8 100644 --- a/backend/src/settings/mod.rs +++ b/backend/src/settings/mod.rs @@ -1,12 +1,11 @@ -use std::fs::create_dir_all; -use crate::settings::models::{EmailSetting, SecuritySettings, SiteSetting}; -use crate::Settings; +use std::path::PathBuf; -use std::path::{Path, PathBuf}; use tokio::fs::read_to_string; -pub mod models; +use crate::settings::models::{EmailSetting, SecuritySettings, SiteSetting}; +use crate::Settings; +pub mod models; pub async fn load_configs(configs: PathBuf) -> anyhow::Result { let security: SecuritySettings = diff --git a/backend/src/settings/models.rs b/backend/src/settings/models.rs index b13aafb3..4355af90 100644 --- a/backend/src/settings/models.rs +++ b/backend/src/settings/models.rs @@ -1,11 +1,9 @@ -use crate::error::internal_error::InternalError; - -use semver::{Error, Version}; -use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::fmt::{Display, Formatter}; + use sea_orm::ConnectOptions; -use sea_orm::DbErr::Conn; +use semver::{Error, Version}; +use serde::{Deserialize, Serialize}; #[derive(Debug, Deserialize, Serialize, Clone)] pub enum Mode { @@ -51,15 +49,13 @@ impl Default for Internal { #[derive(Debug, Deserialize, Serialize, Clone)] #[serde(tag = "type", content = "settings")] pub enum Database { - Mysql(MysqlSettings) + Mysql(MysqlSettings), } - +#[allow(clippy::from_over_into)] impl Into for Database { fn into(self) -> ConnectOptions { match self { - Database::Mysql(mysql) => { - ConnectOptions::new(mysql.to_string()) - } + Database::Mysql(mysql) => ConnectOptions::new(mysql.to_string()), } } } diff --git a/backend/src/storage/file.rs b/backend/src/storage/file.rs index 462087ab..7a4c8f71 100644 --- a/backend/src/storage/file.rs +++ b/backend/src/storage/file.rs @@ -1,18 +1,19 @@ -use crate::error::api_error::APIError; +use std::fs::{DirEntry, Metadata}; +use std::path::PathBuf; +use std::time::SystemTime; -use crate::storage::error::StorageError; use actix_files::NamedFile; use actix_web::body::BoxBody; use actix_web::http::header::ACCEPT; use actix_web::http::{Method, StatusCode}; use actix_web::{HttpRequest, HttpResponse, Responder, ResponseError}; -use log::error; +use log::{as_error, error}; use serde::Serialize; -use std::fs::{DirEntry, Metadata}; -use std::path::PathBuf; -use std::time::SystemTime; use tokio::fs::OpenOptions; +use crate::error::api_error::APIError; +use crate::storage::error::StorageError; + ///Storage Files are just a data container holding the file name, directory relative to the root of nitro_repo and if its a directory #[derive(Serialize, Clone, Debug)] pub struct StorageFile { @@ -29,7 +30,10 @@ impl StorageFile { fn meta_data(metadata: Metadata) -> (u128, u128, u64, bool) { let created = metadata .created() - .unwrap_or(SystemTime::now()) + .unwrap_or_else(|error| { + error!(error = as_error!(error); "Error getting created time"); + SystemTime::now() + }) .duration_since(SystemTime::UNIX_EPOCH) .unwrap() .as_micros(); diff --git a/backend/src/storage/models.rs b/backend/src/storage/models.rs index cb25119e..10aef31b 100644 --- a/backend/src/storage/models.rs +++ b/backend/src/storage/models.rs @@ -1,9 +1,7 @@ use std::fmt::{Debug, Display, Formatter}; -use serde::{Deserialize, Serialize}; - use async_trait::async_trait; - +use serde::{Deserialize, Serialize}; use serde_json::Value; use tokio::sync::RwLockReadGuard; @@ -73,7 +71,7 @@ pub struct StorageSaver { pub struct StorageConfig { pub public_name: String, pub name: String, - #[serde(default="crate::utils::get_current_time")] + #[serde(default = "crate::utils::get_current_time")] pub created: i64, } @@ -99,9 +97,7 @@ impl StorageFactory { impl StorageFactory { pub async fn build(self) -> Result { match &self.storage_type { - StorageType::LocalStorage => { - LocalStorage::new(self).map(|v| DynamicStorage::LocalStorage(v)) - } + StorageType::LocalStorage => LocalStorage::new(self).map(DynamicStorage::LocalStorage), } } } diff --git a/backend/src/storage/multi/mod.rs b/backend/src/storage/multi/mod.rs index d61256a7..1fcee255 100644 --- a/backend/src/storage/multi/mod.rs +++ b/backend/src/storage/multi/mod.rs @@ -1,24 +1,25 @@ -pub mod web; - -use log::{error, info}; use std::collections::HashMap; use std::path::{Path, PathBuf}; +use log::{error, info}; use tokio::fs; use tokio::fs::{read_to_string, OpenOptions}; - -use crate::storage::models::{ - Storage, StorageFactory, StorageSaver, StorageStatus, STORAGE_FILE, STORAGE_FILE_BAK, -}; +use tokio::io::AsyncWriteExt; +use tokio::sync::{RwLock, RwLockReadGuard}; use crate::storage::bad_storage::BadStorage; use crate::storage::error::StorageError; use crate::storage::file::StorageFile; +use crate::storage::models::{ + Storage, StorageFactory, StorageSaver, StorageStatus, STORAGE_FILE, STORAGE_FILE_BAK, +}; use crate::storage::DynamicStorage; -use tokio::io::AsyncWriteExt; -use tokio::sync::{RwLock, RwLockReadGuard}; -async fn load_storages(storages_file: PathBuf) -> Result, StorageError> { +pub mod web; + +async fn load_storages( + storages_file: PathBuf, +) -> Result, StorageError> { if !storages_file.exists() { return Ok(HashMap::new()); } diff --git a/backend/src/storage/multi/web/admin.rs b/backend/src/storage/multi/web/admin.rs index 805d0c3e..85aefd0e 100644 --- a/backend/src/storage/multi/web/admin.rs +++ b/backend/src/storage/multi/web/admin.rs @@ -1,19 +1,23 @@ -use actix_web::{get, HttpResponse, post, ResponseError, web}; use actix_web::http::StatusCode; +use actix_web::{get, post, web, HttpResponse, ResponseError}; use sea_orm::DatabaseConnection; -use serde_json::json; + use crate::authentication::Authentication; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; use crate::storage::error::StorageError; use crate::storage::models::StorageFactory; -use crate::storage::multi::{MultiStorageController}; -use crate::system::user::UserModel; +use crate::storage::multi::MultiStorageController; use crate::system::permissions::options::CanIDo; +use crate::system::user::UserModel; /// API handler for getting storages #[get("/storages")] -pub async fn get_storages(storage_handler: web::Data, database: web::Data, auth: Authentication) -> actix_web::Result { +pub async fn get_storages( + storage_handler: web::Data, + database: web::Data, + auth: Authentication, +) -> actix_web::Result { let user: UserModel = auth.get_user(&database).await??; user.can_i_edit_repos()?; @@ -21,15 +25,22 @@ pub async fn get_storages(storage_handler: web::Data, da } #[post("/storage/new")] -pub async fn new_storage(storage_handler: web::Data, new_storage: web::Json, database: web::Data, auth: Authentication) -> actix_web::Result { +pub async fn new_storage( + storage_handler: web::Data, + new_storage: web::Json, + database: web::Data, + auth: Authentication, +) -> actix_web::Result { let user: UserModel = auth.get_user(&database).await??; user.can_i_edit_repos()?; if let Err(error) = storage_handler.create_storage(new_storage.0).await { match error { - StorageError::StorageAlreadyExist => { - Ok(APIError::from(("Storage already exist", StatusCode::CONFLICT)).error_response()) - } - _ => { Err(InternalError::from(error).into()) } + StorageError::StorageAlreadyExist => Ok(APIError::from(( + "Storage already exist", + StatusCode::CONFLICT, + )) + .error_response()), + _ => Err(InternalError::from(error).into()), } } else { Ok(HttpResponse::Ok().finish()) diff --git a/backend/src/storage/multi/web/mod.rs b/backend/src/storage/multi/web/mod.rs index 8c74d271..e3162d70 100644 --- a/backend/src/storage/multi/web/mod.rs +++ b/backend/src/storage/multi/web/mod.rs @@ -4,4 +4,4 @@ pub mod admin; pub fn init_admin_routes(cfg: &mut ServiceConfig) { cfg.service(admin::get_storages).service(admin::new_storage); -} \ No newline at end of file +} diff --git a/backend/src/system/mod.rs b/backend/src/system/mod.rs index 4358e24a..df4a3aa9 100644 --- a/backend/src/system/mod.rs +++ b/backend/src/system/mod.rs @@ -1,6 +1,7 @@ -use argon2::{Argon2, PasswordHasher}; use argon2::password_hash::SaltString; +use argon2::{Argon2, PasswordHasher}; use rand_core::OsRng; + use crate::error::internal_error::InternalError; pub mod permissions; diff --git a/backend/src/system/permissions/mod.rs b/backend/src/system/permissions/mod.rs index 3c6d9584..7a63ec0c 100644 --- a/backend/src/system/permissions/mod.rs +++ b/backend/src/system/permissions/mod.rs @@ -1,12 +1,13 @@ -pub mod options; -pub mod orm; +use serde::{Deserialize, Serialize}; +use thiserror::Error; use crate::repository::data::RepositoryConfig; use crate::repository::settings::security::Visibility; use crate::repository::settings::Policy; use crate::system::permissions::PermissionError::{RepositoryClassifier, StorageClassifier}; -use serde::{Deserialize, Serialize}; -use thiserror::Error; + +pub mod options; +pub mod orm; #[derive(Error, Debug)] pub enum PermissionError { @@ -42,21 +43,13 @@ pub struct RepositoryPermission { pub permissions: Vec, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Default)] pub struct RepositoryPermissionValue { pub policy: Option, #[serde(rename = "type")] pub repo_type: Option, } -impl Default for RepositoryPermission { - fn default() -> Self { - RepositoryPermission { - permissions: vec![], - } - } -} - pub fn can_deploy( user_perms: &UserPermissions, repo: &RepositoryConfig, diff --git a/backend/src/system/permissions/options.rs b/backend/src/system/permissions/options.rs index 74230728..81897cfa 100644 --- a/backend/src/system/permissions/options.rs +++ b/backend/src/system/permissions/options.rs @@ -1,14 +1,14 @@ -use crate::system::permissions::{can_deploy, can_read, UserPermissions}; +use std::fmt; +use std::fmt::{Debug, Display, Formatter}; -use crate::error::internal_error::InternalError; -use crate::repository::settings::security::Visibility; -use crate::system::user::UserModel; use actix_web::http::StatusCode; use actix_web::ResponseError; -use std::fmt; -use std::fmt::{Debug, Display, Formatter}; +use crate::error::internal_error::InternalError; use crate::repository::data::RepositoryConfig; +use crate::repository::settings::security::Visibility; +use crate::system::permissions::{can_deploy, can_read}; +use crate::system::user::UserModel; pub struct MissingPermission(String); @@ -51,7 +51,7 @@ pub trait CanIDo { impl CanIDo for UserModel { fn can_i_edit_repos(&self) -> Result<(), MissingPermission> { - let permissions: UserPermissions = self.permissions.clone().try_into().unwrap(); + let permissions = &self.permissions; if !permissions.admin && !permissions.repository_manager { return Err("repository_manager".into()); @@ -60,7 +60,7 @@ impl CanIDo for UserModel { } fn can_i_edit_users(&self) -> Result<(), MissingPermission> { - let permissions: UserPermissions = self.permissions.clone().try_into().unwrap(); + let permissions = &self.permissions; if !permissions.admin && !permissions.user_manager { return Err("user_manager".into()); } @@ -68,7 +68,7 @@ impl CanIDo for UserModel { } fn can_i_admin(&self) -> Result<(), MissingPermission> { - let permissions: UserPermissions = self.permissions.clone().try_into().unwrap(); + let permissions = &self.permissions; if !permissions.admin { return Err("admin".into()); diff --git a/backend/src/system/web/mod.rs b/backend/src/system/web/mod.rs index b0303575..375711f4 100644 --- a/backend/src/system/web/mod.rs +++ b/backend/src/system/web/mod.rs @@ -1,8 +1,8 @@ +use actix_web::web::ServiceConfig; + pub mod public; pub mod user; -use actix_web::web::ServiceConfig; - pub fn init_public_routes(cfg: &mut ServiceConfig) { cfg.service(public::login); } @@ -11,4 +11,4 @@ pub fn user_routes(cfg: &mut ServiceConfig) { cfg.service(user::me); } -pub fn init_user_manager_routes(cfg: &mut ServiceConfig) {} \ No newline at end of file +pub fn init_user_manager_routes(_cfg: &mut ServiceConfig) {} diff --git a/backend/src/system/web/public.rs b/backend/src/system/web/public.rs index 6cae0e94..19bf38e4 100644 --- a/backend/src/system/web/public.rs +++ b/backend/src/system/web/public.rs @@ -1,13 +1,14 @@ -use actix_web::{HttpRequest, HttpResponse, HttpResponseBuilder, post}; use actix_web::cookie::Cookie; use actix_web::web; +use actix_web::{post, HttpRequest, HttpResponse}; use log::error; use sea_orm::DatabaseConnection; use serde::{Deserialize, Serialize}; + use crate::authentication::session::SessionManager; use crate::authentication::session::SessionManagerType; use crate::authentication::verify_login; -use crate::system::user::UserModel; + #[derive(Serialize, Deserialize, Clone, Debug)] pub struct Login { pub username: String, diff --git a/backend/src/system/web/user.rs b/backend/src/system/web/user.rs index 5223be73..d7f705fa 100644 --- a/backend/src/system/web/user.rs +++ b/backend/src/system/web/user.rs @@ -1,9 +1,9 @@ -use actix_web::{HttpRequest, HttpResponse, web}; -use actix_web::web::JsonBody; +use actix_web::get; +use actix_web::{web, HttpResponse}; use sea_orm::DatabaseConnection; + use crate::authentication::Authentication; use crate::system::user::UserModel; -use actix_web::get; #[get("/me")] pub async fn me( @@ -12,4 +12,4 @@ pub async fn me( ) -> actix_web::Result { let user: UserModel = auth.get_user(&database).await??; Ok(HttpResponse::Ok().json(user)) -} \ No newline at end of file +} diff --git a/backend/src/utils.rs b/backend/src/utils.rs index 971d2233..ea9c8673 100644 --- a/backend/src/utils.rs +++ b/backend/src/utils.rs @@ -7,7 +7,6 @@ use chrono::{DateTime, Duration, Local}; use nitro_log::config::Config; use nitro_log::{LoggerBuilders, NitroLogger}; use rust_embed::RustEmbed; -use serde::{Deserialize, Serialize}; use crate::error::internal_error::InternalError; use crate::settings::models::Mode; @@ -55,7 +54,6 @@ pub fn default_expiration() -> i64 { time.add(Duration::days(30)).timestamp_millis() } - pub fn get_accept(header_map: &HeaderMap) -> Result, InternalError> { let option = header_map.get("accept"); if option.is_none() { From 4f815cbe0613e384581ba513fbf392ca0a696d5b Mon Sep 17 00:00:00 2001 From: Wyatt Jacob Herkamp Date: Mon, 30 May 2022 10:26:39 -0400 Subject: [PATCH 04/76] More Storage Handlers --- backend/src/authentication/mod.rs | 21 +++++---- backend/src/bin/nitro_repo_full.rs | 7 ++- backend/src/error/handlers/json_error.rs | 6 +-- backend/src/install/mod.rs | 4 ++ backend/src/settings/models.rs | 2 + backend/src/storage/bad_storage.rs | 22 +++++---- backend/src/storage/error.rs | 4 ++ backend/src/storage/local_storage/mod.rs | 55 +++++++++++++++-------- backend/src/storage/mod.rs | 14 ++++-- backend/src/storage/models.rs | 5 +++ backend/src/storage/multi/web/admin.rs | 46 ++++++++++++++++++- backend/src/storage/multi/web/mod.rs | 5 ++- backend/src/system/permissions/options.rs | 9 +++- 13 files changed, 153 insertions(+), 47 deletions(-) diff --git a/backend/src/authentication/mod.rs b/backend/src/authentication/mod.rs index 287a75d7..d30fc24a 100644 --- a/backend/src/authentication/mod.rs +++ b/backend/src/authentication/mod.rs @@ -1,24 +1,25 @@ -pub mod auth_token; -pub mod middleware; -pub mod session; +use std::fmt; +use std::fmt::{Debug, Display, Formatter}; use actix_web::dev::Payload; use actix_web::http::StatusCode; use actix_web::{FromRequest, HttpMessage, HttpRequest, ResponseError}; use argon2::{Argon2, PasswordHash, PasswordVerifier}; -use std::fmt::{Debug, Display, Formatter}; - use futures_util::future::{ready, Ready}; use log::trace; - use sea_orm::{DatabaseConnection, EntityTrait}; +use serde_json::json; use crate::authentication::auth_token::AuthTokenModel; use crate::authentication::session::Session; use crate::error::internal_error::InternalError; use crate::system::user; - use crate::system::user::{UserEntity, UserModel}; + +pub mod auth_token; +pub mod middleware; +pub mod session; + pub struct NotAuthenticated; impl Debug for NotAuthenticated { @@ -29,7 +30,11 @@ impl Debug for NotAuthenticated { impl Display for NotAuthenticated { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "Not Authenticated") + let result = serde_json::to_string(&json!({ + "error": "Not Authenticated", + })) + .map_err(|_| fmt::Error)?; + write!(f, "{}", result) } } diff --git a/backend/src/bin/nitro_repo_full.rs b/backend/src/bin/nitro_repo_full.rs index b16b285a..29b8b478 100644 --- a/backend/src/bin/nitro_repo_full.rs +++ b/backend/src/bin/nitro_repo_full.rs @@ -1,10 +1,11 @@ -use std::env::current_dir; +use std::env::{current_dir, set_var}; use std::error::Error; use std::io::ErrorKind; use std::process::exit; use actix_cors::Cors; use actix_web::main; +use actix_web::middleware::DefaultHeaders; use actix_web::web::{Data, PayloadConfig}; use actix_web::{web, App, HttpServer}; use log::info; @@ -64,7 +65,7 @@ async fn main() -> std::io::Result<()> { }; let application = nitro_repo.core.application.clone(); - + set_var("STORAGE_LOCATION", &application.storage_location); let max_upload = Data::new(PayloadConfig::default().limit(application.max_upload)); let address = application.address.clone(); @@ -80,6 +81,7 @@ async fn main() -> std::io::Result<()> { .app_data(database_data.clone()) .app_data(session_data.clone()) .app_data(max_upload.clone()) + .wrap(DefaultHeaders::new().add(("X-Powered-By", "Nitro Repo powered by Actix.rs"))) .wrap( Cors::default() .allow_any_header() @@ -89,6 +91,7 @@ async fn main() -> std::io::Result<()> { ) .service( web::scope("/api") + .wrap(DefaultHeaders::new().add(("Content-Type", "application/json"))) .wrap(HandleSession {}) .configure(system::web::init_public_routes) .configure(system::web::user_routes) diff --git a/backend/src/error/handlers/json_error.rs b/backend/src/error/handlers/json_error.rs index c9ba76ca..7c13c144 100644 --- a/backend/src/error/handlers/json_error.rs +++ b/backend/src/error/handlers/json_error.rs @@ -1,13 +1,13 @@ use actix_web::error::{ErrorBadRequest, JsonPayloadError}; use actix_web::web::JsonConfig; use actix_web::HttpRequest; -use log::trace; +use log::{as_serde, warn}; pub fn json_config() -> JsonConfig { JsonConfig::default().error_handler(handle) } -pub fn handle(payload: JsonPayloadError, _request: &HttpRequest) -> actix_web::Error { - trace!("JSON Error: {}", payload); +pub fn handle(payload: JsonPayloadError, request: &HttpRequest) -> actix_web::Error { + warn!("JSON Error: {}. Path: {}", payload, request.path()); ErrorBadRequest(format!("Bad Json Payload {}", payload)) } diff --git a/backend/src/install/mod.rs b/backend/src/install/mod.rs index 14c221c9..3a33059c 100644 --- a/backend/src/install/mod.rs +++ b/backend/src/install/mod.rs @@ -1,3 +1,4 @@ +use std::env::current_dir; use std::fmt::{Display, Formatter}; use std::fs::{create_dir_all, OpenOptions}; use std::io; @@ -8,6 +9,7 @@ use crossterm::{ event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, execute, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, + ExecutableCommand, }; use log::{error, info, trace}; use sea_orm::ActiveValue::Set; @@ -135,12 +137,14 @@ pub struct OtherStage { impl From for Application { fn from(other: OtherStage) -> Self { + let storages = current_dir().unwrap().join("storages"); Self { log: other.log_location.unwrap(), address: other.address.unwrap(), app_url: other.app_url.unwrap(), max_upload: other.max_upload.unwrap().parse().unwrap(), mode: Mode::Release, + storage_location: storages, ssl_private_key: None, ssl_cert_key: None, } diff --git a/backend/src/settings/models.rs b/backend/src/settings/models.rs index 4355af90..bfcbb961 100644 --- a/backend/src/settings/models.rs +++ b/backend/src/settings/models.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; use std::fmt::{Display, Formatter}; +use std::path::PathBuf; use sea_orm::ConnectOptions; use semver::{Error, Version}; @@ -87,6 +88,7 @@ pub struct Application { pub app_url: String, pub max_upload: usize, pub mode: Mode, + pub storage_location: PathBuf, pub ssl_private_key: Option, pub ssl_cert_key: Option, } diff --git a/backend/src/storage/bad_storage.rs b/backend/src/storage/bad_storage.rs index 11fdcf7b..aa05b506 100644 --- a/backend/src/storage/bad_storage.rs +++ b/backend/src/storage/bad_storage.rs @@ -1,17 +1,14 @@ -use crate::storage::models::{ - Storage, StorageConfig, StorageFactory, StorageSaver, StorageStatus, StorageType, -}; - +use async_trait::async_trait; use log::warn; +use serde_json::Value; +use tokio::sync::RwLockReadGuard; use crate::repository::data::{RepositoryConfig, RepositoryType}; use crate::storage::error::StorageError; -use async_trait::async_trait; - -use serde_json::Value; - use crate::storage::file::{StorageFile, StorageFileResponse}; -use tokio::sync::RwLockReadGuard; +use crate::storage::models::{ + Storage, StorageConfig, StorageFactory, StorageSaver, StorageStatus, StorageType, +}; /// This is a storage that is here to represent a storage that failed to load from the config stage #[derive(Debug)] @@ -29,6 +26,13 @@ impl BadStorage { } #[async_trait] impl Storage for BadStorage { + fn create_new(config: StorageFactory) -> Result + where + Self: Sized, + { + panic!("Illegal Call") + } + fn new(_: StorageFactory) -> Result where Self: Sized, diff --git a/backend/src/storage/error.rs b/backend/src/storage/error.rs index e23c776c..1c453add 100644 --- a/backend/src/storage/error.rs +++ b/backend/src/storage/error.rs @@ -1,4 +1,6 @@ use std::time::SystemTimeError; + +use actix_web::ResponseError; use thiserror::Error; #[derive(Error, Debug)] @@ -11,6 +13,8 @@ pub enum StorageError { JSONError(serde_json::Error), #[error("Storage Already Exists!")] StorageAlreadyExist, + #[error("Unable to create a new storage {0}")] + StorageCreateError(String), #[error("Repository Already Exists")] RepositoryAlreadyExists, #[error("Missing Repository")] diff --git a/backend/src/storage/local_storage/mod.rs b/backend/src/storage/local_storage/mod.rs index 6c531f64..d6cfcfad 100644 --- a/backend/src/storage/local_storage/mod.rs +++ b/backend/src/storage/local_storage/mod.rs @@ -1,28 +1,25 @@ -use crate::repository::REPOSITORY_CONF_FOLDER; -use crate::storage::models::{ - Storage, StorageConfig, StorageFactory, StorageSaver, StorageStatus, StorageType, -}; -use crate::storage::STORAGE_CONFIG; -use crate::utils::get_current_time; - -use log::{debug, trace, warn}; -use serde::{Deserialize, Serialize}; use std::collections::HashMap; - use std::path::PathBuf; -use crate::repository::data::{RepositoryConfig, RepositoryType}; -use crate::storage::error::StorageError; -use crate::storage::error::StorageError::RepositoryMissing; use async_trait::async_trait; - +use log::{debug, trace, warn}; +use serde::{Deserialize, Serialize}; use serde_json::Value; - -use crate::storage::file::{StorageDirectoryResponse, StorageFile, StorageFileResponse}; use tokio::fs::{create_dir, create_dir_all, read_to_string, remove_dir, remove_file, OpenOptions}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::sync::{RwLock, RwLockReadGuard}; +use crate::repository::data::{RepositoryConfig, RepositoryType}; +use crate::repository::REPOSITORY_CONF_FOLDER; +use crate::storage::error::StorageError; +use crate::storage::error::StorageError::RepositoryMissing; +use crate::storage::file::{StorageDirectoryResponse, StorageFile, StorageFileResponse}; +use crate::storage::models::{ + Storage, StorageConfig, StorageFactory, StorageSaver, StorageStatus, StorageType, +}; +use crate::storage::STORAGE_CONFIG; +use crate::utils::get_current_time; + #[derive(Debug)] pub struct LocalStorage { pub config: LocalConfig, @@ -33,7 +30,7 @@ pub struct LocalStorage { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct LocalConfig { - pub location: String, + pub location: PathBuf, } pub struct LocalFile { @@ -42,7 +39,7 @@ pub struct LocalFile { impl LocalStorage { pub fn get_storage_folder(&self) -> PathBuf { - PathBuf::from(&self.config.location) + self.config.location.clone() } pub fn get_repository_folder(&self, repository: &str) -> PathBuf { self.get_storage_folder().join(repository) @@ -82,6 +79,28 @@ impl LocalStorage { #[async_trait] impl Storage for LocalStorage { + fn create_new(config: StorageFactory) -> Result + where + Self: Sized, + { + let string = std::env::var("STORAGE_LOCATION").map_err(|e| { + ( + StorageError::StorageCreateError(e.to_string()), + config.clone(), + ) + })?; + let location = PathBuf::from(&string); + let local_config = LocalConfig { + location: location.join(&config.generic_config.name), + }; + Ok(LocalStorage { + config: local_config, + storage_config: config.generic_config, + status: StorageStatus::Unloaded, + repositories: RwLock::new(HashMap::new()), + }) + } + fn new(config: StorageFactory) -> Result where Self: Sized, diff --git a/backend/src/storage/mod.rs b/backend/src/storage/mod.rs index adec4fc2..54cb5150 100644 --- a/backend/src/storage/mod.rs +++ b/backend/src/storage/mod.rs @@ -1,3 +1,7 @@ +use async_trait::async_trait; +use serde_json::Value; +use tokio::sync::RwLockReadGuard; + use crate::repository::data::{RepositoryConfig, RepositoryType}; use crate::storage::bad_storage::BadStorage; use crate::storage::error::StorageError; @@ -6,9 +10,6 @@ use crate::storage::local_storage::LocalStorage; use crate::storage::models::{ Storage, StorageConfig, StorageFactory, StorageSaver, StorageStatus, StorageType, }; -use async_trait::async_trait; -use serde_json::Value; -use tokio::sync::RwLockReadGuard; pub mod bad_storage; pub mod error; @@ -28,6 +29,13 @@ pub enum DynamicStorage { #[async_trait] impl Storage for DynamicStorage { + fn create_new(config: StorageFactory) -> Result + where + Self: Sized, + { + panic!("Illegal Call") + } + fn new(_config: StorageFactory) -> Result where Self: Sized, diff --git a/backend/src/storage/models.rs b/backend/src/storage/models.rs index 10aef31b..c3506733 100644 --- a/backend/src/storage/models.rs +++ b/backend/src/storage/models.rs @@ -81,6 +81,7 @@ pub struct StorageFactory { #[serde(flatten)] pub generic_config: StorageConfig, /// Storage Handler Config + #[serde(default)] pub handler_config: Value, } @@ -105,6 +106,10 @@ impl StorageFactory { #[async_trait] pub trait Storage: Send + Sync { /// Initialize the Storage at Storage start. + fn create_new(config: StorageFactory) -> Result + where + Self: Sized; + /// Initialize the Storage at Storage start. fn new(config: StorageFactory) -> Result where Self: Sized; diff --git a/backend/src/storage/multi/web/admin.rs b/backend/src/storage/multi/web/admin.rs index 85aefd0e..f3c3c522 100644 --- a/backend/src/storage/multi/web/admin.rs +++ b/backend/src/storage/multi/web/admin.rs @@ -1,11 +1,12 @@ use actix_web::http::StatusCode; -use actix_web::{get, post, web, HttpResponse, ResponseError}; +use actix_web::{delete, get, post, web, HttpResponse, ResponseError}; use sea_orm::DatabaseConnection; use crate::authentication::Authentication; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; use crate::storage::error::StorageError; +use crate::storage::models::Storage; use crate::storage::models::StorageFactory; use crate::storage::multi::MultiStorageController; use crate::system::permissions::options::CanIDo; @@ -24,6 +25,7 @@ pub async fn get_storages( Ok(HttpResponse::Ok().json(storage_handler.storage_savers().await)) } +/// Creates a new storage based on the Storage Factory #[post("/storage/new")] pub async fn new_storage( storage_handler: web::Data, @@ -46,3 +48,45 @@ pub async fn new_storage( Ok(HttpResponse::Ok().finish()) } } + +/// Delete the storage based on the name +#[delete("/storage/{name}")] +pub async fn delete_storage( + storage_handler: web::Data, + database: web::Data, + auth: Authentication, + name: web::Path, +) -> actix_web::Result { + let user: UserModel = auth.get_user(&database).await??; + user.can_i_edit_repos()?; + if storage_handler + .delete_storage(&name.into_inner()) + .await + .map_err(|error| InternalError::from(error))? + { + Ok(HttpResponse::Ok().finish()) + } else { + Ok(APIError::from(("Storage does not exist", StatusCode::NOT_FOUND)).error_response()) + } +} + +/// Gets the storage based on the name +#[get("/storage/{name}")] +pub async fn get_storage( + storage_handler: web::Data, + name: web::Path, + database: web::Data, + auth: Authentication, +) -> actix_web::Result { + let user: UserModel = auth.get_user(&database).await??; + user.can_i_edit_repos()?; + if let Some(storage) = storage_handler + .get_storage_by_name(&name.into_inner()) + .await + .map_err(|e| InternalError::from(e))? + { + Ok(HttpResponse::Ok().json(storage.config_for_saving())) + } else { + Ok(APIError::from(("Storage not found", StatusCode::NOT_FOUND)).error_response()) + } +} diff --git a/backend/src/storage/multi/web/mod.rs b/backend/src/storage/multi/web/mod.rs index e3162d70..b4aeb68e 100644 --- a/backend/src/storage/multi/web/mod.rs +++ b/backend/src/storage/multi/web/mod.rs @@ -3,5 +3,8 @@ use actix_web::web::ServiceConfig; pub mod admin; pub fn init_admin_routes(cfg: &mut ServiceConfig) { - cfg.service(admin::get_storages).service(admin::new_storage); + cfg.service(admin::get_storages) + .service(admin::new_storage) + .service(admin::delete_storage) + .service(admin::get_storage); } diff --git a/backend/src/system/permissions/options.rs b/backend/src/system/permissions/options.rs index 81897cfa..210ab4a2 100644 --- a/backend/src/system/permissions/options.rs +++ b/backend/src/system/permissions/options.rs @@ -3,7 +3,9 @@ use std::fmt::{Debug, Display, Formatter}; use actix_web::http::StatusCode; use actix_web::ResponseError; +use serde_json::json; +use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; use crate::repository::data::RepositoryConfig; use crate::repository::settings::security::Visibility; @@ -20,7 +22,11 @@ impl Debug for MissingPermission { impl Display for MissingPermission { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "Forbidden: Missing Permission {}", &self.0) + let result = serde_json::to_string(&json!({ + "error": format!("Missing Permission {}", &self.0), + })) + .map_err(|_| fmt::Error)?; + write!(f, "{}", result) } } @@ -48,7 +54,6 @@ pub trait CanIDo { repo: &RepositoryConfig, ) -> Result, InternalError>; } - impl CanIDo for UserModel { fn can_i_edit_repos(&self) -> Result<(), MissingPermission> { let permissions = &self.permissions; From c4b716d261f487d1b462ad75cb5f6df57df4ffb4 Mon Sep 17 00:00:00 2001 From: Wyatt Jacob Herkamp Date: Mon, 30 May 2022 13:11:52 -0400 Subject: [PATCH 05/76] Repository basic Create, Delete, Get, and List --- backend/src/error/api_error.rs | 10 +- backend/src/error/handlers/json_error.rs | 2 +- backend/src/repository/mod.rs | 1 + backend/src/repository/settings/mod.rs | 22 ---- backend/src/repository/web/mod.rs | 30 +++++ backend/src/repository/web/multi/admin.rs | 151 ++++++++++++++++++++++ backend/src/repository/web/multi/mod.rs | 1 + 7 files changed, 185 insertions(+), 32 deletions(-) create mode 100644 backend/src/repository/web/mod.rs create mode 100644 backend/src/repository/web/multi/admin.rs create mode 100644 backend/src/repository/web/multi/mod.rs diff --git a/backend/src/error/api_error.rs b/backend/src/error/api_error.rs index 7e1780dc..ddeca677 100644 --- a/backend/src/error/api_error.rs +++ b/backend/src/error/api_error.rs @@ -6,6 +6,7 @@ use actix_web::http::StatusCode; use actix_web::{HttpResponse, HttpResponseBuilder, ResponseError}; use serde_json::json; +#[derive(Debug)] pub struct APIError { pub message: Option, pub status_code: StatusCode, @@ -38,15 +39,6 @@ impl From<(&str, StatusCode)> for APIError { } } } -impl Debug for APIError { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - if let Some(message) = &self.message { - write!(f, "Status Code: {} Error: {}", self.status_code, message) - } else { - write!(f, "Status Code: {}", self.status_code,) - } - } -} impl Display for APIError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { diff --git a/backend/src/error/handlers/json_error.rs b/backend/src/error/handlers/json_error.rs index 7c13c144..4e9deed7 100644 --- a/backend/src/error/handlers/json_error.rs +++ b/backend/src/error/handlers/json_error.rs @@ -1,7 +1,7 @@ use actix_web::error::{ErrorBadRequest, JsonPayloadError}; use actix_web::web::JsonConfig; use actix_web::HttpRequest; -use log::{as_serde, warn}; +use log::warn; pub fn json_config() -> JsonConfig { JsonConfig::default().error_handler(handle) diff --git a/backend/src/repository/mod.rs b/backend/src/repository/mod.rs index 719134fb..32d74a89 100644 --- a/backend/src/repository/mod.rs +++ b/backend/src/repository/mod.rs @@ -6,6 +6,7 @@ pub mod nitro; pub mod npm; pub mod response; pub mod settings; +pub mod web; pub static REPOSITORY_CONF: &str = "repository.nitro_repo"; pub static REPOSITORY_CONF_FOLDER: &str = ".config.nitro_repo"; diff --git a/backend/src/repository/settings/mod.rs b/backend/src/repository/settings/mod.rs index 9f7c4ff2..5b355f96 100644 --- a/backend/src/repository/settings/mod.rs +++ b/backend/src/repository/settings/mod.rs @@ -1,4 +1,3 @@ -use crate::repository::settings::frontend::{BadgeSettings, Frontend}; use serde::{Deserialize, Serialize}; pub mod frontend; @@ -20,24 +19,3 @@ impl Default for Policy { Policy::Mixed } } - -#[derive(Debug, Deserialize, Serialize, Clone)] -pub struct RepositorySettings { - #[serde(default)] - pub frontend: Frontend, - #[serde(default)] - pub badge: BadgeSettings, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct UpdateFrontend { - pub frontend: Frontend, - pub badge: BadgeSettings, -} - -impl RepositorySettings { - pub fn update_frontend(&mut self, settings: UpdateFrontend) { - self.frontend = settings.frontend; - self.badge = settings.badge; - } -} diff --git a/backend/src/repository/web/mod.rs b/backend/src/repository/web/mod.rs new file mode 100644 index 00000000..0778437b --- /dev/null +++ b/backend/src/repository/web/mod.rs @@ -0,0 +1,30 @@ +use serde::Serialize; + +use crate::error::internal_error::InternalError; +use crate::repository::data::RepositoryConfig; +use crate::repository::settings::frontend::{BadgeSettings, Frontend}; +use crate::storage::models::Storage; + +pub mod multi; + +#[derive(Serialize, Debug)] +pub struct RepositoryResponse<'a> { + pub config: &'a RepositoryConfig, + pub frontend: Option, + pub badge: Option, +} + +impl<'a> RepositoryResponse<'a> { + pub async fn new( + config: &'a RepositoryConfig, + storage: &dyn Storage, + ) -> Result, InternalError> { + let frontend = config.get_frontend_config(storage).await?; + let badge: Option = None; + Ok(RepositoryResponse { + config, + frontend, + badge, + }) + } +} diff --git a/backend/src/repository/web/multi/admin.rs b/backend/src/repository/web/multi/admin.rs new file mode 100644 index 00000000..585f5199 --- /dev/null +++ b/backend/src/repository/web/multi/admin.rs @@ -0,0 +1,151 @@ +use std::ops::Deref; + +use actix_web::http::StatusCode; +use actix_web::{delete, get, post, web, HttpRequest, HttpResponse, ResponseError}; +use sea_orm::DatabaseConnection; +use serde::Deserialize; + +use crate::authentication::Authentication; +use crate::error::api_error::APIError; +use crate::error::internal_error::InternalError; +use crate::repository::data::RepositoryType; +use crate::repository::web::RepositoryResponse; +use crate::storage::error::StorageError; +use crate::storage::models::Storage; +use crate::storage::models::StorageFactory; +use crate::storage::multi::MultiStorageController; +use crate::system::permissions::options::CanIDo; +use crate::system::user::UserModel; + +/// Get all repositories from the storage +#[get("/repositories/{storage_name}")] +pub async fn get_repositories( + storage_handler: web::Data, + database: web::Data, + auth: Authentication, + storage_name: web::Path, +) -> actix_web::Result { + let user: UserModel = auth.get_user(&database).await??; + user.can_i_edit_repos()?; + + let storage = storage_handler + .get_storage_by_name(&storage_name.into_inner()) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::from(("Storage not found", StatusCode::NOT_FOUND)))?; + + Ok(HttpResponse::Ok().json( + storage + .get_repositories() + .await + .map_err(InternalError::from)?, + )) +} + +/// Create a new repository +#[post("/repositories/{storage_name}/new/{repository_name}/{repository_type}")] +pub async fn create_repository( + storage_handler: web::Data, + database: web::Data, + auth: Authentication, + storage_name: web::Path, + query_params: web::Path<(String, RepositoryType)>, +) -> actix_web::Result { + let user: UserModel = auth.get_user(&database).await??; + user.can_i_edit_repos()?; + + let storage = storage_handler + .get_storage_by_name(&storage_name.into_inner()) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::from(("Storage not found", StatusCode::NOT_FOUND)))?; + + let (repository_name, repository_type) = query_params.into_inner(); + + if let Err(error) = storage + .create_repository(repository_name, repository_type) + .await + { + return match error { + StorageError::RepositoryAlreadyExists => { + Err(APIError::from(("Repository already exists", StatusCode::CONFLICT)).into()) + } + value => Err(InternalError::from(value).into()), + }; + } + + Ok(HttpResponse::NoContent().finish()) +} + +#[derive(Deserialize)] +pub struct GetRepositoryQuery { + #[serde(default)] + pub all_info: bool, +} + +/// Get a repository by the name and storage name +/// If the query param all_info is present. It will include other repository configs such as Frontend and Badge +#[get("/repositories/{storage_name}/{repository_name}")] +pub async fn get_repository( + storage_handler: web::Data, + database: web::Data, + auth: Authentication, + path_params: web::Path<(String, String)>, + query_params: web::Query, +) -> actix_web::Result { + let user: UserModel = auth.get_user(&database).await??; + user.can_i_edit_repos()?; + let (storage_name, repository_name) = path_params.into_inner(); + let storage = storage_handler + .get_storage_by_name(&storage_name) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::from(("Storage not found", StatusCode::NOT_FOUND)))?; + let repository = storage + .get_repository(&repository_name) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::from(("Repository not found", StatusCode::NOT_FOUND)))?; + // Check if the query param contains all_info + if query_params.all_info { + //Generate a RepositoryResponse + let response = RepositoryResponse::new(&repository, storage.deref()).await?; + Ok(HttpResponse::Ok().json(response)) + } else { + Ok(HttpResponse::Ok().json(repository.deref())) + } +} + +#[derive(Deserialize)] +pub struct DeleteRepositoryQuery { + #[serde(default)] + pub purge_repository: bool, +} + +#[delete("/repositories/{storage_name}/{repository_name}")] +pub async fn delete_repository( + storage_handler: web::Data, + database: web::Data, + auth: Authentication, + path_params: web::Path<(String, String)>, + query_params: web::Query, +) -> actix_web::Result { + let user: UserModel = auth.get_user(&database).await??; + user.can_i_edit_repos()?; + let (storage_name, repository_name) = path_params.into_inner(); + let storage = storage_handler + .get_storage_by_name(&storage_name) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::from(("Storage not found", StatusCode::NOT_FOUND)))?; + let repository = storage + .get_repository(&repository_name) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::from(("Repository not found", StatusCode::NOT_FOUND)))?; + storage + .delete_repository(&repository, query_params.purge_repository) + .await + .map_err(InternalError::from)?; + Ok(HttpResponse::NoContent().finish()) +} diff --git a/backend/src/repository/web/multi/mod.rs b/backend/src/repository/web/multi/mod.rs new file mode 100644 index 00000000..92918b09 --- /dev/null +++ b/backend/src/repository/web/multi/mod.rs @@ -0,0 +1 @@ +pub mod admin; From a59b7cb6e8f2e0505f8ddc88345b890061e6e6bc Mon Sep 17 00:00:00 2001 From: Wyatt Jacob Herkamp Date: Mon, 30 May 2022 15:28:09 -0400 Subject: [PATCH 06/76] handler building --- backend/src/repository/handler.rs | 8 +-- backend/src/repository/maven/mod.rs | 36 +++++------- backend/src/repository/mod.rs | 34 +++++++++++ .../src/repository/nitro/nitro_repository.rs | 14 ++--- backend/src/repository/nitro/utils.rs | 30 +++++----- backend/src/repository/npm/mod.rs | 58 +++++++++---------- backend/src/repository/npm/utils.rs | 15 ++--- 7 files changed, 109 insertions(+), 86 deletions(-) diff --git a/backend/src/repository/handler.rs b/backend/src/repository/handler.rs index 5930e5ca..32245d11 100644 --- a/backend/src/repository/handler.rs +++ b/backend/src/repository/handler.rs @@ -1,16 +1,16 @@ -use crate::authentication::Authentication; use actix_web::http::header::HeaderMap; use actix_web::http::StatusCode; use actix_web::web::Bytes; - -use crate::error::api_error::APIError; use async_trait::async_trait; use sea_orm::DatabaseConnection; +use crate::authentication::Authentication; +use crate::error::api_error::APIError; use crate::repository::response::RepoResponse; +use crate::storage::models::Storage; #[async_trait] -pub trait RepositoryHandler<'a>: Send + Sync { +pub trait RepositoryHandler<'a, S: Storage>: Send + Sync { /// Handles a get request to a Repo async fn handle_get( &self, diff --git a/backend/src/repository/maven/mod.rs b/backend/src/repository/maven/mod.rs index 2ecdee75..648a3f74 100644 --- a/backend/src/repository/maven/mod.rs +++ b/backend/src/repository/maven/mod.rs @@ -1,45 +1,41 @@ use actix_web::http::header::HeaderMap; use actix_web::http::StatusCode; use actix_web::web::Bytes; - +use async_trait::async_trait; use log::error; use sea_orm::DatabaseConnection; - -use crate::repository::maven::models::Pom; -use crate::repository::settings::security::Visibility; -use crate::repository::settings::Policy; +use tokio::sync::RwLockReadGuard; use crate::authentication::Authentication; +use crate::error::api_error::APIError; +use crate::error::internal_error::InternalError; use crate::repository::data::RepositoryConfig; use crate::repository::handler::RepositoryHandler; +use crate::repository::maven::models::Pom; use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; - -use crate::error::api_error::APIError; -use crate::error::internal_error::InternalError; use crate::repository::response::RepoResponse; +use crate::repository::settings::security::Visibility; +use crate::repository::settings::Policy; use crate::storage::file::StorageFileResponse; use crate::storage::models::Storage; +use crate::storage::DynamicStorage; use crate::system::permissions::options::CanIDo; use crate::system::user::UserModel; -use async_trait::async_trait; - -use crate::storage::DynamicStorage; -use tokio::sync::RwLockReadGuard; pub mod error; pub mod models; mod utils; -pub struct MavenHandler<'a> { +pub struct MavenHandler<'a, S: Storage> { config: RepositoryConfig, - storage: RwLockReadGuard<'a, DynamicStorage>, + storage: RwLockReadGuard<'a, S>, } -impl<'a> MavenHandler<'a> { +impl<'a, S: Storage> MavenHandler<'a, S> { pub fn create( repository: RepositoryConfig, - storage: RwLockReadGuard<'a, DynamicStorage>, - ) -> MavenHandler<'a> { + storage: RwLockReadGuard<'a, S>, + ) -> MavenHandler<'a, S> { MavenHandler::<'a> { config: repository, storage, @@ -48,7 +44,7 @@ impl<'a> MavenHandler<'a> { } #[async_trait] -impl<'a> RepositoryHandler<'a> for MavenHandler<'a> { +impl<'a, S: Storage> RepositoryHandler<'a, S> for MavenHandler<'a, S> { async fn handle_get( &self, path: &str, @@ -142,12 +138,12 @@ impl<'a> RepositoryHandler<'a> for MavenHandler<'a> { } } -impl NitroRepositoryHandler for MavenHandler<'_> { +impl NitroRepositoryHandler for MavenHandler<'_, StorageType> { fn parse_project_to_directory>(value: S) -> String { value.into().replace('.', "/").replace(':', "/") } - fn storage(&self) -> &DynamicStorage { + fn storage(&self) -> &StorageType { &self.storage } diff --git a/backend/src/repository/mod.rs b/backend/src/repository/mod.rs index 32d74a89..1eb90cba 100644 --- a/backend/src/repository/mod.rs +++ b/backend/src/repository/mod.rs @@ -1,3 +1,16 @@ +use std::ops::Deref; + +use futures_util::TryFutureExt; +use tokio::sync::RwLockReadGuard; + +use crate::error::api_error::APIError; +use crate::error::internal_error::InternalError; +use crate::repository::data::{RepositoryConfig, RepositoryType}; +use crate::repository::handler::RepositoryHandler; +use crate::repository::maven::MavenHandler; +use crate::repository::npm::NPMHandler; +use crate::storage::models::Storage; + pub mod data; pub mod frontend; pub mod handler; @@ -11,3 +24,24 @@ pub mod web; pub static REPOSITORY_CONF: &str = "repository.nitro_repo"; pub static REPOSITORY_CONF_FOLDER: &str = ".config.nitro_repo"; pub static REPOSITORY_CONF_BAK: &str = "repository.nitro_repo.bak"; + +pub async fn get_repository_handler<'a, StorageType: Storage>( + storage: RwLockReadGuard<'a, StorageType>, + repository: &str, +) -> Result + 'a>>, InternalError> { + let value = storage.get_repository(repository).await?; + if value.is_none() { + return Ok(None); + } + let repository_config = value.unwrap().deref().clone(); + match repository_config.repository_type { + RepositoryType::Maven => Ok(Some(Box::new(MavenHandler::create( + repository_config, + storage, + )))), + RepositoryType::NPM => Ok(Some(Box::new(NPMHandler::create( + repository_config, + storage, + )))), + } +} diff --git a/backend/src/repository/nitro/nitro_repository.rs b/backend/src/repository/nitro/nitro_repository.rs index 31fb4ab0..b558ff11 100644 --- a/backend/src/repository/nitro/nitro_repository.rs +++ b/backend/src/repository/nitro/nitro_repository.rs @@ -1,13 +1,9 @@ -use crate::repository::response::Project; -use crate::storage::models::Storage; - -use crate::constants::{PROJECT_FILE, VERSION_DATA}; -use crate::error::internal_error::InternalError; use async_trait::async_trait; use log::{debug, error, trace}; +use crate::constants::{PROJECT_FILE, VERSION_DATA}; +use crate::error::internal_error::InternalError; use crate::repository::data::RepositoryConfig; - use crate::repository::nitro::utils::{ get_project_data, get_version_data, get_versions, update_project_in_repositories, }; @@ -15,14 +11,16 @@ use crate::repository::nitro::{ NitroFile, NitroFileResponse, NitroFileResponseType, NitroRepoVersions, ProjectData, VersionData, }; +use crate::repository::response::Project; use crate::storage::file::StorageDirectoryResponse; +use crate::storage::models::Storage; use crate::storage::DynamicStorage; use crate::system::user::UserModel; #[async_trait] -pub trait NitroRepositoryHandler { +pub trait NitroRepositoryHandler { fn parse_project_to_directory>(value: S) -> String; - fn storage(&self) -> &DynamicStorage; + fn storage(&self) -> &StorageType; fn repository(&self) -> &RepositoryConfig; /// Handles a List of versions request async fn get_versions( diff --git a/backend/src/repository/nitro/utils.rs b/backend/src/repository/nitro/utils.rs index a43c9803..bf947d09 100644 --- a/backend/src/repository/nitro/utils.rs +++ b/backend/src/repository/nitro/utils.rs @@ -1,17 +1,18 @@ +use std::fs::read_to_string; +use std::path::Path; + +use log::debug; + use crate::constants::{PROJECTS_FILE, PROJECT_FILE, VERSION_DATA}; use crate::error::internal_error::InternalError; use crate::repository::data::RepositoryConfig; use crate::repository::nitro::{NitroRepoVersions, ProjectData, RepositoryListing, VersionData}; use crate::repository::response::VersionResponse; - use crate::storage::models::Storage; use crate::storage::DynamicStorage; -use log::debug; -use std::fs::read_to_string; -use std::path::Path; -pub async fn get_version( - storage: &DynamicStorage, +pub async fn get_version( + storage: &StorageType, repository: &RepositoryConfig, project: String, version: String, @@ -35,8 +36,8 @@ pub fn get_version_by_data( None } -pub async fn update_project_in_repositories( - storage: &DynamicStorage, +pub async fn update_project_in_repositories( + storage: &StorageType, repository: &RepositoryConfig, project: String, ) -> Result<(), InternalError> { @@ -57,8 +58,8 @@ pub async fn update_project_in_repositories( Ok(()) } -pub async fn get_versions( - storage: &DynamicStorage, +pub async fn get_versions( + storage: &StorageType, repository: &RepositoryConfig, path: String, ) -> Result { @@ -94,8 +95,8 @@ pub fn get_latest_version_data( } } -pub async fn get_project_data( - storage: &DynamicStorage, +pub async fn get_project_data( + storage: &StorageType, repository: &RepositoryConfig, project: &str, ) -> Result, InternalError> { @@ -112,8 +113,9 @@ pub async fn get_project_data( None }) } -pub async fn get_version_data( - storage: &DynamicStorage, + +pub async fn get_version_data( + storage: &StorageType, repository: &RepositoryConfig, folder: &str, ) -> Result, InternalError> { diff --git a/backend/src/repository/npm/mod.rs b/backend/src/repository/npm/mod.rs index 97aad2dd..3e8e5a49 100644 --- a/backend/src/repository/npm/mod.rs +++ b/backend/src/repository/npm/mod.rs @@ -1,22 +1,27 @@ use std::collections::HashMap; - -use actix_web::web::Bytes; +use std::string::String; use actix_web::http::header::HeaderMap; use actix_web::http::StatusCode; - +use actix_web::web::Bytes; +use async_trait::async_trait; use log::{debug, error, trace}; use regex::Regex; use sea_orm::DatabaseConnection; -use std::string::String; +use tokio::sync::RwLockReadGuard; +use crate::authentication::{verify_login, Authentication}; +use crate::error::api_error::APIError; +use crate::error::internal_error::InternalError; +use crate::repository::data::RepositoryConfig; +use crate::repository::handler::RepositoryHandler; +use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; use crate::repository::npm::models::{Attachment, LoginRequest, LoginResponse, PublishRequest}; use crate::repository::npm::utils::generate_get_response; - -use crate::authentication::{verify_login, Authentication}; - use crate::repository::response::RepoResponse; +use crate::storage::file::StorageFileResponse; use crate::storage::models::Storage; +use crate::storage::DynamicStorage; use crate::system::permissions::options::CanIDo; use crate::system::user::UserModel; @@ -24,27 +29,16 @@ pub mod error; pub mod models; mod utils; -use crate::repository::data::RepositoryConfig; -use crate::repository::handler::RepositoryHandler; -use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; - -use crate::error::api_error::APIError; -use crate::error::internal_error::InternalError; -use crate::storage::file::StorageFileResponse; -use crate::storage::DynamicStorage; -use async_trait::async_trait; -use tokio::sync::RwLockReadGuard; - -pub struct NPMHandler<'a> { +pub struct NPMHandler<'a, StorageType: Storage> { config: RepositoryConfig, - storage: RwLockReadGuard<'a, DynamicStorage>, + storage: RwLockReadGuard<'a, StorageType>, } -impl<'a> NPMHandler<'a> { +impl<'a, StorageType: Storage> NPMHandler<'a, StorageType> { pub fn create( repository: RepositoryConfig, - storage: RwLockReadGuard<'a, DynamicStorage>, - ) -> NPMHandler<'a> { + storage: RwLockReadGuard<'a, StorageType>, + ) -> NPMHandler<'a, StorageType> { NPMHandler { config: repository, storage, @@ -54,9 +48,10 @@ impl<'a> NPMHandler<'a> { APIError::from(("Bad NPM Command", StatusCode::BAD_REQUEST)).into() } } + // name/version #[async_trait] -impl<'a> RepositoryHandler<'a> for NPMHandler<'a> { +impl<'a, StorageType: Storage> RepositoryHandler<'a, StorageType> for NPMHandler<'a, StorageType> { async fn handle_get( &self, path: &str, @@ -89,9 +84,10 @@ impl<'a> RepositoryHandler<'a> for NPMHandler<'a> { .map_err(InternalError::from)?; return Ok(RepoResponse::FileResponse(result)); } - let get_response = generate_get_response(&self.storage, &self.config, path) - .await - .unwrap(); + let get_response = + generate_get_response::(&self.storage, &self.config, path) + .await + .unwrap(); if get_response.is_none() { return Err(APIError::not_found().into()); } @@ -230,19 +226,19 @@ impl<'a> RepositoryHandler<'a> for NPMHandler<'a> { ), )); } - Err(NPMHandler::bad_npm_command()) + Err(NPMHandler::::bad_npm_command()) } else { - Err(NPMHandler::bad_npm_command()) + Err(NPMHandler::::bad_npm_command()) } } } -impl NitroRepositoryHandler for NPMHandler<'_> { +impl NitroRepositoryHandler for NPMHandler<'_, StorageType> { fn parse_project_to_directory>(path: S) -> String { path.into().replace('.', "/").replace(':', "/") } - fn storage(&self) -> &DynamicStorage { + fn storage(&self) -> &StorageType { &self.storage } diff --git a/backend/src/repository/npm/utils.rs b/backend/src/repository/npm/utils.rs index fb16ddc6..f9042a85 100644 --- a/backend/src/repository/npm/utils.rs +++ b/backend/src/repository/npm/utils.rs @@ -1,15 +1,12 @@ use std::collections::HashMap; -use log::warn; - use chrono::{DateTime, NaiveDateTime, Utc}; - -use crate::repository::nitro::{NitroRepoVersions, ProjectData}; +use log::warn; use crate::error::internal_error::InternalError; use crate::repository::data::RepositoryConfig; use crate::repository::nitro::utils::get_project_data; - +use crate::repository::nitro::{NitroRepoVersions, ProjectData}; use crate::repository::npm::models::{DistTags, GetResponse, NPMTimes, NPMVersions, Version}; use crate::storage::models::Storage; use crate::storage::DynamicStorage; @@ -35,8 +32,8 @@ impl From for HashMap { } } -pub async fn get_version_data( - storage: &DynamicStorage, +pub async fn get_version_data( + storage: &StorageType, repository: &RepositoryConfig, project_folder: &str, project: &ProjectData, @@ -69,8 +66,8 @@ pub async fn get_version_data( Ok((times, dist_tags, npm_versions)) } -pub async fn generate_get_response( - storage: &DynamicStorage, +pub async fn generate_get_response( + storage: &StorageType, repository: &RepositoryConfig, project_folder: &str, ) -> Result, InternalError> { From 63652e17c5be2d7bea85328f9933f602efa7392d Mon Sep 17 00:00:00 2001 From: Wyatt Jacob Herkamp Date: Tue, 31 May 2022 08:59:38 -0400 Subject: [PATCH 07/76] Repository Handlers --- backend/src/error/api_error.rs | 41 ++++-- backend/src/repository/handler.rs | 118 ++++++++++++++++ backend/src/repository/mod.rs | 8 +- backend/src/repository/web/multi/mod.rs | 20 +++ .../web/multi/repository_handler.rs | 132 ++++++++++++++++++ backend/src/storage/file.rs | 2 +- backend/src/storage/multi/web/admin.rs | 2 +- 7 files changed, 304 insertions(+), 19 deletions(-) create mode 100644 backend/src/repository/web/multi/repository_handler.rs diff --git a/backend/src/error/api_error.rs b/backend/src/error/api_error.rs index ddeca677..921a7c66 100644 --- a/backend/src/error/api_error.rs +++ b/backend/src/error/api_error.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::error::Error; use std::fmt::{Debug, Display, Formatter}; @@ -7,40 +8,54 @@ use actix_web::{HttpResponse, HttpResponseBuilder, ResponseError}; use serde_json::json; #[derive(Debug)] -pub struct APIError { - pub message: Option, +pub struct APIError<'a> { + pub message: Option>, pub status_code: StatusCode, } -impl APIError { - pub fn bad_request(error: E) -> APIError { + +impl<'a> APIError<'a> { + pub fn bad_request(error: E) -> APIError<'a> { APIError { - message: Some(error.to_string()), + message: Some(Cow::Owned(error.to_string())), status_code: StatusCode::BAD_REQUEST, } } - pub fn internal_error(error: E) -> APIError { + pub fn internal_error(error: E) -> APIError<'a> { APIError { - message: Some(error.to_string()), + message: Some(Cow::Owned(error.to_string())), status_code: StatusCode::INTERNAL_SERVER_ERROR, } } - pub fn not_found() -> APIError { + pub fn not_found() -> APIError<'a> { APIError { message: None, status_code: StatusCode::NOT_FOUND, } } + pub fn storage_not_found() -> APIError<'a> { + APIError { + message: Some(Cow::Borrowed("Storage not found")), + status_code: StatusCode::NOT_FOUND, + } + } + pub fn repository_not_found() -> APIError<'a> { + APIError { + message: Some(Cow::Borrowed("Repository not found")), + status_code: StatusCode::NOT_FOUND, + } + } } -impl From<(&str, StatusCode)> for APIError { - fn from((message, status): (&str, StatusCode)) -> Self { + +impl<'a> From<(&'a str, StatusCode)> for APIError<'a> { + fn from((message, status): (&'a str, StatusCode)) -> Self { APIError { - message: Some(message.to_string()), + message: Some(Cow::Borrowed(message)), status_code: status, } } } -impl Display for APIError { +impl<'a> Display for APIError<'a> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { if let Some(message) = &self.message { write!(f, "Status Code: {} Error: {}", self.status_code, message) @@ -50,7 +65,7 @@ impl Display for APIError { } } -impl ResponseError for APIError { +impl<'a> ResponseError for APIError<'a> { fn status_code(&self) -> StatusCode { self.status_code } diff --git a/backend/src/repository/handler.rs b/backend/src/repository/handler.rs index 32245d11..bcac4b5f 100644 --- a/backend/src/repository/handler.rs +++ b/backend/src/repository/handler.rs @@ -1,11 +1,14 @@ use actix_web::http::header::HeaderMap; use actix_web::http::StatusCode; use actix_web::web::Bytes; +use actix_web::Error; use async_trait::async_trait; use sea_orm::DatabaseConnection; use crate::authentication::Authentication; use crate::error::api_error::APIError; +use crate::repository::maven::MavenHandler; +use crate::repository::npm::NPMHandler; use crate::repository::response::RepoResponse; use crate::storage::models::Storage; @@ -85,3 +88,118 @@ pub trait RepositoryHandler<'a, S: Storage>: Send + Sync { .into()) } } + +pub enum DynamicRepositoryHandler<'a, StorageType: Storage> { + Maven(MavenHandler<'a, StorageType>), + NPM(NPMHandler<'a, StorageType>), +} + +// Implement RepositoryHandler to match to the type on the Enum +#[async_trait] +impl<'a, StorageType: Storage> RepositoryHandler<'a, StorageType> + for DynamicRepositoryHandler<'a, StorageType> +{ + async fn handle_get( + &self, + path: &str, + header: &HeaderMap, + conn: &DatabaseConnection, + authentication: Authentication, + ) -> Result { + // Implement the get method for the specific type + match self { + DynamicRepositoryHandler::Maven(handler) => { + handler.handle_get(path, header, conn, authentication).await + } + DynamicRepositoryHandler::NPM(handler) => { + handler.handle_get(path, header, conn, authentication).await + } + } + } + async fn handle_post( + &self, + path: &str, + header: &HeaderMap, + conn: &DatabaseConnection, + authentication: Authentication, + bytes: Bytes, + ) -> Result { + // Implement the post method for the specific type + match self { + DynamicRepositoryHandler::Maven(handler) => { + handler + .handle_post(path, header, conn, authentication, bytes) + .await + } + DynamicRepositoryHandler::NPM(handler) => { + handler + .handle_post(path, header, conn, authentication, bytes) + .await + } + } + } + async fn handle_put( + &self, + path: &str, + header: &HeaderMap, + conn: &DatabaseConnection, + authentication: Authentication, + bytes: Bytes, + ) -> Result { + match self { + DynamicRepositoryHandler::Maven(handler) => { + handler + .handle_put(path, header, conn, authentication, bytes) + .await + } + DynamicRepositoryHandler::NPM(handler) => { + handler + .handle_put(path, header, conn, authentication, bytes) + .await + } + } + } + async fn handle_patch( + &self, + path: &str, + header: &HeaderMap, + conn: &DatabaseConnection, + authentication: Authentication, + bytes: Bytes, + ) -> Result { + // Implement the patch method for the specific type + match self { + DynamicRepositoryHandler::Maven(handler) => { + handler + .handle_patch(path, header, conn, authentication, bytes) + .await + } + DynamicRepositoryHandler::NPM(handler) => { + handler + .handle_patch(path, header, conn, authentication, bytes) + .await + } + } + } + async fn handle_head( + &self, + path: &str, + header: &HeaderMap, + conn: &DatabaseConnection, + authentication: Authentication, + ) -> Result { + // Implement the head method for the specific type + match self { + DynamicRepositoryHandler::Maven(handler) => { + handler + .handle_head(path, header, conn, authentication) + .await + } + DynamicRepositoryHandler::NPM(handler) => { + handler + .handle_head(path, header, conn, authentication) + .await + } + } + } +} diff --git a/backend/src/repository/mod.rs b/backend/src/repository/mod.rs index 1eb90cba..183f15cf 100644 --- a/backend/src/repository/mod.rs +++ b/backend/src/repository/mod.rs @@ -6,7 +6,7 @@ use tokio::sync::RwLockReadGuard; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; use crate::repository::data::{RepositoryConfig, RepositoryType}; -use crate::repository::handler::RepositoryHandler; +use crate::repository::handler::{DynamicRepositoryHandler, RepositoryHandler}; use crate::repository::maven::MavenHandler; use crate::repository::npm::NPMHandler; use crate::storage::models::Storage; @@ -28,18 +28,18 @@ pub static REPOSITORY_CONF_BAK: &str = "repository.nitro_repo.bak"; pub async fn get_repository_handler<'a, StorageType: Storage>( storage: RwLockReadGuard<'a, StorageType>, repository: &str, -) -> Result + 'a>>, InternalError> { +) -> Result>, InternalError> { let value = storage.get_repository(repository).await?; if value.is_none() { return Ok(None); } let repository_config = value.unwrap().deref().clone(); match repository_config.repository_type { - RepositoryType::Maven => Ok(Some(Box::new(MavenHandler::create( + RepositoryType::Maven => Ok(Some(DynamicRepositoryHandler::Maven(MavenHandler::create( repository_config, storage, )))), - RepositoryType::NPM => Ok(Some(Box::new(NPMHandler::create( + RepositoryType::NPM => Ok(Some(DynamicRepositoryHandler::NPM(NPMHandler::create( repository_config, storage, )))), diff --git a/backend/src/repository/web/multi/mod.rs b/backend/src/repository/web/multi/mod.rs index 92918b09..4056a2cf 100644 --- a/backend/src/repository/web/multi/mod.rs +++ b/backend/src/repository/web/multi/mod.rs @@ -1 +1,21 @@ +use actix_web::web; + +use crate::system::web::public; + pub mod admin; +pub mod repository_handler; + +pub fn init(cfg: &mut web::ServiceConfig) { + cfg.service( + web::resource([ + "/storages/{storage}/{repository}", + "/storages/{storage}/{repository}/{file:.*}", + "/storages/{storage}/{repository}/", + ]) + .route(web::get().to(repository_handler::get_repository)) + .route(web::put().to(repository_handler::put_repository)) + .route(web::head().to(repository_handler::head_repository)) + .route(web::patch().to(repository_handler::patch_repository)) + .route(web::post().to(repository_handler::post_repository)), + ); +} diff --git a/backend/src/repository/web/multi/repository_handler.rs b/backend/src/repository/web/multi/repository_handler.rs new file mode 100644 index 00000000..aa0d7e09 --- /dev/null +++ b/backend/src/repository/web/multi/repository_handler.rs @@ -0,0 +1,132 @@ +use actix_web::http::StatusCode; +use actix_web::web::Bytes; +use actix_web::{get, web, HttpRequest, HttpResponse}; +use log::{debug, trace}; +use sea_orm::DatabaseConnection; +use serde::{Deserialize, Serialize}; + +use crate::authentication::Authentication; +use crate::error::api_error::APIError; +use crate::error::internal_error::InternalError; +use crate::repository::data::RepositoryType::{Maven, NPM}; +use crate::repository::get_repository_handler; +use crate::repository::handler::RepositoryHandler; +use crate::repository::maven::MavenHandler; +use crate::repository::nitro::NitroFileResponseType::Storage; +use crate::repository::nitro::{NitroFile, NitroFileResponse}; +use crate::repository::npm::NPMHandler; +use crate::repository::response::RepoResponse; +use crate::storage::multi::MultiStorageController; +use crate::utils::get_accept; +use crate::NitroRepoData; + +#[derive(Deserialize, Clone)] +pub struct GetPath { + pub storage: String, + pub repository: String, + #[serde(default)] + pub file: String, +} + +pub async fn get_repository( + pool: web::Data, + storages: web::Data, + auth: Authentication, + r: HttpRequest, + path: web::Path, +) -> actix_web::Result { + let storage = storages + .get_storage_by_name(&path.storage) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::storage_not_found())?; + let repository_handler = get_repository_handler(storage, path.repository.as_str()) + .await? + .ok_or_else(|| APIError::repository_not_found())?; + repository_handler + .handle_get(path.file.as_str(), r.headers(), pool.get_ref(), auth) + .await +} + +pub async fn put_repository( + pool: web::Data, + storages: web::Data, + auth: Authentication, + r: HttpRequest, + path: web::Path, + bytes: Bytes, +) -> actix_web::Result { + let storage = storages + .get_storage_by_name(&path.storage) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::storage_not_found())?; + let repository_handler = get_repository_handler(storage, path.repository.as_str()) + .await? + .ok_or_else(|| APIError::repository_not_found())?; + repository_handler + .handle_put(path.file.as_str(), r.headers(), pool.get_ref(), auth, bytes) + .await +} + +pub async fn head_repository( + pool: web::Data, + storages: web::Data, + auth: Authentication, + r: HttpRequest, + path: web::Path, +) -> actix_web::Result { + let storage = storages + .get_storage_by_name(&path.storage) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::storage_not_found())?; + let repository_handler = get_repository_handler(storage, path.repository.as_str()) + .await? + .ok_or_else(|| APIError::repository_not_found())?; + repository_handler + .handle_head(path.file.as_str(), r.headers(), pool.get_ref(), auth) + .await +} + +pub async fn post_repository( + pool: web::Data, + storages: web::Data, + auth: Authentication, + r: HttpRequest, + path: web::Path, + bytes: Bytes, +) -> actix_web::Result { + let storage = storages + .get_storage_by_name(&path.storage) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::storage_not_found())?; + let repository_handler = get_repository_handler(storage, path.repository.as_str()) + .await? + .ok_or_else(|| APIError::repository_not_found())?; + repository_handler + .handle_post(path.file.as_str(), r.headers(), pool.get_ref(), auth, bytes) + .await +} + +pub async fn patch_repository( + pool: web::Data, + storages: web::Data, + auth: Authentication, + r: HttpRequest, + path: web::Path, + bytes: Bytes, +) -> actix_web::Result { + let storage = storages + .get_storage_by_name(&path.storage) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::storage_not_found())?; + let repository_handler = get_repository_handler(storage, path.repository.as_str()) + .await? + .ok_or_else(|| APIError::repository_not_found())?; + repository_handler + .handle_patch(path.file.as_str(), r.headers(), pool.get_ref(), auth, bytes) + .await +} diff --git a/backend/src/storage/file.rs b/backend/src/storage/file.rs index 7a4c8f71..af42daf1 100644 --- a/backend/src/storage/file.rs +++ b/backend/src/storage/file.rs @@ -149,7 +149,7 @@ pub trait FileListResponder { } /// For Internal Use /// Invalid Data Type - fn invalid_accept_type() -> APIError { + fn invalid_accept_type() -> APIError<'static> { APIError::from(("Invalid Accept Header", StatusCode::BAD_REQUEST)) } } diff --git a/backend/src/storage/multi/web/admin.rs b/backend/src/storage/multi/web/admin.rs index f3c3c522..a6eb7158 100644 --- a/backend/src/storage/multi/web/admin.rs +++ b/backend/src/storage/multi/web/admin.rs @@ -83,7 +83,7 @@ pub async fn get_storage( if let Some(storage) = storage_handler .get_storage_by_name(&name.into_inner()) .await - .map_err(|e| InternalError::from(e))? + .map_err(InternalError::from)? { Ok(HttpResponse::Ok().json(storage.config_for_saving())) } else { From 7ff4ff5b15fba2b22ebec5d48bcaf3804c2659db Mon Sep 17 00:00:00 2001 From: Wyatt Jacob Herkamp Date: Tue, 31 May 2022 09:02:16 -0400 Subject: [PATCH 08/76] Repository Handlers --- backend/src/repository/maven/mod.rs | 1 - backend/src/repository/mod.rs | 6 ++-- .../src/repository/nitro/nitro_repository.rs | 1 - backend/src/repository/nitro/utils.rs | 1 - backend/src/repository/npm/mod.rs | 1 - backend/src/repository/npm/utils.rs | 1 - backend/src/repository/web/multi/admin.rs | 3 +- backend/src/repository/web/multi/mod.rs | 2 -- .../web/multi/repository_handler.rs | 33 +++++++------------ backend/src/storage/bad_storage.rs | 2 +- backend/src/storage/error.rs | 1 - backend/src/storage/mod.rs | 2 +- backend/src/storage/multi/web/admin.rs | 2 +- backend/src/system/permissions/options.rs | 1 - 14 files changed, 18 insertions(+), 39 deletions(-) diff --git a/backend/src/repository/maven/mod.rs b/backend/src/repository/maven/mod.rs index 648a3f74..19716216 100644 --- a/backend/src/repository/maven/mod.rs +++ b/backend/src/repository/maven/mod.rs @@ -18,7 +18,6 @@ use crate::repository::settings::security::Visibility; use crate::repository::settings::Policy; use crate::storage::file::StorageFileResponse; use crate::storage::models::Storage; -use crate::storage::DynamicStorage; use crate::system::permissions::options::CanIDo; use crate::system::user::UserModel; diff --git a/backend/src/repository/mod.rs b/backend/src/repository/mod.rs index 183f15cf..01fb632a 100644 --- a/backend/src/repository/mod.rs +++ b/backend/src/repository/mod.rs @@ -1,12 +1,10 @@ use std::ops::Deref; -use futures_util::TryFutureExt; use tokio::sync::RwLockReadGuard; -use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; -use crate::repository::data::{RepositoryConfig, RepositoryType}; -use crate::repository::handler::{DynamicRepositoryHandler, RepositoryHandler}; +use crate::repository::data::RepositoryType; +use crate::repository::handler::DynamicRepositoryHandler; use crate::repository::maven::MavenHandler; use crate::repository::npm::NPMHandler; use crate::storage::models::Storage; diff --git a/backend/src/repository/nitro/nitro_repository.rs b/backend/src/repository/nitro/nitro_repository.rs index b558ff11..c929cb89 100644 --- a/backend/src/repository/nitro/nitro_repository.rs +++ b/backend/src/repository/nitro/nitro_repository.rs @@ -14,7 +14,6 @@ use crate::repository::nitro::{ use crate::repository::response::Project; use crate::storage::file::StorageDirectoryResponse; use crate::storage::models::Storage; -use crate::storage::DynamicStorage; use crate::system::user::UserModel; #[async_trait] diff --git a/backend/src/repository/nitro/utils.rs b/backend/src/repository/nitro/utils.rs index bf947d09..d02d9db5 100644 --- a/backend/src/repository/nitro/utils.rs +++ b/backend/src/repository/nitro/utils.rs @@ -9,7 +9,6 @@ use crate::repository::data::RepositoryConfig; use crate::repository::nitro::{NitroRepoVersions, ProjectData, RepositoryListing, VersionData}; use crate::repository::response::VersionResponse; use crate::storage::models::Storage; -use crate::storage::DynamicStorage; pub async fn get_version( storage: &StorageType, diff --git a/backend/src/repository/npm/mod.rs b/backend/src/repository/npm/mod.rs index 3e8e5a49..91f30004 100644 --- a/backend/src/repository/npm/mod.rs +++ b/backend/src/repository/npm/mod.rs @@ -21,7 +21,6 @@ use crate::repository::npm::utils::generate_get_response; use crate::repository::response::RepoResponse; use crate::storage::file::StorageFileResponse; use crate::storage::models::Storage; -use crate::storage::DynamicStorage; use crate::system::permissions::options::CanIDo; use crate::system::user::UserModel; diff --git a/backend/src/repository/npm/utils.rs b/backend/src/repository/npm/utils.rs index f9042a85..80470335 100644 --- a/backend/src/repository/npm/utils.rs +++ b/backend/src/repository/npm/utils.rs @@ -9,7 +9,6 @@ use crate::repository::nitro::utils::get_project_data; use crate::repository::nitro::{NitroRepoVersions, ProjectData}; use crate::repository::npm::models::{DistTags, GetResponse, NPMTimes, NPMVersions, Version}; use crate::storage::models::Storage; -use crate::storage::DynamicStorage; static NPM_TIME_FORMAT: &str = "%Y-%m-%dT%H:%M:%S.%3fZ"; diff --git a/backend/src/repository/web/multi/admin.rs b/backend/src/repository/web/multi/admin.rs index 585f5199..f46ae9d7 100644 --- a/backend/src/repository/web/multi/admin.rs +++ b/backend/src/repository/web/multi/admin.rs @@ -1,7 +1,7 @@ use std::ops::Deref; use actix_web::http::StatusCode; -use actix_web::{delete, get, post, web, HttpRequest, HttpResponse, ResponseError}; +use actix_web::{delete, get, post, web, HttpResponse}; use sea_orm::DatabaseConnection; use serde::Deserialize; @@ -12,7 +12,6 @@ use crate::repository::data::RepositoryType; use crate::repository::web::RepositoryResponse; use crate::storage::error::StorageError; use crate::storage::models::Storage; -use crate::storage::models::StorageFactory; use crate::storage::multi::MultiStorageController; use crate::system::permissions::options::CanIDo; use crate::system::user::UserModel; diff --git a/backend/src/repository/web/multi/mod.rs b/backend/src/repository/web/multi/mod.rs index 4056a2cf..b041aefc 100644 --- a/backend/src/repository/web/multi/mod.rs +++ b/backend/src/repository/web/multi/mod.rs @@ -1,7 +1,5 @@ use actix_web::web; -use crate::system::web::public; - pub mod admin; pub mod repository_handler; diff --git a/backend/src/repository/web/multi/repository_handler.rs b/backend/src/repository/web/multi/repository_handler.rs index aa0d7e09..96ac75cb 100644 --- a/backend/src/repository/web/multi/repository_handler.rs +++ b/backend/src/repository/web/multi/repository_handler.rs @@ -1,24 +1,15 @@ -use actix_web::http::StatusCode; use actix_web::web::Bytes; -use actix_web::{get, web, HttpRequest, HttpResponse}; -use log::{debug, trace}; +use actix_web::{web, HttpRequest}; use sea_orm::DatabaseConnection; -use serde::{Deserialize, Serialize}; +use serde::Deserialize; use crate::authentication::Authentication; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; -use crate::repository::data::RepositoryType::{Maven, NPM}; use crate::repository::get_repository_handler; use crate::repository::handler::RepositoryHandler; -use crate::repository::maven::MavenHandler; -use crate::repository::nitro::NitroFileResponseType::Storage; -use crate::repository::nitro::{NitroFile, NitroFileResponse}; -use crate::repository::npm::NPMHandler; use crate::repository::response::RepoResponse; use crate::storage::multi::MultiStorageController; -use crate::utils::get_accept; -use crate::NitroRepoData; #[derive(Deserialize, Clone)] pub struct GetPath { @@ -39,10 +30,10 @@ pub async fn get_repository( .get_storage_by_name(&path.storage) .await .map_err(InternalError::from)? - .ok_or_else(|| APIError::storage_not_found())?; + .ok_or_else(APIError::storage_not_found)?; let repository_handler = get_repository_handler(storage, path.repository.as_str()) .await? - .ok_or_else(|| APIError::repository_not_found())?; + .ok_or_else(APIError::repository_not_found)?; repository_handler .handle_get(path.file.as_str(), r.headers(), pool.get_ref(), auth) .await @@ -60,10 +51,10 @@ pub async fn put_repository( .get_storage_by_name(&path.storage) .await .map_err(InternalError::from)? - .ok_or_else(|| APIError::storage_not_found())?; + .ok_or_else(APIError::storage_not_found)?; let repository_handler = get_repository_handler(storage, path.repository.as_str()) .await? - .ok_or_else(|| APIError::repository_not_found())?; + .ok_or_else(APIError::repository_not_found)?; repository_handler .handle_put(path.file.as_str(), r.headers(), pool.get_ref(), auth, bytes) .await @@ -80,10 +71,10 @@ pub async fn head_repository( .get_storage_by_name(&path.storage) .await .map_err(InternalError::from)? - .ok_or_else(|| APIError::storage_not_found())?; + .ok_or_else(APIError::storage_not_found)?; let repository_handler = get_repository_handler(storage, path.repository.as_str()) .await? - .ok_or_else(|| APIError::repository_not_found())?; + .ok_or_else(APIError::repository_not_found)?; repository_handler .handle_head(path.file.as_str(), r.headers(), pool.get_ref(), auth) .await @@ -101,10 +92,10 @@ pub async fn post_repository( .get_storage_by_name(&path.storage) .await .map_err(InternalError::from)? - .ok_or_else(|| APIError::storage_not_found())?; + .ok_or_else(APIError::storage_not_found)?; let repository_handler = get_repository_handler(storage, path.repository.as_str()) .await? - .ok_or_else(|| APIError::repository_not_found())?; + .ok_or_else(APIError::repository_not_found)?; repository_handler .handle_post(path.file.as_str(), r.headers(), pool.get_ref(), auth, bytes) .await @@ -122,10 +113,10 @@ pub async fn patch_repository( .get_storage_by_name(&path.storage) .await .map_err(InternalError::from)? - .ok_or_else(|| APIError::storage_not_found())?; + .ok_or_else(APIError::storage_not_found)?; let repository_handler = get_repository_handler(storage, path.repository.as_str()) .await? - .ok_or_else(|| APIError::repository_not_found())?; + .ok_or_else(APIError::repository_not_found)?; repository_handler .handle_patch(path.file.as_str(), r.headers(), pool.get_ref(), auth, bytes) .await diff --git a/backend/src/storage/bad_storage.rs b/backend/src/storage/bad_storage.rs index aa05b506..d6d1444d 100644 --- a/backend/src/storage/bad_storage.rs +++ b/backend/src/storage/bad_storage.rs @@ -26,7 +26,7 @@ impl BadStorage { } #[async_trait] impl Storage for BadStorage { - fn create_new(config: StorageFactory) -> Result + fn create_new(_config: StorageFactory) -> Result where Self: Sized, { diff --git a/backend/src/storage/error.rs b/backend/src/storage/error.rs index 1c453add..df612341 100644 --- a/backend/src/storage/error.rs +++ b/backend/src/storage/error.rs @@ -1,6 +1,5 @@ use std::time::SystemTimeError; -use actix_web::ResponseError; use thiserror::Error; #[derive(Error, Debug)] diff --git a/backend/src/storage/mod.rs b/backend/src/storage/mod.rs index 54cb5150..f034fcf0 100644 --- a/backend/src/storage/mod.rs +++ b/backend/src/storage/mod.rs @@ -29,7 +29,7 @@ pub enum DynamicStorage { #[async_trait] impl Storage for DynamicStorage { - fn create_new(config: StorageFactory) -> Result + fn create_new(_config: StorageFactory) -> Result where Self: Sized, { diff --git a/backend/src/storage/multi/web/admin.rs b/backend/src/storage/multi/web/admin.rs index a6eb7158..3d37bf91 100644 --- a/backend/src/storage/multi/web/admin.rs +++ b/backend/src/storage/multi/web/admin.rs @@ -62,7 +62,7 @@ pub async fn delete_storage( if storage_handler .delete_storage(&name.into_inner()) .await - .map_err(|error| InternalError::from(error))? + .map_err(InternalError::from)? { Ok(HttpResponse::Ok().finish()) } else { diff --git a/backend/src/system/permissions/options.rs b/backend/src/system/permissions/options.rs index 210ab4a2..7ff8225e 100644 --- a/backend/src/system/permissions/options.rs +++ b/backend/src/system/permissions/options.rs @@ -5,7 +5,6 @@ use actix_web::http::StatusCode; use actix_web::ResponseError; use serde_json::json; -use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; use crate::repository::data::RepositoryConfig; use crate::repository::settings::security::Visibility; From 6161511236160d485c19b66620e6cf73441baaf8 Mon Sep 17 00:00:00 2001 From: Wyatt Jacob Herkamp Date: Tue, 31 May 2022 11:52:19 -0400 Subject: [PATCH 09/76] Improved the Config System for Repository Config --- backend/Cargo.toml | 2 +- backend/src/repository/data/mod.rs | 76 ----------- backend/src/repository/maven/mod.rs | 3 +- backend/src/repository/maven/models.rs | 16 +-- backend/src/repository/mod.rs | 3 +- backend/src/repository/nitro/mod.rs | 9 +- .../src/repository/nitro/nitro_repository.rs | 2 +- backend/src/repository/nitro/utils.rs | 2 +- backend/src/repository/npm/mod.rs | 2 +- backend/src/repository/npm/models.rs | 16 ++- backend/src/repository/npm/utils.rs | 2 +- backend/src/repository/response.rs | 2 +- backend/src/repository/settings/frontend.rs | 13 ++ backend/src/repository/settings/mod.rs | 97 +++++++++++++- backend/src/repository/settings/security.rs | 3 - backend/src/repository/web/mod.rs | 10 +- backend/src/repository/web/multi/admin.rs | 2 +- backend/src/storage/bad_storage.rs | 46 ++++--- backend/src/storage/local_storage/mod.rs | 118 +++++++++--------- backend/src/storage/mod.rs | 84 ++++++++----- backend/src/storage/models.rs | 39 +++--- backend/src/system/permissions/mod.rs | 3 +- backend/src/system/permissions/options.rs | 2 +- 23 files changed, 308 insertions(+), 244 deletions(-) delete mode 100644 backend/src/repository/data/mod.rs diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 0d016ec6..040a5d60 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -26,7 +26,7 @@ actix-files = "0.6.0" lettre = "0.10.0-rc.6" handlebars = "4.2.2" # Database -sea-orm = { version = "0.7.1", features = ["sqlx-mysql", "sqlx-sqlite", "runtime-actix-native-tls", "macros"] } +sea-orm = { version = "0.8.0", features = ["sqlx-mysql", "sqlx-sqlite", "runtime-actix-native-tls", "macros"] } sqlx = "0.5.13" # Serde serde = { version = "1.0.137", features = ["derive"] } diff --git a/backend/src/repository/data/mod.rs b/backend/src/repository/data/mod.rs deleted file mode 100644 index 87a2a5c8..00000000 --- a/backend/src/repository/data/mod.rs +++ /dev/null @@ -1,76 +0,0 @@ -use std::fmt::Debug; - -use serde::de::DeserializeOwned; -use serde::{Deserialize, Serialize}; - -use crate::error::internal_error::InternalError; -use crate::repository::settings::frontend::Frontend; -use crate::repository::settings::security::Visibility; -use crate::repository::settings::{Policy, FRONTEND_CONFIG}; -use crate::storage::models::Storage; - -/// Types of Repositories that can exist. -#[derive(Serialize, Deserialize, Clone, Debug, strum_macros::Display, strum_macros::EnumString)] -pub enum RepositoryType { - Maven, - NPM, -} - -/// The Basic Repository Config -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct RepositoryConfig { - /// Repository Name - pub name: String, - /// The Type of Repository - pub repository_type: RepositoryType, - /// Storage. - pub storage: String, - /// Visibility. - #[serde(default)] - pub visibility: Visibility, - /// Rather or not the Repository is active. Meaning it can be pulled or pushed - #[serde(default = "default")] - pub active: bool, - ///The versioning policy for the Repository - #[serde(default)] - pub policy: Policy, - /// When it was created - pub created: i64, -} -impl RepositoryConfig { - /// Pull the Frontend Config - pub async fn get_frontend_config( - &self, - storage: &dyn Storage, - ) -> Result, InternalError> { - let option = storage.get_file(self, FRONTEND_CONFIG).await?; - if option.is_none() { - return Ok(None); - } - serde_json::from_slice(option.unwrap().as_slice()) - .map(Some) - .map_err(InternalError::from) - } - /// Update the frontend config - async fn save_frontend_config( - &self, - storage: &dyn Storage, - frontend: Option, - ) -> Result<(), InternalError> { - if frontend.is_none() { - // Treats a disable - storage.delete_file(self, FRONTEND_CONFIG).await?; - } - let value = serde_json::to_string(&frontend.unwrap())?; - storage - .save_file(self, value.as_bytes(), FRONTEND_CONFIG) - .await?; - Ok(()) - } -} - -fn default() -> bool { - true -} - -pub trait RepositorySetting: Send + Sync + Clone + Debug + Serialize + DeserializeOwned {} diff --git a/backend/src/repository/maven/mod.rs b/backend/src/repository/maven/mod.rs index 19716216..271e051a 100644 --- a/backend/src/repository/maven/mod.rs +++ b/backend/src/repository/maven/mod.rs @@ -9,13 +9,12 @@ use tokio::sync::RwLockReadGuard; use crate::authentication::Authentication; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; -use crate::repository::data::RepositoryConfig; use crate::repository::handler::RepositoryHandler; use crate::repository::maven::models::Pom; use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; use crate::repository::response::RepoResponse; use crate::repository::settings::security::Visibility; -use crate::repository::settings::Policy; +use crate::repository::settings::{Policy, RepositoryConfig}; use crate::storage::file::StorageFileResponse; use crate::storage::models::Storage; use crate::system::permissions::options::CanIDo; diff --git a/backend/src/repository/maven/models.rs b/backend/src/repository/maven/models.rs index 7bf12ccc..524c7c9a 100644 --- a/backend/src/repository/maven/models.rs +++ b/backend/src/repository/maven/models.rs @@ -1,22 +1,18 @@ -use crate::repository::data::RepositorySetting; +use serde::{Deserialize, Serialize}; + use crate::repository::nitro::VersionData; +use crate::repository::settings::RepositoryConfigType; use crate::utils::get_current_time; -use serde::{Deserialize, Serialize}; -use serde_json::Value; #[derive(Debug, Serialize, Deserialize, Clone, Default)] pub struct MavenSettings {} -impl TryFrom for MavenSettings { - type Error = serde_json::Error; - - fn try_from(value: Value) -> Result { - serde_json::from_value(value) +impl RepositoryConfigType for MavenSettings { + fn config_name() -> &'static str { + "maven.json" } } -impl RepositorySetting for MavenSettings {} - #[derive(Debug, Serialize, Deserialize, Clone)] pub struct DeployMetadata { #[serde(rename = "groupId")] diff --git a/backend/src/repository/mod.rs b/backend/src/repository/mod.rs index 01fb632a..2dc8c531 100644 --- a/backend/src/repository/mod.rs +++ b/backend/src/repository/mod.rs @@ -3,13 +3,12 @@ use std::ops::Deref; use tokio::sync::RwLockReadGuard; use crate::error::internal_error::InternalError; -use crate::repository::data::RepositoryType; use crate::repository::handler::DynamicRepositoryHandler; use crate::repository::maven::MavenHandler; use crate::repository::npm::NPMHandler; +use crate::repository::settings::RepositoryType; use crate::storage::models::Storage; -pub mod data; pub mod frontend; pub mod handler; pub mod maven; diff --git a/backend/src/repository/nitro/mod.rs b/backend/src/repository/nitro/mod.rs index 15a3aed3..41f2e9f4 100644 --- a/backend/src/repository/nitro/mod.rs +++ b/backend/src/repository/nitro/mod.rs @@ -1,11 +1,12 @@ -pub mod nitro_repository; -pub mod utils; +use serde::{Deserialize, Serialize}; -use crate::repository::data::RepositoryConfig; use crate::repository::response::Project; +use crate::repository::settings::RepositoryConfig; use crate::storage::file::StorageFile; use crate::utils::get_current_time; -use serde::{Deserialize, Serialize}; + +pub mod nitro_repository; +pub mod utils; #[derive(Serialize, Clone, Debug)] pub struct NitroFileResponse { diff --git a/backend/src/repository/nitro/nitro_repository.rs b/backend/src/repository/nitro/nitro_repository.rs index c929cb89..ebe1f7ee 100644 --- a/backend/src/repository/nitro/nitro_repository.rs +++ b/backend/src/repository/nitro/nitro_repository.rs @@ -3,7 +3,6 @@ use log::{debug, error, trace}; use crate::constants::{PROJECT_FILE, VERSION_DATA}; use crate::error::internal_error::InternalError; -use crate::repository::data::RepositoryConfig; use crate::repository::nitro::utils::{ get_project_data, get_version_data, get_versions, update_project_in_repositories, }; @@ -12,6 +11,7 @@ use crate::repository::nitro::{ VersionData, }; use crate::repository::response::Project; +use crate::repository::settings::RepositoryConfig; use crate::storage::file::StorageDirectoryResponse; use crate::storage::models::Storage; use crate::system::user::UserModel; diff --git a/backend/src/repository/nitro/utils.rs b/backend/src/repository/nitro/utils.rs index d02d9db5..1d99a672 100644 --- a/backend/src/repository/nitro/utils.rs +++ b/backend/src/repository/nitro/utils.rs @@ -5,9 +5,9 @@ use log::debug; use crate::constants::{PROJECTS_FILE, PROJECT_FILE, VERSION_DATA}; use crate::error::internal_error::InternalError; -use crate::repository::data::RepositoryConfig; use crate::repository::nitro::{NitroRepoVersions, ProjectData, RepositoryListing, VersionData}; use crate::repository::response::VersionResponse; +use crate::repository::settings::RepositoryConfig; use crate::storage::models::Storage; pub async fn get_version( diff --git a/backend/src/repository/npm/mod.rs b/backend/src/repository/npm/mod.rs index 91f30004..ce68738f 100644 --- a/backend/src/repository/npm/mod.rs +++ b/backend/src/repository/npm/mod.rs @@ -13,12 +13,12 @@ use tokio::sync::RwLockReadGuard; use crate::authentication::{verify_login, Authentication}; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; -use crate::repository::data::RepositoryConfig; use crate::repository::handler::RepositoryHandler; use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; use crate::repository::npm::models::{Attachment, LoginRequest, LoginResponse, PublishRequest}; use crate::repository::npm::utils::generate_get_response; use crate::repository::response::RepoResponse; +use crate::repository::settings::RepositoryConfig; use crate::storage::file::StorageFileResponse; use crate::storage::models::Storage; use crate::system::permissions::options::CanIDo; diff --git a/backend/src/repository/npm/models.rs b/backend/src/repository/npm/models.rs index 9db25f0c..0e84d375 100644 --- a/backend/src/repository/npm/models.rs +++ b/backend/src/repository/npm/models.rs @@ -1,23 +1,21 @@ use std::collections::HashMap; -use crate::repository::data::RepositorySetting; -use crate::repository::nitro::VersionData; -use crate::utils::get_current_time; use serde::{Deserialize, Serialize}; use serde_json::Value; +use crate::repository::nitro::VersionData; +use crate::repository::settings::RepositoryConfigType; +use crate::utils::get_current_time; + #[derive(Debug, Serialize, Deserialize, Clone, Default)] pub struct NPMSettings {} -impl TryFrom for NPMSettings { - type Error = serde_json::Error; - fn try_from(value: Value) -> Result { - serde_json::from_value(value) +impl RepositoryConfigType for NPMSettings { + fn config_name() -> &'static str { + "npm.json" } } -impl RepositorySetting for NPMSettings {} - #[derive(Debug, Serialize, Deserialize)] pub struct LoginRequest { pub password: String, diff --git a/backend/src/repository/npm/utils.rs b/backend/src/repository/npm/utils.rs index 80470335..fd37b26c 100644 --- a/backend/src/repository/npm/utils.rs +++ b/backend/src/repository/npm/utils.rs @@ -4,10 +4,10 @@ use chrono::{DateTime, NaiveDateTime, Utc}; use log::warn; use crate::error::internal_error::InternalError; -use crate::repository::data::RepositoryConfig; use crate::repository::nitro::utils::get_project_data; use crate::repository::nitro::{NitroRepoVersions, ProjectData}; use crate::repository::npm::models::{DistTags, GetResponse, NPMTimes, NPMVersions, Version}; +use crate::repository::settings::RepositoryConfig; use crate::storage::models::Storage; static NPM_TIME_FORMAT: &str = "%Y-%m-%dT%H:%M:%S.%3fZ"; diff --git a/backend/src/repository/response.rs b/backend/src/repository/response.rs index 2a077f70..6079e335 100644 --- a/backend/src/repository/response.rs +++ b/backend/src/repository/response.rs @@ -9,9 +9,9 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; use crate::error::internal_error::InternalError; -use crate::repository::data::RepositoryConfig; use crate::repository::frontend::FrontendResponse; use crate::repository::nitro::{NitroVersion, ProjectData, VersionData}; +use crate::repository::settings::RepositoryConfig; use crate::storage::file::StorageFileResponse; #[derive(Serialize, Deserialize, Clone, Debug)] diff --git a/backend/src/repository/settings/frontend.rs b/backend/src/repository/settings/frontend.rs index 109dc3a5..f650f8f5 100644 --- a/backend/src/repository/settings/frontend.rs +++ b/backend/src/repository/settings/frontend.rs @@ -1,6 +1,8 @@ use badge_maker::Style; use serde::{Deserialize, Serialize}; +use crate::repository::settings::RepositoryConfigType; + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Frontend { #[serde(default = "PageProvider::default")] @@ -9,6 +11,11 @@ pub struct Frontend { pub description: String, } +impl RepositoryConfigType for Frontend { + fn config_name() -> &'static str { + "frontend.json" + } +} #[derive(Debug, Clone, Serialize, Deserialize)] pub enum BadgeStyle { Flat, @@ -42,6 +49,12 @@ pub struct BadgeSettings { pub color: String, } +impl RepositoryConfigType for BadgeSettings { + fn config_name() -> &'static str { + "badge.json" + } +} + impl Default for BadgeSettings { fn default() -> Self { BadgeSettings { diff --git a/backend/src/repository/settings/mod.rs b/backend/src/repository/settings/mod.rs index 5b355f96..e3c8cf1d 100644 --- a/backend/src/repository/settings/mod.rs +++ b/backend/src/repository/settings/mod.rs @@ -1,12 +1,16 @@ +use std::fmt::Debug; + +use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; +use crate::error::internal_error::InternalError; +use crate::repository::settings::security::Visibility; +use crate::storage::models::Storage; + pub mod frontend; pub mod security; pub mod webhook; -pub const WEBHOOK_CONFIG: &str = ".nitro_repo/webhook.json"; -pub const FRONTEND_CONFIG: &str = ".nitro_repo/frontend.json"; - #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, strum_macros::EnumString)] pub enum Policy { Release, @@ -19,3 +23,90 @@ impl Default for Policy { Policy::Mixed } } + +fn default() -> bool { + true +} + +/// Types of Repositories that can exist. +#[derive(Serialize, Deserialize, Clone, Debug, strum_macros::Display, strum_macros::EnumString)] +pub enum RepositoryType { + /// A Maven Repository + Maven, + /// A NPM Repository + NPM, +} + +/// The Basic Repository Config +/// These values are core to the existence of the Repository +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct RepositoryConfig { + /// Repository Name + pub name: String, + /// The Type of Repository + pub repository_type: RepositoryType, + /// Storage. + pub storage: String, + /// Visibility. + #[serde(default)] + pub visibility: Visibility, + /// Rather or not the Repository is active. Meaning it can be pulled or pushed + #[serde(default = "default")] + pub active: bool, + ///The versioning policy for the Repository + #[serde(default)] + pub policy: Policy, + /// When it was created + pub created: i64, +} + +impl RepositoryConfig { + /// Gets the Config File + /// # Arguments + /// * `storage` - The Storage to use. The Repository must belong to the Storage + /// # Returns + /// * `Result, InternalError>` - The Config File + pub async fn get_config( + &self, + storage: &StorageType, + ) -> Result, InternalError> { + storage + .get_repository_config::(self, Config::config_name()) + .await + .map_err(InternalError::StorageError) + } + /// Saves the repository config + /// # Arguments + /// * `storage` - The Storage to use. The Repository must belong to the Storage + /// * `config` - The Config to save. If None is passed, then the config is deleted + /// # Returns + /// * `Result<(), InternalError>` - + /// # Errors + /// * `InternalError::StorageError` - If the Storage fails to save the config + /// # Remarks + /// This will overwrite the config file. + pub async fn save_config( + &self, + storage: &StorageType, + config: Option<&Config>, + ) -> Result<(), InternalError> { + if let Some(value) = config { + storage + .update_repository_config(self, Config::config_name(), &value) + .await + .map_err(InternalError::StorageError) + } else { + // Deleting the config means for the Config type that the feature set has been disabled + // If the type should not be disabled. This is a bug. + storage + .delete_repository_config(self, Config::config_name()) + .await + .map_err(InternalError::StorageError) + } + } +} + +/// Represents a Repository Setting group. That is not apart of the core config set +pub trait RepositoryConfigType: Send + Sync + Clone + Debug + Serialize + DeserializeOwned { + fn config_name() -> &'static str; +} diff --git a/backend/src/repository/settings/security.rs b/backend/src/repository/settings/security.rs index cf5254e7..2f705355 100644 --- a/backend/src/repository/settings/security.rs +++ b/backend/src/repository/settings/security.rs @@ -12,6 +12,3 @@ impl Default for Visibility { Visibility::Public } } - -#[derive(Debug, Deserialize, Serialize, Clone, Default)] -pub struct SecurityRules {} diff --git a/backend/src/repository/web/mod.rs b/backend/src/repository/web/mod.rs index 0778437b..ef3504b3 100644 --- a/backend/src/repository/web/mod.rs +++ b/backend/src/repository/web/mod.rs @@ -1,8 +1,8 @@ use serde::Serialize; use crate::error::internal_error::InternalError; -use crate::repository::data::RepositoryConfig; use crate::repository::settings::frontend::{BadgeSettings, Frontend}; +use crate::repository::settings::RepositoryConfig; use crate::storage::models::Storage; pub mod multi; @@ -15,12 +15,12 @@ pub struct RepositoryResponse<'a> { } impl<'a> RepositoryResponse<'a> { - pub async fn new( + pub async fn new( config: &'a RepositoryConfig, - storage: &dyn Storage, + storage: &StorageType, ) -> Result, InternalError> { - let frontend = config.get_frontend_config(storage).await?; - let badge: Option = None; + let frontend = config.get_config(storage).await?; + let badge = config.get_config(storage).await?; Ok(RepositoryResponse { config, frontend, diff --git a/backend/src/repository/web/multi/admin.rs b/backend/src/repository/web/multi/admin.rs index f46ae9d7..e8bebeb7 100644 --- a/backend/src/repository/web/multi/admin.rs +++ b/backend/src/repository/web/multi/admin.rs @@ -8,8 +8,8 @@ use serde::Deserialize; use crate::authentication::Authentication; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; -use crate::repository::data::RepositoryType; use crate::repository::web::RepositoryResponse; +use crate::repository::RepositoryType; use crate::storage::error::StorageError; use crate::storage::models::Storage; use crate::storage::multi::MultiStorageController; diff --git a/backend/src/storage/bad_storage.rs b/backend/src/storage/bad_storage.rs index d6d1444d..7bee7a47 100644 --- a/backend/src/storage/bad_storage.rs +++ b/backend/src/storage/bad_storage.rs @@ -1,9 +1,11 @@ use async_trait::async_trait; use log::warn; +use serde::de::DeserializeOwned; +use serde::Serialize; use serde_json::Value; use tokio::sync::RwLockReadGuard; -use crate::repository::data::{RepositoryConfig, RepositoryType}; +use crate::repository::settings::{RepositoryConfig, RepositoryType}; use crate::storage::error::StorageError; use crate::storage::file::{StorageFile, StorageFileResponse}; use crate::storage::models::{ @@ -104,23 +106,6 @@ impl Storage for BadStorage { panic!("This should not be called!") } - async fn update_repository_config( - &self, - _repository: &RepositoryConfig, - _file: &str, - _data: &Option, - ) -> Result<(), StorageError> { - panic!("This should not be called!") - } - - async fn get_repository_config( - &self, - _repository: &RepositoryConfig, - _file: &str, - ) -> Result, StorageError> { - panic!("This should not be called!") - } - async fn save_file( &self, _repository: &RepositoryConfig, @@ -161,4 +146,29 @@ impl Storage for BadStorage { ) -> Result>, StorageError> { panic!("This should not be called!") } + + async fn update_repository_config( + &self, + repository: &RepositoryConfig, + config_name: &str, + data: &ConfigType, + ) -> Result<(), StorageError> { + panic!("This should not be called!") + } + + async fn get_repository_config( + &self, + repository: &RepositoryConfig, + config_name: &str, + ) -> Result, StorageError> { + panic!("This should not be called!") + } + + async fn delete_repository_config( + &self, + repository: &RepositoryConfig, + config_name: &str, + ) -> Result<(), StorageError> { + panic!("This should not be called!") + } } diff --git a/backend/src/storage/local_storage/mod.rs b/backend/src/storage/local_storage/mod.rs index d6cfcfad..2ac1d078 100644 --- a/backend/src/storage/local_storage/mod.rs +++ b/backend/src/storage/local_storage/mod.rs @@ -3,13 +3,14 @@ use std::path::PathBuf; use async_trait::async_trait; use log::{debug, trace, warn}; +use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use serde_json::Value; use tokio::fs::{create_dir, create_dir_all, read_to_string, remove_dir, remove_file, OpenOptions}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::sync::{RwLock, RwLockReadGuard}; -use crate::repository::data::{RepositoryConfig, RepositoryType}; +use crate::repository::settings::{RepositoryConfig, RepositoryType}; use crate::repository::REPOSITORY_CONF_FOLDER; use crate::storage::error::StorageError; use crate::storage::error::StorageError::RepositoryMissing; @@ -259,61 +260,6 @@ impl Storage for LocalStorage { return Ok(()); } - async fn update_repository_config( - &self, - repository: &RepositoryConfig, - file: &str, - data: &Option, - ) -> Result<(), StorageError> { - let repositories = self.repositories.write().await; - if !repositories.contains_key(&repository.name) { - return Err(RepositoryMissing); - } - let conf = self - .get_repository_folder(&repository.name) - .join(REPOSITORY_CONF_FOLDER) - .join(file); - - if data.is_none() { - remove_file(&conf).await?; - } else if let Some(value) = data { - let file = OpenOptions::new() - .create(true) - .open(&conf) - .await? - .into_std() - .await; - serde_json::to_writer_pretty(file, value)?; - } - return Ok(()); - } - - async fn get_repository_config( - &self, - repository: &RepositoryConfig, - file: &str, - ) -> Result, StorageError> { - let repositories = self.repositories.write().await; - if !repositories.contains_key(&repository.name) { - return Err(RepositoryMissing); - } - let conf = self - .get_repository_folder(&repository.name) - .join(REPOSITORY_CONF_FOLDER) - .join(file); - if !conf.exists() { - return Ok(None); - } - let file = OpenOptions::new() - .read(true) - .open(&conf) - .await? - .into_std() - .await; - - Ok(serde_json::from_reader(file)?) - } - async fn save_file( &self, repository: &RepositoryConfig, @@ -423,4 +369,64 @@ impl Storage for LocalStorage { file.read_to_end(&mut bytes).await?; Ok(Some(bytes)) } + + async fn update_repository_config( + &self, + repository: &RepositoryConfig, + config_name: &str, + data: &ConfigType, + ) -> Result<(), StorageError> { + let mut repositories = self.repositories.write().await; + if !repositories.contains_key(&repository.name) { + return Err(StorageError::RepositoryMissing); + } + let buf = self + .get_repository_folder(repository.name.as_str()) + .join(".config") + .join(config_name); + let mut file = OpenOptions::new() + .write(true) + .create(true) + .open(buf) + .await?; + file.write_all(serde_json::to_string(data).unwrap().as_bytes()) + .await?; + return Ok(()); + } + + async fn get_repository_config( + &self, + repository: &RepositoryConfig, + config_name: &str, + ) -> Result, StorageError> { + let buf = self + .get_repository_folder(repository.name.as_str()) + .join(".config") + .join(config_name); + if !buf.exists() { + Ok(None) + } else { + let string = read_to_string(buf).await.map_err(StorageError::IOError)?; + serde_json::from_str(&string) + .map_err(StorageError::JSONError) + .map(Some) + } + } + + async fn delete_repository_config( + &self, + repository: &RepositoryConfig, + config_name: &str, + ) -> Result<(), StorageError> { + let mut repositories = self.repositories.write().await; + if !repositories.contains_key(&repository.name) { + return Err(StorageError::RepositoryMissing); + } + let buf = self + .get_repository_folder(repository.name.as_str()) + .join(".config") + .join(config_name); + remove_file(buf).await?; + return Ok(()); + } } diff --git a/backend/src/storage/mod.rs b/backend/src/storage/mod.rs index f034fcf0..7d51087a 100644 --- a/backend/src/storage/mod.rs +++ b/backend/src/storage/mod.rs @@ -1,8 +1,10 @@ use async_trait::async_trait; +use serde::de::DeserializeOwned; +use serde::Serialize; use serde_json::Value; use tokio::sync::RwLockReadGuard; -use crate::repository::data::{RepositoryConfig, RepositoryType}; +use crate::repository::settings::{RepositoryConfig, RepositoryType}; use crate::storage::bad_storage::BadStorage; use crate::storage::error::StorageError; use crate::storage::file::{StorageFile, StorageFileResponse}; @@ -144,35 +146,6 @@ impl Storage for DynamicStorage { } } - async fn update_repository_config( - &self, - repository: &RepositoryConfig, - file: &str, - data: &Option, - ) -> Result<(), StorageError> { - match self { - DynamicStorage::LocalStorage(local) => { - local.update_repository_config(repository, file, data).await - } - DynamicStorage::BadStorage(bad) => { - bad.update_repository_config(repository, file, data).await - } - } - } - - async fn get_repository_config( - &self, - repository: &RepositoryConfig, - file: &str, - ) -> Result, StorageError> { - match self { - DynamicStorage::LocalStorage(local) => { - local.get_repository_config(repository, file).await - } - DynamicStorage::BadStorage(bad) => bad.get_repository_config(repository, file).await, - } - } - async fn save_file( &self, repository: &RepositoryConfig, @@ -234,4 +207,55 @@ impl Storage for DynamicStorage { DynamicStorage::BadStorage(bad) => bad.get_file(repository, location).await, } } + + async fn update_repository_config( + &self, + repository: &RepositoryConfig, + config_name: &str, + data: &ConfigType, + ) -> Result<(), StorageError> { + match self { + DynamicStorage::LocalStorage(local) => { + local + .update_repository_config(repository, config_name, data) + .await + } + DynamicStorage::BadStorage(bad) => { + bad.update_repository_config(repository, config_name, data) + .await + } + } + } + + async fn get_repository_config( + &self, + repository: &RepositoryConfig, + config_name: &str, + ) -> Result, StorageError> { + match self { + DynamicStorage::LocalStorage(local) => { + local.get_repository_config(repository, config_name).await + } + DynamicStorage::BadStorage(bad) => { + bad.get_repository_config(repository, config_name).await + } + } + } + + async fn delete_repository_config( + &self, + repository: &RepositoryConfig, + config_name: &str, + ) -> Result<(), StorageError> { + match self { + DynamicStorage::LocalStorage(local) => { + local + .delete_repository_config(repository, config_name) + .await + } + DynamicStorage::BadStorage(bad) => { + bad.delete_repository_config(repository, config_name).await + } + } + } } diff --git a/backend/src/storage/models.rs b/backend/src/storage/models.rs index c3506733..316c05b9 100644 --- a/backend/src/storage/models.rs +++ b/backend/src/storage/models.rs @@ -1,11 +1,12 @@ use std::fmt::{Debug, Display, Formatter}; use async_trait::async_trait; +use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use serde_json::Value; use tokio::sync::RwLockReadGuard; -use crate::repository::data::{RepositoryConfig, RepositoryType}; +use crate::repository::settings::{RepositoryConfig, RepositoryType}; use crate::storage::error::StorageError; use crate::storage::file::{StorageFile, StorageFileResponse}; use crate::storage::local_storage::LocalStorage; @@ -151,21 +152,6 @@ pub trait Storage: Send + Sync { ) -> Result>, StorageError>; async fn update_repository(&self, repository: RepositoryConfig) -> Result<(), StorageError>; - /// Locks the Repositories for updating - /// Keeps all config files in .config - async fn update_repository_config( - &self, - repository: &RepositoryConfig, - file: &str, - data: &Option, - ) -> Result<(), StorageError>; - /// Gets a Repository Config - async fn get_repository_config( - &self, - repository: &RepositoryConfig, - file: &str, - ) -> Result, StorageError>; - /// Saves a File to a location /// Will overwrite any data found async fn save_file( @@ -200,4 +186,25 @@ pub trait Storage: Send + Sync { repository: &RepositoryConfig, location: &str, ) -> Result>, StorageError>; + + /// Locks the Repositories for updating + /// Keeps all config files in .config + async fn update_repository_config( + &self, + repository: &RepositoryConfig, + config_name: &str, + data: &ConfigType, + ) -> Result<(), StorageError>; + /// Gets a Repository Config + async fn get_repository_config( + &self, + repository: &RepositoryConfig, + config_name: &str, + ) -> Result, StorageError>; + /// Delete Repository Config + async fn delete_repository_config( + &self, + repository: &RepositoryConfig, + config_name: &str, + ) -> Result<(), StorageError>; } diff --git a/backend/src/system/permissions/mod.rs b/backend/src/system/permissions/mod.rs index 7a63ec0c..8e963eb9 100644 --- a/backend/src/system/permissions/mod.rs +++ b/backend/src/system/permissions/mod.rs @@ -1,9 +1,8 @@ use serde::{Deserialize, Serialize}; use thiserror::Error; -use crate::repository::data::RepositoryConfig; use crate::repository::settings::security::Visibility; -use crate::repository::settings::Policy; +use crate::repository::settings::{Policy, RepositoryConfig}; use crate::system::permissions::PermissionError::{RepositoryClassifier, StorageClassifier}; pub mod options; diff --git a/backend/src/system/permissions/options.rs b/backend/src/system/permissions/options.rs index 7ff8225e..1bb22532 100644 --- a/backend/src/system/permissions/options.rs +++ b/backend/src/system/permissions/options.rs @@ -6,8 +6,8 @@ use actix_web::ResponseError; use serde_json::json; use crate::error::internal_error::InternalError; -use crate::repository::data::RepositoryConfig; use crate::repository::settings::security::Visibility; +use crate::repository::settings::RepositoryConfig; use crate::system::permissions::{can_deploy, can_read}; use crate::system::user::UserModel; From 81d8ef893f67ceec2a26e8be0459f1bb0e20024a Mon Sep 17 00:00:00 2001 From: Wyatt Jacob Herkamp Date: Tue, 31 May 2022 14:30:14 -0400 Subject: [PATCH 10/76] added repository update and cleaned up settings some more --- backend/Cargo.toml | 3 + backend/src/bin/nitro_repo_full.rs | 10 +- backend/src/install/mod.rs | 4 +- backend/src/lib.rs | 11 +- backend/src/repository/maven/mod.rs | 3 +- backend/src/repository/mod.rs | 2 +- backend/src/repository/nitro/mod.rs | 1 + .../src/repository/nitro/post_deploy/mod.rs | 0 backend/src/repository/settings/badge.rs | 62 ++++ backend/src/repository/settings/frontend.rs | 93 ++---- backend/src/repository/settings/mod.rs | 21 +- .../settings/{webhook.rs => post_deploy.rs} | 77 ++--- backend/src/repository/settings/security.rs | 14 - backend/src/repository/web/mod.rs | 3 +- backend/src/repository/web/multi/admin.rs | 269 +++++++++++++++++- backend/src/repository/web/multi/helpers.rs | 11 + backend/src/repository/web/multi/mod.rs | 18 +- backend/src/storage/local_storage/mod.rs | 4 +- backend/src/system/permissions/mod.rs | 2 +- backend/src/system/permissions/options.rs | 2 +- backend/src/utils.rs | 32 ++- 21 files changed, 485 insertions(+), 157 deletions(-) create mode 100644 backend/src/repository/nitro/post_deploy/mod.rs create mode 100644 backend/src/repository/settings/badge.rs rename backend/src/repository/settings/{webhook.rs => post_deploy.rs} (51%) delete mode 100644 backend/src/repository/settings/security.rs create mode 100644 backend/src/repository/web/multi/helpers.rs diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 040a5d60..dbd44fcd 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -70,6 +70,9 @@ crossterm = "0.23.2" clap = { version = "3.1.15", features = ["derive"] } unicode-width = "0.1.9" semver = "1.0.9" +# Docs +schemars = "0.8.10" + [build-dependencies] vergen = "7.0.0" [features] diff --git a/backend/src/bin/nitro_repo_full.rs b/backend/src/bin/nitro_repo_full.rs index 29b8b478..66d40ddb 100644 --- a/backend/src/bin/nitro_repo_full.rs +++ b/backend/src/bin/nitro_repo_full.rs @@ -20,7 +20,7 @@ use api::settings::load_configs; use api::settings::models::GeneralSettings; use api::storage::multi::MultiStorageController; use api::utils::load_logger; -use api::{frontend, storage, system, NitroRepo}; +use api::{frontend, repository, storage, system, NitroRepo}; #[main] async fn main() -> std::io::Result<()> { @@ -98,9 +98,15 @@ async fn main() -> std::io::Result<()> { .service( web::scope("/admin") .configure(system::web::init_user_manager_routes) - .configure(storage::multi::web::init_admin_routes), + .configure(storage::multi::web::init_admin_routes) + .configure(repository::web::multi::init_admin), ), ) + .service( + web::scope("/nitro_repo/help") + .service(repository::web::multi::helpers::help_update_type), + ) + .configure(repository::web::multi::init_repository_handlers) .configure(frontend::init) }); diff --git a/backend/src/install/mod.rs b/backend/src/install/mod.rs index 3a33059c..c33f1028 100644 --- a/backend/src/install/mod.rs +++ b/backend/src/install/mod.rs @@ -192,7 +192,7 @@ impl Default for App { } } } - +#[allow(unused_mut)] async fn run_app( mut terminal: Terminal>, mut app: App, @@ -226,7 +226,7 @@ async fn run_app( } else { let string = app.database_stage.to_string(); trace!("Database String: {}", &string); - let database_conn = sea_orm::Database::connect(string).await?; + let mut database_conn = sea_orm::Database::connect(string).await?; let schema = Schema::new(database_conn.get_database_backend()); let users = schema.create_table_from_entity(UserEntity); database_conn diff --git a/backend/src/lib.rs b/backend/src/lib.rs index 240ba08e..8ef7f552 100644 --- a/backend/src/lib.rs +++ b/backend/src/lib.rs @@ -1,3 +1,10 @@ +#![allow(clippy::from_over_into)] + +use actix_web::web::Data; +use tokio::sync::RwLock; + +use crate::settings::models::{GeneralSettings, Settings}; + pub mod authentication; pub mod cli; pub mod constants; @@ -11,10 +18,6 @@ pub mod system; pub mod updater; pub mod utils; -use crate::settings::models::{GeneralSettings, Settings}; -use actix_web::web::Data; -use tokio::sync::RwLock; - #[derive(Debug)] pub struct NitroRepo { pub settings: RwLock, diff --git a/backend/src/repository/maven/mod.rs b/backend/src/repository/maven/mod.rs index 271e051a..b93604ff 100644 --- a/backend/src/repository/maven/mod.rs +++ b/backend/src/repository/maven/mod.rs @@ -13,8 +13,7 @@ use crate::repository::handler::RepositoryHandler; use crate::repository::maven::models::Pom; use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; use crate::repository::response::RepoResponse; -use crate::repository::settings::security::Visibility; -use crate::repository::settings::{Policy, RepositoryConfig}; +use crate::repository::settings::{Policy, RepositoryConfig, Visibility}; use crate::storage::file::StorageFileResponse; use crate::storage::models::Storage; use crate::system::permissions::options::CanIDo; diff --git a/backend/src/repository/mod.rs b/backend/src/repository/mod.rs index 2dc8c531..443328a4 100644 --- a/backend/src/repository/mod.rs +++ b/backend/src/repository/mod.rs @@ -24,7 +24,7 @@ pub static REPOSITORY_CONF_BAK: &str = "repository.nitro_repo.bak"; pub async fn get_repository_handler<'a, StorageType: Storage>( storage: RwLockReadGuard<'a, StorageType>, - repository: &str, + repository: &'a str, ) -> Result>, InternalError> { let value = storage.get_repository(repository).await?; if value.is_none() { diff --git a/backend/src/repository/nitro/mod.rs b/backend/src/repository/nitro/mod.rs index 41f2e9f4..dd5285dd 100644 --- a/backend/src/repository/nitro/mod.rs +++ b/backend/src/repository/nitro/mod.rs @@ -6,6 +6,7 @@ use crate::storage::file::StorageFile; use crate::utils::get_current_time; pub mod nitro_repository; +pub mod post_deploy; pub mod utils; #[derive(Serialize, Clone, Debug)] diff --git a/backend/src/repository/nitro/post_deploy/mod.rs b/backend/src/repository/nitro/post_deploy/mod.rs new file mode 100644 index 00000000..e69de29b diff --git a/backend/src/repository/settings/badge.rs b/backend/src/repository/settings/badge.rs new file mode 100644 index 00000000..0e1a1155 --- /dev/null +++ b/backend/src/repository/settings/badge.rs @@ -0,0 +1,62 @@ +use badge_maker::Style; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use crate::repository::settings::RepositoryConfigType; + +#[derive(Debug, Clone, Serialize, JsonSchema, Deserialize)] +pub struct BadgeSettings { + #[serde(default = "BadgeStyle::default")] + pub style: BadgeStyle, + #[serde(default = "default_label_color")] + pub label_color: String, + #[serde(default = "default_color")] + pub color: String, +} + +impl RepositoryConfigType for BadgeSettings { + fn config_name() -> &'static str { + "badge.json" + } +} + +impl Default for BadgeSettings { + fn default() -> Self { + BadgeSettings { + style: Default::default(), + label_color: default_label_color(), + color: default_color(), + } + } +} + +fn default_color() -> String { + "#33B5E5".to_string() +} + +fn default_label_color() -> String { + "#555".to_string() +} + +#[derive(Debug, Clone, Serialize, JsonSchema, Deserialize)] +pub enum BadgeStyle { + Flat, + FlatSquare, + Plastic, +} + +impl Default for BadgeStyle { + fn default() -> Self { + BadgeStyle::Flat + } +} + +impl BadgeStyle { + pub fn to_badge_maker_style(&self) -> badge_maker::Style { + match self { + BadgeStyle::Flat => Style::Flat, + BadgeStyle::FlatSquare => Style::FlatSquare, + BadgeStyle::Plastic => Style::Plastic, + } + } +} diff --git a/backend/src/repository/settings/frontend.rs b/backend/src/repository/settings/frontend.rs index f650f8f5..5cab156f 100644 --- a/backend/src/repository/settings/frontend.rs +++ b/backend/src/repository/settings/frontend.rs @@ -1,89 +1,36 @@ -use badge_maker::Style; +use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::repository::settings::RepositoryConfigType; -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Frontend { - #[serde(default = "PageProvider::default")] - pub page_provider: PageProvider, - #[serde(default)] - pub description: String, -} - -impl RepositoryConfigType for Frontend { - fn config_name() -> &'static str { - "frontend.json" - } -} -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum BadgeStyle { - Flat, - FlatSquare, - Plastic, +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)] +pub enum PageProvider { + // Do not create a page for this projects in this repository + None, + /// The README is pulled from Github + ReadmeGit, + /// The README is sent to the repository + ReadmeSent, } -impl Default for BadgeStyle { +impl Default for PageProvider { fn default() -> Self { - BadgeStyle::Flat - } -} - -impl BadgeStyle { - pub fn to_badge_maker_style(&self) -> badge_maker::Style { - match self { - BadgeStyle::Flat => Style::Flat, - BadgeStyle::FlatSquare => Style::FlatSquare, - BadgeStyle::Plastic => Style::Plastic, - } + PageProvider::None } } -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct BadgeSettings { - #[serde(default = "BadgeStyle::default")] - pub style: BadgeStyle, - #[serde(default = "default_label_color")] - pub label_color: String, - #[serde(default = "default_color")] - pub color: String, +/// Frontend Settings +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +pub struct Frontend { + pub page_provider: PageProvider, + /// The Description of the Repository + #[serde(default)] + pub description: String, } -impl RepositoryConfigType for BadgeSettings { +impl RepositoryConfigType for Frontend { fn config_name() -> &'static str { - "badge.json" - } -} - -impl Default for BadgeSettings { - fn default() -> Self { - BadgeSettings { - style: Default::default(), - label_color: default_label_color(), - color: default_color(), - } - } -} - -fn default_color() -> String { - "#33B5E5".to_string() -} - -fn default_label_color() -> String { - "#555".to_string() -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum PageProvider { - None, - README, - ReadmeGit, - ReadmeSent, -} - -impl PageProvider { - fn default() -> Self { - PageProvider::None + "frontend.json" } } diff --git a/backend/src/repository/settings/mod.rs b/backend/src/repository/settings/mod.rs index e3c8cf1d..96d97568 100644 --- a/backend/src/repository/settings/mod.rs +++ b/backend/src/repository/settings/mod.rs @@ -4,12 +4,24 @@ use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use crate::error::internal_error::InternalError; -use crate::repository::settings::security::Visibility; use crate::storage::models::Storage; +pub mod badge; pub mod frontend; -pub mod security; -pub mod webhook; +pub mod post_deploy; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, strum_macros::EnumString)] +pub enum Visibility { + Public, + Private, + Hidden, +} + +impl Default for Visibility { + fn default() -> Self { + Visibility::Public + } +} #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, strum_macros::EnumString)] pub enum Policy { @@ -109,4 +121,7 @@ impl RepositoryConfig { /// Represents a Repository Setting group. That is not apart of the core config set pub trait RepositoryConfigType: Send + Sync + Clone + Debug + Serialize + DeserializeOwned { fn config_name() -> &'static str; + fn from_slice_json(slice: &[u8]) -> Result { + serde_json::from_slice(slice) + } } diff --git a/backend/src/repository/settings/webhook.rs b/backend/src/repository/settings/post_deploy.rs similarity index 51% rename from backend/src/repository/settings/webhook.rs rename to backend/src/repository/settings/post_deploy.rs index baf0fe9d..e4002e31 100644 --- a/backend/src/repository/settings/webhook.rs +++ b/backend/src/repository/settings/post_deploy.rs @@ -1,8 +1,22 @@ -use serde::{Deserialize, Serialize}; -use serde_json::Value; -use std::collections::HashMap; use std::ops::Deref; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +use crate::repository::settings::RepositoryConfigType; + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct PostDeployTasks { + pub report_generation: ReportGeneration, + pub webhooks: Vec, +} + +impl RepositoryConfigType for PostDeployTasks { + fn config_name() -> &'static str { + "post_deploy.json" + } +} + #[derive(Serialize, Deserialize, Clone, Debug)] pub enum ReportValues { DeployerUsername, @@ -15,53 +29,48 @@ pub struct ReportGeneration { pub values: Vec, } +impl Default for ReportGeneration { + fn default() -> Self { + ReportGeneration { + active: true, + values: vec!["DeployerUsername".to_string(), "Time".to_string()], + } + } +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub enum WebhookHandlerConfig {} + #[derive(Serialize, Deserialize, Clone, Debug)] pub struct Webhook { - pub id: String, - pub handler: String, - pub settings: HashMap, + pub id: Uuid, + pub handler: WebhookHandlerConfig, } impl PartialEq for Webhook { fn eq(&self, other: &Self) -> bool { - other.id.eq_ignore_ascii_case(&self.id) + other.id.eq(&self.id) } } -impl PartialEq for Webhook { - fn eq(&self, other: &String) -> bool { - self.id.eq(other) - } -} - -impl Default for ReportGeneration { - fn default() -> Self { - ReportGeneration { - active: true, - values: vec!["DeployerUsername".to_string(), "Time".to_string()], - } +impl PartialEq for Webhook { + fn eq(&self, other: &Uuid) -> bool { + other.eq(&self.id) } } -#[derive(Debug, Deserialize, Serialize, Clone, Default)] -pub struct DeploySettings { - #[serde(default)] - pub report_generation: ReportGeneration, - #[serde(default)] - pub webhooks: Vec, -} - -impl DeploySettings { - pub fn add_webhook(&mut self, webhook: Webhook) { - for x in self.webhooks.iter_mut() { - if x.deref().eq(&webhook) { - //TODO update webhook properties - return; +impl PostDeployTasks { + /// If the Webhook by id already exists. It will replace it via std::mem::replace + pub fn add_webhook(&mut self, webhook: Webhook) -> Option { + for web in self.webhooks.iter_mut() { + if web.deref().eq(&webhook) { + return Some(std::mem::replace(web, webhook)); } } self.webhooks.push(webhook); + None } - pub fn remove_hook(&mut self, webhook: String) -> Option { + pub fn remove_hook(&mut self, webhook: Uuid) -> Option { let option = self.webhooks.iter().position(|x| x.eq(&webhook)); if let Some(value) = option { Some(self.webhooks.remove(value)) diff --git a/backend/src/repository/settings/security.rs b/backend/src/repository/settings/security.rs deleted file mode 100644 index 2f705355..00000000 --- a/backend/src/repository/settings/security.rs +++ /dev/null @@ -1,14 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, strum_macros::EnumString)] -pub enum Visibility { - Public, - Private, - Hidden, -} - -impl Default for Visibility { - fn default() -> Self { - Visibility::Public - } -} diff --git a/backend/src/repository/web/mod.rs b/backend/src/repository/web/mod.rs index ef3504b3..141fa53a 100644 --- a/backend/src/repository/web/mod.rs +++ b/backend/src/repository/web/mod.rs @@ -1,7 +1,8 @@ use serde::Serialize; use crate::error::internal_error::InternalError; -use crate::repository::settings::frontend::{BadgeSettings, Frontend}; +use crate::repository::settings::badge::BadgeSettings; +use crate::repository::settings::frontend::Frontend; use crate::repository::settings::RepositoryConfig; use crate::storage::models::Storage; diff --git a/backend/src/repository/web/multi/admin.rs b/backend/src/repository/web/multi/admin.rs index e8bebeb7..dcdd40d7 100644 --- a/backend/src/repository/web/multi/admin.rs +++ b/backend/src/repository/web/multi/admin.rs @@ -1,17 +1,26 @@ use std::ops::Deref; use actix_web::http::StatusCode; -use actix_web::{delete, get, post, web, HttpResponse}; +use actix_web::{delete, get, post, put, web, HttpResponse}; +use badge_maker::Badge; +use schemars::schema::RootSchema; +use schemars::schema_for; use sea_orm::DatabaseConnection; use serde::Deserialize; +use serde_json::Value; use crate::authentication::Authentication; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; +use crate::repository::settings::badge::BadgeSettings; +use crate::repository::settings::frontend::Frontend; +use crate::repository::settings::{ + badge, Policy, RepositoryConfig, RepositoryConfigType, Visibility, +}; use crate::repository::web::RepositoryResponse; use crate::repository::RepositoryType; use crate::storage::error::StorageError; -use crate::storage::models::Storage; +use crate::storage::models::{Storage, StorageType}; use crate::storage::multi::MultiStorageController; use crate::system::permissions::options::CanIDo; use crate::system::user::UserModel; @@ -148,3 +157,259 @@ pub async fn delete_repository( .map_err(InternalError::from)?; Ok(HttpResponse::NoContent().finish()) } + +#[derive(Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum RepositoryConfigTypeEnum { + Frontend, + Badge, +} + +impl RepositoryConfigTypeEnum { + pub async fn update( + &self, + storage: &StorageType, + repository: &RepositoryConfig, + bytes: &[u8], + ) -> actix_web::Result<()> { + match self { + RepositoryConfigTypeEnum::Frontend => { + let frontend = Frontend::from_slice_json(bytes).map_err(|e| { + APIError::from(("Invalid Frontend Config ", StatusCode::BAD_REQUEST)) + })?; + repository.save_config(storage, Some(&frontend)).await?; + } + RepositoryConfigTypeEnum::Badge => { + let badge = BadgeSettings::from_slice_json(bytes).map_err(|e| { + APIError::from(("Invalid Badge Config ", StatusCode::BAD_REQUEST)) + })?; + repository.save_config(storage, Some(&badge)).await?; + } + } + Ok(()) + } + pub async fn get_config( + &self, + storage: &StorageType, + repository: &RepositoryConfig, + ) -> actix_web::Result> { + match self { + RepositoryConfigTypeEnum::Frontend => { + let option: Option = repository.get_config(storage).await?; + if let Some(value) = option { + Ok(Some( + serde_json::to_value(value).map_err(InternalError::JSONError)?, + )) + } else { + Ok(None) + } + } + RepositoryConfigTypeEnum::Badge => { + let option: Option = repository.get_config(storage).await?; + if let Some(value) = option { + Ok(Some( + serde_json::to_value(value).map_err(InternalError::JSONError)?, + )) + } else { + Ok(None) + } + } + } + } + pub async fn remove_config( + &self, + storage: &StorageType, + repository: &RepositoryConfig, + ) -> actix_web::Result<()> { + match self { + RepositoryConfigTypeEnum::Frontend => { + repository + .save_config::(storage, None) + .await?; + Ok(()) + } + RepositoryConfigTypeEnum::Badge => { + repository + .save_config::(storage, None) + .await?; + Ok(()) + } + } + } + pub fn describe(&self) -> RootSchema { + match self { + RepositoryConfigTypeEnum::Frontend => schema_for!(Frontend), + RepositoryConfigTypeEnum::Badge => schema_for!(BadgeSettings), + } + } +} + +#[put("/repositories/{storage_name}/{repository_name}/{config}")] +pub async fn update_repository_config( + storage_handler: web::Data, + database: web::Data, + auth: Authentication, + path_params: web::Path<(String, String, RepositoryConfigTypeEnum)>, + bytes: web::Bytes, +) -> actix_web::Result { + let user: UserModel = auth.get_user(&database).await??; + user.can_i_edit_repos()?; + let (storage_name, repository_name, update) = path_params.into_inner(); + let storage = storage_handler + .get_storage_by_name(&storage_name) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::storage_not_found())?; + let repository = storage + .get_repository(&repository_name) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::repository_not_found())?; + let bytes = bytes.to_vec(); + update.update(storage.deref(), &repository, &bytes).await?; + Ok(HttpResponse::NoContent().finish()) +} + +#[get("/repositories/{storage_name}/{repository_name}/{config}")] +pub async fn get_repository_config( + storage_handler: web::Data, + database: web::Data, + auth: Authentication, + path_params: web::Path<(String, String, RepositoryConfigTypeEnum)>, +) -> actix_web::Result { + let user: UserModel = auth.get_user(&database).await??; + user.can_i_edit_repos()?; + let (storage_name, repository_name, update) = path_params.into_inner(); + let storage = storage_handler + .get_storage_by_name(&storage_name) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::storage_not_found())?; + let repository = storage + .get_repository(&repository_name) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::repository_not_found())?; + let config = update.get_config(storage.deref(), &repository).await?; + if let Some(config) = config { + Ok(HttpResponse::Ok().json(config)) + } else { + Ok(HttpResponse::NotFound().finish()) + } +} + +#[delete("/repositories/{storage_name}/{repository_name}/{config}")] +pub async fn remove_repository_config( + storage_handler: web::Data, + database: web::Data, + auth: Authentication, + path_params: web::Path<(String, String, RepositoryConfigTypeEnum)>, +) -> actix_web::Result { + let user: UserModel = auth.get_user(&database).await??; + user.can_i_edit_repos()?; + let (storage_name, repository_name, update) = path_params.into_inner(); + let storage = storage_handler + .get_storage_by_name(&storage_name) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::storage_not_found())?; + let repository = storage + .get_repository(&repository_name) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::repository_not_found())?; + update.remove_config(storage.deref(), &repository).await?; + Ok(HttpResponse::NoContent().finish()) +} + +#[put("/repositories/{storage_name}/{repository_name}/main/visibility/{visibility}")] +pub async fn update_repository_visibility( + storage_handler: web::Data, + database: web::Data, + auth: Authentication, + path_params: web::Path<(String, String, Visibility)>, +) -> actix_web::Result { + let user: UserModel = auth.get_user(&database).await??; + user.can_i_edit_repos()?; + let (storage_name, repository_name, visibility) = path_params.into_inner(); + let storage = storage_handler + .get_storage_by_name(&storage_name) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::storage_not_found())?; + let mut repository = storage + .get_repository(&repository_name) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::repository_not_found())? + .deref() + .clone(); + repository.visibility = visibility; + storage + .update_repository(repository) + .await + .map_err(InternalError::from)?; + + Ok(HttpResponse::NoContent().finish()) +} + +#[put("/repositories/{storage_name}/{repository_name}/main/active/{active}")] +pub async fn update_repository_active( + storage_handler: web::Data, + database: web::Data, + auth: Authentication, + path_params: web::Path<(String, String, bool)>, +) -> actix_web::Result { + let user: UserModel = auth.get_user(&database).await??; + user.can_i_edit_repos()?; + let (storage_name, repository_name, active) = path_params.into_inner(); + let storage = storage_handler + .get_storage_by_name(&storage_name) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::storage_not_found())?; + let mut repository = storage + .get_repository(&repository_name) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::repository_not_found())? + .deref() + .clone(); + repository.active = active; + storage + .update_repository(repository) + .await + .map_err(InternalError::from)?; + + Ok(HttpResponse::NoContent().finish()) +} + +#[put("/repositories/{storage_name}/{repository_name}/main/policy/{policy}")] +pub async fn update_repository_policy( + storage_handler: web::Data, + database: web::Data, + auth: Authentication, + path_params: web::Path<(String, String, Policy)>, +) -> actix_web::Result { + let user: UserModel = auth.get_user(&database).await??; + user.can_i_edit_repos()?; + let (storage_name, repository_name, policy) = path_params.into_inner(); + let storage = storage_handler + .get_storage_by_name(&storage_name) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::storage_not_found())?; + let mut repository = storage + .get_repository(&repository_name) + .await + .map_err(InternalError::from)? + .ok_or_else(|| APIError::repository_not_found())? + .deref() + .clone(); + repository.policy = policy; + storage + .update_repository(repository) + .await + .map_err(InternalError::from)?; + Ok(HttpResponse::NoContent().finish()) +} diff --git a/backend/src/repository/web/multi/helpers.rs b/backend/src/repository/web/multi/helpers.rs new file mode 100644 index 00000000..f1730ff7 --- /dev/null +++ b/backend/src/repository/web/multi/helpers.rs @@ -0,0 +1,11 @@ +use actix_web::{get, web, HttpResponse}; + +use crate::repository::web::multi::admin::RepositoryConfigTypeEnum; + +#[get("/repositories/config/type/{config}")] +pub async fn help_update_type( + path_params: web::Path, +) -> actix_web::Result { + let schema = path_params.into_inner().describe(); + Ok(HttpResponse::Ok().json(schema)) +} diff --git a/backend/src/repository/web/multi/mod.rs b/backend/src/repository/web/multi/mod.rs index b041aefc..c808fb2f 100644 --- a/backend/src/repository/web/multi/mod.rs +++ b/backend/src/repository/web/multi/mod.rs @@ -1,9 +1,12 @@ +use std::ops::Deref; + use actix_web::web; pub mod admin; +pub mod helpers; pub mod repository_handler; -pub fn init(cfg: &mut web::ServiceConfig) { +pub fn init_repository_handlers(cfg: &mut web::ServiceConfig) { cfg.service( web::resource([ "/storages/{storage}/{repository}", @@ -17,3 +20,16 @@ pub fn init(cfg: &mut web::ServiceConfig) { .route(web::post().to(repository_handler::post_repository)), ); } + +pub fn init_admin(cfg: &mut web::ServiceConfig) { + cfg.service(admin::get_repository) + .service(admin::get_repositories) + .service(admin::create_repository) + .service(admin::delete_repository) + .service(admin::update_repository_config) + .service(admin::get_repository_config) + .service(admin::remove_repository_config) + .service(admin::update_repository_active) + .service(admin::update_repository_policy) + .service(admin::update_repository_visibility); +} diff --git a/backend/src/storage/local_storage/mod.rs b/backend/src/storage/local_storage/mod.rs index 2ac1d078..f6ca5973 100644 --- a/backend/src/storage/local_storage/mod.rs +++ b/backend/src/storage/local_storage/mod.rs @@ -376,7 +376,7 @@ impl Storage for LocalStorage { config_name: &str, data: &ConfigType, ) -> Result<(), StorageError> { - let mut repositories = self.repositories.write().await; + let repositories = self.repositories.write().await; if !repositories.contains_key(&repository.name) { return Err(StorageError::RepositoryMissing); } @@ -418,7 +418,7 @@ impl Storage for LocalStorage { repository: &RepositoryConfig, config_name: &str, ) -> Result<(), StorageError> { - let mut repositories = self.repositories.write().await; + let repositories = self.repositories.write().await; if !repositories.contains_key(&repository.name) { return Err(StorageError::RepositoryMissing); } diff --git a/backend/src/system/permissions/mod.rs b/backend/src/system/permissions/mod.rs index 8e963eb9..12225f7c 100644 --- a/backend/src/system/permissions/mod.rs +++ b/backend/src/system/permissions/mod.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use thiserror::Error; -use crate::repository::settings::security::Visibility; +use crate::repository::settings::Visibility; use crate::repository::settings::{Policy, RepositoryConfig}; use crate::system::permissions::PermissionError::{RepositoryClassifier, StorageClassifier}; diff --git a/backend/src/system/permissions/options.rs b/backend/src/system/permissions/options.rs index 1bb22532..327ab5c9 100644 --- a/backend/src/system/permissions/options.rs +++ b/backend/src/system/permissions/options.rs @@ -6,8 +6,8 @@ use actix_web::ResponseError; use serde_json::json; use crate::error::internal_error::InternalError; -use crate::repository::settings::security::Visibility; use crate::repository::settings::RepositoryConfig; +use crate::repository::settings::Visibility; use crate::system::permissions::{can_deploy, can_read}; use crate::system::user::UserModel; diff --git a/backend/src/utils.rs b/backend/src/utils.rs index ea9c8673..bef8d148 100644 --- a/backend/src/utils.rs +++ b/backend/src/utils.rs @@ -1,6 +1,8 @@ -use std::fs::read; +use std::borrow::Cow; +use std::fs::OpenOptions; +use std::io::Read; use std::ops::Add; -use std::path::{Path, PathBuf}; +use std::path::Path; use actix_web::http::header::HeaderMap; use chrono::{DateTime, Duration, Local}; @@ -17,7 +19,12 @@ pub fn load_logger>(logger: T) { Mode::Release => "log-release.json", Mode::Install => "log-install.json", }; - let config: Config = serde_json::from_str(Resources::file_get_string(file).as_str()).unwrap(); + let config: Config = serde_json::from_slice( + Resources::file_get(file) + .as_ref() + .expect("Unable to load the logger!"), + ) + .unwrap(); NitroLogger::load(config, LoggerBuilders::default()).unwrap(); } #[derive(RustEmbed)] @@ -25,18 +32,19 @@ pub fn load_logger>(logger: T) { pub struct Resources; impl Resources { - pub fn file_get(file: &str) -> Vec { + pub fn file_get<'a>(file: &str) -> Result, InternalError> { let buf = Path::new("resources").join(file); if buf.exists() { - read(buf).unwrap() + let mut buffer = Vec::new(); + OpenOptions::new() + .read(true) + .open(buf)? + .read_to_end(&mut buffer)?; + Ok(Cow::Owned(buffer)) } else { - Resources::get(file).unwrap().data.to_vec() + Ok(Resources::get(file).unwrap().data) } } - pub fn file_get_string(file: &str) -> String { - let vec = Resources::file_get(file); - String::from_utf8(vec).unwrap() - } } pub fn get_current_time() -> i64 { @@ -64,7 +72,3 @@ pub fn get_accept(header_map: &HeaderMap) -> Result, InternalErro let header = x.unwrap().to_string(); Ok(Some(header)) } - -pub fn get_storage_location() -> PathBuf { - PathBuf::from("./") -} From 259fe3e912dfa56f8be21325baf8a048a30843db Mon Sep 17 00:00:00 2001 From: Wyatt Jacob Herkamp Date: Wed, 1 Jun 2022 10:25:14 -0400 Subject: [PATCH 11/76] Removed a bunch of session manager creations --- backend/src/authentication/middleware.rs | 233 +++++++++++------------ 1 file changed, 115 insertions(+), 118 deletions(-) diff --git a/backend/src/authentication/middleware.rs b/backend/src/authentication/middleware.rs index 4f90cecf..c4447a1f 100644 --- a/backend/src/authentication/middleware.rs +++ b/backend/src/authentication/middleware.rs @@ -69,134 +69,131 @@ where // Move all into an Async Box. Box::pin(async move { //Step One Find the Authorization - let (authentication, session): (Authentication, Option) = if let Some(cookie) = - req.cookie("session") - { - //Check for the Session Cookie - let session_manager: &web::Data = req.app_data().unwrap(); - trace!("Cookie sent {}", cookie.encoded().to_string()); - let session = session_manager - .retrieve_session(cookie.value()) - .await - .unwrap(); - if session.is_none() { - //Create a new session and go with it! - let _session_manager: &web::Data = req.app_data().unwrap(); - if let Some(origin) = req.headers().get(ORIGIN) { - trace!( - "Cookie {} not found. Creating a new Session for {}", - cookie.value(), - origin.to_str().unwrap_or("Bad Origin") - ); - let session_manager: &web::Data = req.app_data().unwrap(); - let session = session_manager.create_session().await.unwrap(); - (Authentication::Session(session.clone()), Some(session)) - } else { - (Authentication::NoIdentification, Option::None) - } - } else if let Some(mut session) = session { - if session.expiration <= SystemTime::UNIX_EPOCH { - session = session_manager - .re_create_session(&session.token) - .await - .unwrap(); - } - (Authentication::Session(session.clone()), Option::None) - } else { - (Authentication::NoIdentification, Option::None) - } - } else if let Some(header) = req.headers().get(AUTHORIZATION) { - //If it is an Authorization Header pull Database from App Data - let database: &web::Data = req.app_data().unwrap(); - // Convert Header to String - let header_value = header.to_str().unwrap(); - trace!("Authorization Header {}", &header_value); - - let split = header_value.split(' ').collect::>(); - if split.len() != 2 { - debug!("Invalid Authorization Header!"); - // If the length is not correct. It is an invalid authorization. But let request continue - (Authentication::NoIdentification, Option::None) - } else { - let value = split.get(1).unwrap(); - let auth_type = split.get(0).unwrap(); - // If its a Bearer use the token System - if auth_type.eq(&"Bearer") { - trace!("Authorization Bearer (token)"); - - let auth_token = auth_token::get_by_token(value, database) - .await - .map_err(internal_server_error)?; - - if let Some(token) = auth_token { - (Authentication::AuthToken(token), Option::None) + let session_manager: &web::Data = req.app_data().unwrap(); + + let (authentication, session): (Authentication, Option) = + if let Some(cookie) = req.cookie("session") { + //Check for the Session Cookie + trace!("Cookie sent {}", cookie.encoded().to_string()); + let session = session_manager + .retrieve_session(cookie.value()) + .await + .unwrap(); + if session.is_none() { + //Create a new session and go with it! + if let Some(origin) = req.headers().get(ORIGIN) { + trace!( + "Cookie {} not found. Creating a new Session for {}", + cookie.value(), + origin.to_str().unwrap_or("Bad Origin") + ); + let session = session_manager.create_session().await.unwrap(); + (Authentication::Session(session.clone()), Some(session)) } else { (Authentication::NoIdentification, Option::None) } - } else if auth_type.eq(&"Basic") { - //If its a Basic header. Parse from base64 - let base64 = base64::decode(value).map_err(request_error)?; - let string = String::from_utf8(base64).map_err(request_error)?; - let split = string.split(':').collect::>(); - - if split.len() != 2 { - debug!("Invalid Authorization Basic Header!"); - (Authentication::NoIdentification, Option::None) - } else { - let username = split.get(0).unwrap().to_string(); - let password = split.get(1).unwrap().to_string(); - // Maven will pass everything as a Basic. Setting the username as Token lets you use the token system - if username.eq("token") { - trace!("Authorization Basic token:(token)"); - - // Treat the password as a token - let auth_token = auth_token::get_by_token(&password, database) - .await - .map_err(internal_server_error)?; - if let Some(token) = auth_token { - (Authentication::AuthToken(token), Option::None) - } else { - (Authentication::NoIdentification, Option::None) - } + } else if let Some(mut session) = session { + if session.expiration <= SystemTime::UNIX_EPOCH { + session = session_manager + .re_create_session(&session.token) + .await + .unwrap(); + } + (Authentication::Session(session.clone()), Option::None) + } else { + (Authentication::NoIdentification, Option::None) + } + } else if let Some(header) = req.headers().get(AUTHORIZATION) { + //If it is an Authorization Header pull Database from App Data + let database: &web::Data = req.app_data().unwrap(); + // Convert Header to String + let header_value = header.to_str().unwrap(); + trace!("Authorization Header {}", &header_value); + + let split = header_value.split(' ').collect::>(); + if split.len() != 2 { + debug!("Invalid Authorization Header!"); + // If the length is not correct. It is an invalid authorization. But let request continue + (Authentication::NoIdentification, Option::None) + } else { + let value = split.get(1).unwrap(); + let auth_type = split.get(0).unwrap(); + // If its a Bearer use the token System + if auth_type.eq(&"Bearer") { + trace!("Authorization Bearer (token)"); + + let auth_token = auth_token::get_by_token(value, database) + .await + .map_err(internal_server_error)?; + + if let Some(token) = auth_token { + (Authentication::AuthToken(token), Option::None) } else { - // Treat authorization as normal login - trace!("Authorization Basic username:password"); - let user = verify_login(username, password, database).await?; - if let Ok(user) = user { - trace!("Authorized User"); - (Authentication::Basic(user), None) + (Authentication::NoIdentification, Option::None) + } + } else if auth_type.eq(&"Basic") { + //If its a Basic header. Parse from base64 + let base64 = base64::decode(value).map_err(request_error)?; + let string = String::from_utf8(base64).map_err(request_error)?; + let split = string.split(':').collect::>(); + + if split.len() != 2 { + debug!("Invalid Authorization Basic Header!"); + (Authentication::NoIdentification, Option::None) + } else { + let username = split.get(0).unwrap().to_string(); + let password = split.get(1).unwrap().to_string(); + // Maven will pass everything as a Basic. Setting the username as Token lets you use the token system + if username.eq("token") { + trace!("Authorization Basic token:(token)"); + + // Treat the password as a token + let auth_token = auth_token::get_by_token(&password, database) + .await + .map_err(internal_server_error)?; + if let Some(token) = auth_token { + (Authentication::AuthToken(token), Option::None) + } else { + (Authentication::NoIdentification, Option::None) + } } else { - trace!("Invalid username:password combo"); - (Authentication::NoIdentification, None) + // Treat authorization as normal login + trace!("Authorization Basic username:password"); + let user = verify_login(username, password, database).await?; + if let Ok(user) = user { + trace!("Authorized User"); + (Authentication::Basic(user), None) + } else { + trace!("Invalid username:password combo"); + (Authentication::NoIdentification, None) + } } } + } else { + ( + Authentication::AuthorizationHeaderUnknown( + auth_type.to_string(), + value.to_string(), + ), + None, + ) } - } else { - ( - Authentication::AuthorizationHeaderUnknown( - auth_type.to_string(), - value.to_string(), - ), - None, - ) } - } - } else { - // Try to create a new Session for the user. Could be a first request - // Require a Origin Header for request - if let Some(origin) = req.headers().get(ORIGIN) { - trace!( - "Creating a new Session for {}. ", - origin.to_str().unwrap_or("Bad Origin") - ); - let session_manager: &web::Data = req.app_data().unwrap(); - let session = session_manager.create_session().await.unwrap(); - (Authentication::Session(session.clone()), Some(session)) } else { - warn!("A Not Origin Not Authorized Request was made"); - (Authentication::NoIdentification, Option::None) - } - }; + // Try to create a new Session for the user. Could be a first request + // Require a Origin Header for request + if let Some(origin) = req.headers().get(ORIGIN) { + trace!( + "Creating a new Session for {}. ", + origin.to_str().unwrap_or("Bad Origin") + ); + let session = session_manager.create_session().await.unwrap(); + (Authentication::Session(session.clone()), Some(session)) + } else { + warn!("A Not Origin Not Authorized Request was made"); + (Authentication::NoIdentification, Option::None) + } + }; // Add the authentication Information for the data req.extensions_mut().insert(authentication); // Finish the request From e338877abdb9355d2eb82b93f828c3e3d7c2531b Mon Sep 17 00:00:00 2001 From: Wyatt Jacob Herkamp Date: Fri, 3 Jun 2022 09:00:26 -0400 Subject: [PATCH 12/76] Just a random structure --- backend/src/repository/nitro/post_deploy/mod.rs | 1 + backend/src/system/web/admin.rs | 9 +++++++++ backend/src/system/web/mod.rs | 1 + 3 files changed, 11 insertions(+) create mode 100644 backend/src/system/web/admin.rs diff --git a/backend/src/repository/nitro/post_deploy/mod.rs b/backend/src/repository/nitro/post_deploy/mod.rs index e69de29b..8b137891 100644 --- a/backend/src/repository/nitro/post_deploy/mod.rs +++ b/backend/src/repository/nitro/post_deploy/mod.rs @@ -0,0 +1 @@ + diff --git a/backend/src/system/web/admin.rs b/backend/src/system/web/admin.rs new file mode 100644 index 00000000..c2419d00 --- /dev/null +++ b/backend/src/system/web/admin.rs @@ -0,0 +1,9 @@ +use serde::{Deserialize, Serialize}; + +// struct that derives Serialize and Deserialize contains the number of active storages, number of active repositories, and the number of active users. +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct SystemStatus { + pub active_storages: usize, + pub active_repositories: usize, + pub active_users: usize, +} diff --git a/backend/src/system/web/mod.rs b/backend/src/system/web/mod.rs index 375711f4..7c28bc15 100644 --- a/backend/src/system/web/mod.rs +++ b/backend/src/system/web/mod.rs @@ -1,5 +1,6 @@ use actix_web::web::ServiceConfig; +pub mod admin; pub mod public; pub mod user; From 25613638d9f5c8019472583d2615863d3ca4bc5a Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Tue, 12 Jul 2022 12:03:33 -0400 Subject: [PATCH 13/76] Init New Website (#466) --- .gitignore | 1 + backend/src/authentication/middleware.rs | 2 +- backend/src/storage/multi/mod.rs | 2 +- backend/src/system/web/public.rs | 20 +- frontend/.browserslistrc | 1 + frontend/.editorconfig | 5 + frontend/.eslintrc.js | 8 +- frontend/.gitignore | 22 +- frontend/.nvmrc | 2 +- frontend/.prettierignore | 3 - frontend/.prettierrc | 0 frontend/.prettierrc.json | 1 - frontend/README.md | 4 +- frontend/babel.config.js | 2 +- frontend/balm.config.js | 5 - frontend/components.d.ts | 25 +- frontend/index.html | 50 +- frontend/package-lock.json | 26380 +++------------- frontend/package.json | 56 +- frontend/src/App.vue | 34 +- frontend/src/api/repository/BadgeGen.ts | 1 + frontend/src/components/ArtifactSearch.vue | 48 + frontend/src/components/CreateRepo.vue | 127 - frontend/src/components/CreateStorage.vue | 108 - frontend/src/components/CreateUser.vue | 171 - frontend/src/components/Me.vue | 68 - frontend/src/components/Repositories.vue | 72 - frontend/src/components/Storages.vue | 64 - frontend/src/components/UpdateStorage.vue | 97 - frontend/src/components/UpdateUser.vue | 47 - frontend/src/components/Users.vue | 67 - frontend/src/components/browse/BrowseBox.vue | 98 - .../src/components/common/code/CodeCard.vue | 3 +- .../src/components/common/code/CodeMenu.vue | 4 +- .../src/components/common/forms/Switch.vue | 12 +- .../components/common/list/SearchableList.vue | 6 +- .../components/common/model/NitroModal.vue | 8 +- .../src/components/common/nav/LinkNavItem.vue | 5 +- .../src/components/common/nav/SubNavBar.vue | 3 +- .../src/components/common/nav/SubNavItem.vue | 1 - .../src/components/common/nav/SubNavType.ts | 1 + frontend/src/components/nav/AdminDropBox.vue | 54 +- frontend/src/components/nav/Login.vue | 13 +- frontend/src/components/nav/Navbar.vue | 131 +- .../src/components/project/ViewProject.vue | 43 - .../components/project/badge/ProjectBadge.vue | 106 - .../project/types/maven/MavenProjectInfo.vue | 24 - .../types/maven/copy/MavenProjectCopy.vue | 76 - frontend/src/components/repo/ViewRepo.vue | 81 - .../components/repo/badge/RepositoryBadge.vue | 53 - .../repo/types/maven/MavenRepoInfo.vue | 45 - .../src/components/repo/update/DeployRepo.vue | 84 - .../components/repo/update/FrontendRepo.vue | 170 - .../components/repo/update/GeneralRepo.vue | 216 - .../components/repo/update/SecurityRepo.vue | 62 - .../src/components/repo/update/UpdateRepo.vue | 109 - frontend/src/components/upload/MavenUpload.js | 25 - .../src/components/upload/MavenUpload.vue | 193 - frontend/src/components/upload/PomCreator.ts | 13 - frontend/src/components/upload/PomCreator.vue | 146 - frontend/src/components/user/LoginComp.vue | 87 +- .../components/user/update/PermissionList.vue | 5 +- .../components/user/update/Permissions.vue | 29 +- .../components/user/update/UserGeneral.vue | 78 +- frontend/src/http-common.ts | 35 +- frontend/src/main.ts | 40 +- frontend/src/router/index.ts | 85 +- frontend/src/store/user.ts | 36 +- frontend/src/styles/app.css | 12 - frontend/src/styles/form.css | 105 - frontend/src/styles/forms.css | 22 + frontend/src/styles/main.css | 78 + frontend/src/styles/prism-atom-dark.css | 143 - frontend/src/types/user.ts | 30 + frontend/src/views/Browse.ts | 4 - frontend/src/views/Browse.vue | 170 +- frontend/src/views/Login.vue | 16 - frontend/src/views/Me.vue | 123 - frontend/src/views/Project.vue | 37 - frontend/src/views/Repository.vue | 26 - frontend/src/views/Upload.vue | 40 - frontend/src/views/{Home.vue => admin.vue} | 10 +- frontend/src/views/admin/Admin.vue | 48 - frontend/src/views/admin/ViewRepository.vue | 38 - frontend/src/views/admin/ViewStorage.vue | 33 - frontend/src/views/admin/ViewUser.vue | 42 - frontend/src/views/index.vue | 22 + frontend/src/views/login.vue | 39 + frontend/tailwind.config.js | 19 +- frontend/tsconfig.json | 13 +- frontend/vite.config.ts | 17 +- frontend/vue.config.js | 31 - nitro_repo-api-wrapper/.nvmrc | 1 - nitro_repo-api-wrapper/package-lock.json | 471 - nitro_repo-api-wrapper/package.json | 28 - nitro_repo-api-wrapper/src/NitroRepoAPI.ts | 55 - nitro_repo-api-wrapper/src/index.ts | 9 - .../src/repository/repositoryAdminAPI.ts | 612 - .../src/repository/repositoryTypes.ts | 132 - .../src/repository/repositoryUserAPI.ts | 120 - .../src/storage/storageAPI.ts | 145 - .../src/storage/storageTypes.ts | 15 - .../src/user/adminUserAPI.ts | 231 - nitro_repo-api-wrapper/src/user/userTypes.ts | 41 - .../src/user/userUserAPI.ts | 115 - nitro_repo-api-wrapper/tsconfig.json | 23 - 106 files changed, 5293 insertions(+), 27496 deletions(-) create mode 100644 frontend/.editorconfig delete mode 100644 frontend/.prettierignore create mode 100644 frontend/.prettierrc delete mode 100644 frontend/.prettierrc.json delete mode 100644 frontend/balm.config.js create mode 100644 frontend/src/components/ArtifactSearch.vue delete mode 100644 frontend/src/components/CreateRepo.vue delete mode 100644 frontend/src/components/CreateStorage.vue delete mode 100644 frontend/src/components/CreateUser.vue delete mode 100644 frontend/src/components/Me.vue delete mode 100644 frontend/src/components/Repositories.vue delete mode 100644 frontend/src/components/Storages.vue delete mode 100644 frontend/src/components/UpdateStorage.vue delete mode 100644 frontend/src/components/UpdateUser.vue delete mode 100644 frontend/src/components/Users.vue delete mode 100644 frontend/src/components/browse/BrowseBox.vue delete mode 100644 frontend/src/components/project/ViewProject.vue delete mode 100644 frontend/src/components/project/badge/ProjectBadge.vue delete mode 100644 frontend/src/components/project/types/maven/MavenProjectInfo.vue delete mode 100644 frontend/src/components/project/types/maven/copy/MavenProjectCopy.vue delete mode 100644 frontend/src/components/repo/ViewRepo.vue delete mode 100644 frontend/src/components/repo/badge/RepositoryBadge.vue delete mode 100644 frontend/src/components/repo/types/maven/MavenRepoInfo.vue delete mode 100644 frontend/src/components/repo/update/DeployRepo.vue delete mode 100644 frontend/src/components/repo/update/FrontendRepo.vue delete mode 100644 frontend/src/components/repo/update/GeneralRepo.vue delete mode 100644 frontend/src/components/repo/update/SecurityRepo.vue delete mode 100644 frontend/src/components/repo/update/UpdateRepo.vue delete mode 100644 frontend/src/components/upload/MavenUpload.js delete mode 100644 frontend/src/components/upload/MavenUpload.vue delete mode 100644 frontend/src/components/upload/PomCreator.ts delete mode 100644 frontend/src/components/upload/PomCreator.vue delete mode 100644 frontend/src/styles/app.css delete mode 100644 frontend/src/styles/form.css create mode 100644 frontend/src/styles/forms.css create mode 100644 frontend/src/styles/main.css delete mode 100644 frontend/src/styles/prism-atom-dark.css create mode 100644 frontend/src/types/user.ts delete mode 100644 frontend/src/views/Browse.ts delete mode 100644 frontend/src/views/Login.vue delete mode 100644 frontend/src/views/Me.vue delete mode 100644 frontend/src/views/Project.vue delete mode 100644 frontend/src/views/Repository.vue delete mode 100644 frontend/src/views/Upload.vue rename frontend/src/views/{Home.vue => admin.vue} (52%) delete mode 100644 frontend/src/views/admin/Admin.vue delete mode 100644 frontend/src/views/admin/ViewRepository.vue delete mode 100644 frontend/src/views/admin/ViewStorage.vue delete mode 100644 frontend/src/views/admin/ViewUser.vue create mode 100644 frontend/src/views/index.vue create mode 100644 frontend/src/views/login.vue delete mode 100644 frontend/vue.config.js delete mode 100644 nitro_repo-api-wrapper/.nvmrc delete mode 100644 nitro_repo-api-wrapper/package-lock.json delete mode 100644 nitro_repo-api-wrapper/package.json delete mode 100644 nitro_repo-api-wrapper/src/NitroRepoAPI.ts delete mode 100644 nitro_repo-api-wrapper/src/index.ts delete mode 100644 nitro_repo-api-wrapper/src/repository/repositoryAdminAPI.ts delete mode 100644 nitro_repo-api-wrapper/src/repository/repositoryTypes.ts delete mode 100644 nitro_repo-api-wrapper/src/repository/repositoryUserAPI.ts delete mode 100644 nitro_repo-api-wrapper/src/storage/storageAPI.ts delete mode 100644 nitro_repo-api-wrapper/src/storage/storageTypes.ts delete mode 100644 nitro_repo-api-wrapper/src/user/adminUserAPI.ts delete mode 100644 nitro_repo-api-wrapper/src/user/userTypes.ts delete mode 100644 nitro_repo-api-wrapper/src/user/userUserAPI.ts delete mode 100644 nitro_repo-api-wrapper/tsconfig.json diff --git a/.gitignore b/.gitignore index c0d3ab58..bfbd09cd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ backend/target backend/test +test/ *.iml .idea log diff --git a/backend/src/authentication/middleware.rs b/backend/src/authentication/middleware.rs index c4447a1f..c4ef2317 100644 --- a/backend/src/authentication/middleware.rs +++ b/backend/src/authentication/middleware.rs @@ -204,7 +204,7 @@ where if let Some(session) = session { let mut cookie = Cookie::new("session", &session.token); cookie.set_secure(false); - cookie.set_same_site(SameSite::Lax); + cookie.set_same_site(SameSite::None); cookie.set_path("/"); cookie.set_expires(session.expiration); let cookie_encoded = cookie.encoded().to_string(); diff --git a/backend/src/storage/multi/mod.rs b/backend/src/storage/multi/mod.rs index 1fcee255..bc5c2906 100644 --- a/backend/src/storage/multi/mod.rs +++ b/backend/src/storage/multi/mod.rs @@ -74,7 +74,7 @@ impl MultiStorageController { pub async fn get_storage_by_name( &self, name: &str, - ) -> Result>, StorageError> { + ) -> Result>, StorageError> { let storages = self.storages.read().await; if storages.contains_key(name) { return Ok(None); diff --git a/backend/src/system/web/public.rs b/backend/src/system/web/public.rs index 19bf38e4..c5379a8d 100644 --- a/backend/src/system/web/public.rs +++ b/backend/src/system/web/public.rs @@ -1,6 +1,7 @@ use actix_web::cookie::Cookie; use actix_web::web; use actix_web::{post, HttpRequest, HttpResponse}; +use actix_web::http::StatusCode; use log::error; use sea_orm::DatabaseConnection; use serde::{Deserialize, Serialize}; @@ -23,15 +24,20 @@ pub async fn login( nc: web::Json, ) -> actix_web::Result { let user = verify_login(nc.username.clone(), nc.password.clone(), &connection).await??; - let cookie: Cookie = r.cookie("session").unwrap(); - actix_web::rt::spawn(async move { - if (session_manager.set_user(cookie.value(), user.id).await).is_err() { - error!( + let cookie = r.cookie("session"); + if let Some(cookie) = cookie { + actix_web::rt::spawn(async move { + if (session_manager.set_user(cookie.value(), user.id).await).is_err() { + error!( "Unable to save user {} to cookie {}", user.id, cookie.value() ); - } - }); - Ok(HttpResponse::Ok().json(user)) + } + }); + Ok(HttpResponse::Ok().json(user)) + } else { + log::warn!("No cookie found for {r:?}"); + Ok(HttpResponse::Ok().status(StatusCode::BAD_GATEWAY).finish()) + } } diff --git a/frontend/.browserslistrc b/frontend/.browserslistrc index 214388fe..dc3bc09a 100644 --- a/frontend/.browserslistrc +++ b/frontend/.browserslistrc @@ -1,3 +1,4 @@ > 1% last 2 versions not dead +not ie 11 diff --git a/frontend/.editorconfig b/frontend/.editorconfig new file mode 100644 index 00000000..7053c49a --- /dev/null +++ b/frontend/.editorconfig @@ -0,0 +1,5 @@ +[*.{js,jsx,ts,tsx,vue}] +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/frontend/.eslintrc.js b/frontend/.eslintrc.js index add9b496..bebeb668 100644 --- a/frontend/.eslintrc.js +++ b/frontend/.eslintrc.js @@ -8,7 +8,6 @@ module.exports = { "eslint:recommended", "@vue/typescript/recommended", "@vue/prettier", - "@vue/prettier/@typescript-eslint", ], parserOptions: { ecmaVersion: 2020, @@ -16,5 +15,12 @@ module.exports = { rules: { "no-console": process.env.NODE_ENV === "production" ? "warn" : "off", "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off", + "prettier/prettier": [ + "error", + { + endOfLine: "auto", + }, + ], + indent: ["error", 2], }, }; diff --git a/frontend/.gitignore b/frontend/.gitignore index 403adbc1..e47c70bc 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -1,21 +1,21 @@ -.DS_Store -node_modules -/dist - - -# local env files -.env.local -.env.*.local - -# Log files +# Logs +logs +*.log npm-debug.log* yarn-debug.log* yarn-error.log* pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +*.local # Editor directories and files +.vscode/* +!.vscode/extensions.json .idea -.vscode +.DS_Store *.suo *.ntvs* *.njsproj diff --git a/frontend/.nvmrc b/frontend/.nvmrc index 7ce18f23..9a6e9d89 100644 --- a/frontend/.nvmrc +++ b/frontend/.nvmrc @@ -1 +1 @@ -v17.7.1 +v18.2.0 \ No newline at end of file diff --git a/frontend/.prettierignore b/frontend/.prettierignore deleted file mode 100644 index 0f5f50e0..00000000 --- a/frontend/.prettierignore +++ /dev/null @@ -1,3 +0,0 @@ -dist -build -node_modules diff --git a/frontend/.prettierrc b/frontend/.prettierrc new file mode 100644 index 00000000..e69de29b diff --git a/frontend/.prettierrc.json b/frontend/.prettierrc.json deleted file mode 100644 index 0967ef42..00000000 --- a/frontend/.prettierrc.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/frontend/README.md b/frontend/README.md index 4812f8f5..4af1cefd 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -1 +1,3 @@ -# Nitro Repo Frontend \ No newline at end of file +# Under Development + +1.1 new Frontend diff --git a/frontend/babel.config.js b/frontend/babel.config.js index 162a3ea9..6431b568 100644 --- a/frontend/babel.config.js +++ b/frontend/babel.config.js @@ -1,3 +1,3 @@ module.exports = { - presets: ["@vue/cli-plugin-babel/preset"], + presets: ["@vue/cli-plugin-babel/preset"], }; diff --git a/frontend/balm.config.js b/frontend/balm.config.js deleted file mode 100644 index 40d1a6eb..00000000 --- a/frontend/balm.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const api = (mix) => { - if (mix.env.isDev) { - mix.copy("node_modules/balm-ui/fonts/*", "app/fonts"); - } -}; diff --git a/frontend/components.d.ts b/frontend/components.d.ts index eb5986fc..ec076a16 100644 --- a/frontend/components.d.ts +++ b/frontend/components.d.ts @@ -6,47 +6,24 @@ import '@vue/runtime-core' declare module '@vue/runtime-core' { export interface GlobalComponents { AdminDropBox: typeof import('./src/components/nav/AdminDropBox.vue')['default'] - BrowseBox: typeof import('./src/components/browse/BrowseBox.vue')['default'] + ArtifactSearch: typeof import('./src/components/ArtifactSearch.vue')['default'] CodeCard: typeof import('./src/components/common/code/CodeCard.vue')['default'] CodeMenu: typeof import('./src/components/common/code/CodeMenu.vue')['default'] - CreateRepo: typeof import('./src/components/CreateRepo.vue')['default'] - CreateStorage: typeof import('./src/components/CreateStorage.vue')['default'] - CreateUser: typeof import('./src/components/CreateUser.vue')['default'] - DeployRepo: typeof import('./src/components/repo/update/DeployRepo.vue')['default'] - FrontendRepo: typeof import('./src/components/repo/update/FrontendRepo.vue')['default'] - GeneralRepo: typeof import('./src/components/repo/update/GeneralRepo.vue')['default'] LinkNavItem: typeof import('./src/components/common/nav/LinkNavItem.vue')['default'] Login: typeof import('./src/components/nav/Login.vue')['default'] LoginComp: typeof import('./src/components/user/LoginComp.vue')['default'] - MavenProjectCopy: typeof import('./src/components/project/types/maven/copy/MavenProjectCopy.vue')['default'] - MavenProjectInfo: typeof import('./src/components/project/types/maven/MavenProjectInfo.vue')['default'] - MavenRepoInfo: typeof import('./src/components/repo/types/maven/MavenRepoInfo.vue')['default'] - MavenUpload: typeof import('./src/components/upload/MavenUpload.vue')['default'] - Me: typeof import('./src/components/Me.vue')['default'] MenuButton: typeof import('./src/components/nav/MenuButton.vue')['default'] Navbar: typeof import('./src/components/nav/Navbar.vue')['default'] NitroModal: typeof import('./src/components/common/model/NitroModal.vue')['default'] PermissionList: typeof import('./src/components/user/update/PermissionList.vue')['default'] Permissions: typeof import('./src/components/user/update/Permissions.vue')['default'] - PomCreator: typeof import('./src/components/upload/PomCreator.vue')['default'] - ProjectBadge: typeof import('./src/components/project/badge/ProjectBadge.vue')['default'] - Repositories: typeof import('./src/components/Repositories.vue')['default'] - RepositoryBadge: typeof import('./src/components/repo/badge/RepositoryBadge.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] SearchableList: typeof import('./src/components/common/list/SearchableList.vue')['default'] - SecurityRepo: typeof import('./src/components/repo/update/SecurityRepo.vue')['default'] - Storages: typeof import('./src/components/Storages.vue')['default'] SubNavBar: typeof import('./src/components/common/nav/SubNavBar.vue')['default'] SubNavItem: typeof import('./src/components/common/nav/SubNavItem.vue')['default'] Switch: typeof import('./src/components/common/forms/Switch.vue')['default'] - UpdateRepo: typeof import('./src/components/repo/update/UpdateRepo.vue')['default'] - UpdateStorage: typeof import('./src/components/UpdateStorage.vue')['default'] - UpdateUser: typeof import('./src/components/UpdateUser.vue')['default'] UserGeneral: typeof import('./src/components/user/update/UserGeneral.vue')['default'] - Users: typeof import('./src/components/Users.vue')['default'] - ViewProject: typeof import('./src/components/project/ViewProject.vue')['default'] - ViewRepo: typeof import('./src/components/repo/ViewRepo.vue')['default'] } } diff --git a/frontend/index.html b/frontend/index.html index 77ddbd62..2bc90239 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -1,41 +1,37 @@ - - - - - + + + + + <% if(!isDev){ %> {{title}} - - + + - - - - - + + + + + - - - - + + + <% } else { %> Nitro Repo <% } %> + + - - - -
- - + +
+ + diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 28f75cbc..6073032a 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,96 +1,47 @@ { - "name": "site", - "version": "1.0.1", + "name": "frontend", + "version": "0.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "site", - "version": "1.0.1", + "name": "frontend", + "version": "0.1.0", "dependencies": { "@kyvg/vue3-notification": "^2.3.4", - "@nitro_repo/nitro_repo-api-wrapper": "file:../nitro_repo-api-wrapper", - "@uppy/drag-drop": "^2.1.0", - "@uppy/vue": "^0.4.7", + "@rushstack/eslint-patch": "^1.1.3", + "@types/webpack-env": "^1.17.0", "axios": "^0.27.2", - "boxicons": "^2.1.2", - "core-js": "^3.22.7", - "equal-vue": "^0.79.3", - "fast-xml-parser": "^4.0.8", + "core-js": "^3.22.8", "pinia": "^2.0.14", "prismjs": "^1.28.0", - "ts-results": "3.3.0", "vite-plugin-ejs": "^1.4.4", "vue": "^3.2.36", - "vue-axios": "^3.4.1", "vue-class-component": "^8.0.0-0", - "vue-color-kit": "^1.0.5", - "vue-final-modal": "^3.4.3", + "vue-final-modal": "^3.4.4", "vue-meta": "3.0.0-alpha.10", "vue-prism-editor": "^2.0.0-alpha.2", - "vue-router": "^4.0.15", - "vue3-cookies": "^1.0.6" + "vue-router": "^4.0.15" }, "devDependencies": { - "@typescript-eslint/eslint-plugin": "^5.26.0", - "@typescript-eslint/parser": "^5.26.0", + "@types/prismjs": "^1.26.0", + "@typescript-eslint/eslint-plugin": "5.27.0", + "@typescript-eslint/parser": "5.27.0", "@vitejs/plugin-vue": "^2.3.3", - "@vue/cli-plugin-babel": "~5.0.4", - "@vue/cli-plugin-eslint": "~5.0.4", - "@vue/cli-plugin-router": "~5.0.4", - "@vue/cli-plugin-typescript": "~5.0.4", - "@vue/cli-plugin-vuex": "~5.0.4", - "@vue/cli-service": "~5.0.4", - "@vue/compiler-sfc": "^3.2.36", - "@vue/eslint-config-prettier": "^7.0.0", - "eslint": "^8.16.0", - "eslint-plugin-prettier": "^4.0.0", - "eslint-plugin-vue": "^9.0.1", + "@vue/eslint-config-prettier": "7.0.0", + "@vue/eslint-config-typescript": "10.0.0", + "autoprefixer": "^10.4.7", + "eslint": "8.16.0", + "eslint-plugin-prettier": "4.0.0", + "eslint-plugin-vue": "8.0.1", + "postcss": "^8.4.14", "prettier": "2.6.2", "sass": "^1.52.1", "tailwindcss": "^3.0.24", "typescript": "~4.7.2", "unplugin-vue-components": "^0.19.6", - "vite": "^2.9.9" - } - }, - "../nitro_repo-api-wrapper": { - "name": "@nitro_repo/nitro_repo-api-wrapper", - "version": "1.0.1", - "license": "MIT", - "dependencies": { - "axios": "^0.27.2", - "ts-results": "^3.3.0" - }, - "devDependencies": { - "typedoc": "^0.22.15", - "typescript": "^4.7.2" - } - }, - "node_modules/@achrinza/node-ipc": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/@achrinza/node-ipc/-/node-ipc-9.2.2.tgz", - "integrity": "sha512-b90U39dx0cU6emsOvy5hxU4ApNXnE3+Tuo8XQZfiKTGelDwpMwBVgBP7QX6dGTcJgu/miyJuNJ/2naFBliNWEw==", - "dev": true, - "dependencies": { - "@node-ipc/js-queue": "2.0.3", - "event-pubsub": "4.3.0", - "js-message": "1.0.7" - }, - "engines": { - "node": "8 || 10 || 12 || 14 || 16 || 17" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", - "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.0" - }, - "engines": { - "node": ">=6.0.0" + "vite": "^2.9.9", + "vue-tsc": "^0.35.2" } }, "node_modules/@antfu/utils": { @@ -102,3362 +53,2884 @@ "url": "https://github.com/sponsors/antfu" } }, - "node_modules/@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.16.7" + "node_modules/@babel/parser": { + "version": "7.18.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.4.tgz", + "integrity": "sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==", + "bin": { + "parser": "bin/babel-parser.js" }, "engines": { - "node": ">=6.9.0" + "node": ">=6.0.0" } }, - "node_modules/@babel/compat-data": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz", - "integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==", + "node_modules/@eslint/eslintrc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", + "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.3.2", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@babel/core": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.8.tgz", - "integrity": "sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ==", + "node_modules/@humanwhocodes/config-array": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", + "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", "dev": true, "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.7", - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-module-transforms": "^7.17.7", - "@babel/helpers": "^7.17.8", - "@babel/parser": "^7.17.8", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0" + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" }, "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "node": ">=10.10.0" } }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true }, - "node_modules/@babel/generator": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", - "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz", + "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "@babel/types": "^7.17.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { - "node": ">=6.9.0" + "node": ">=6.0.0" } }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", - "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", + "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, + "optional": true, + "peer": true, "engines": { - "node": ">=6.9.0" + "node": ">=6.0.0" } }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz", - "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==", + "node_modules/@jridgewell/set-array": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz", + "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==", "dev": true, - "dependencies": { - "@babel/helper-explode-assignable-expression": "^7.16.7", - "@babel/types": "^7.16.7" - }, + "optional": true, + "peer": true, "engines": { - "node": ">=6.9.0" + "node": ">=6.0.0" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz", - "integrity": "sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==", + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.17.5", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", + "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", "dev": true, - "bin": { - "semver": "bin/semver.js" - } + "optional": true, + "peer": true }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.17.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz", - "integrity": "sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg==", + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz", + "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-member-expression-to-functions": "^7.16.7", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz", - "integrity": "sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "regexpu-core": "^5.0.1" - }, - "engines": { - "node": ">=6.9.0" - }, + "node_modules/@kyvg/vue3-notification": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@kyvg/vue3-notification/-/vue3-notification-2.3.4.tgz", + "integrity": "sha512-20Km1L75gncIZCjosT1OKbJl9HhNiOd7LRXqVIqlehHHem9NgBjQhDFz6XGo1RcF0MyA4/BC7kV7tcq/PMT+tA==", "peerDependencies": { - "@babel/core": "^7.0.0" + "vue": "^3.0.0" } }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", - "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "dependencies": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, - "peerDependencies": { - "@babel/core": "^7.4.0-0" + "engines": { + "node": ">= 8" } }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "engines": { + "node": ">= 8" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", - "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "dependencies": { - "@babel/types": "^7.16.7" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": ">=6.9.0" + "node": ">= 8" } }, - "node_modules/@babel/helper-explode-assignable-expression": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz", - "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==", + "node_modules/@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", "dev": true, "dependencies": { - "@babel/types": "^7.16.7" + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" }, "engines": { - "node": ">=6.9.0" + "node": ">= 8.0.0" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", - "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", + "node_modules/@rushstack/eslint-patch": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.3.tgz", + "integrity": "sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw==" + }, + "node_modules/@types/eslint": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.2.tgz", + "integrity": "sha512-Z1nseZON+GEnFjJc04sv4NSALGjhFwy6K0HXt7qsn5ArfAKtb63dXNJHf+1YW6IpOIYRBGUbu3GwJdj8DGnCjA==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "@babel/helper-get-function-arity": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" + "@types/estree": "*", + "@types/json-schema": "*" } }, - "node_modules/@babel/helper-get-function-arity": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", - "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", + "node_modules/@types/eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" + "@types/eslint": "*", + "@types/estree": "*" } }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "node_modules/@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } + "optional": true, + "peer": true }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.17.7.tgz", - "integrity": "sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw==", + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "17.0.38", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.38.tgz", + "integrity": "sha512-5jY9RhV7c0Z4Jy09G+NIDTsCZ5G0L5n+Z+p+Y7t5VJHM30bgwzSjVtlcBxqAj+6L/swIlvtOSzr8rBk/aNyV2g==", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/@types/prismjs": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.0.tgz", + "integrity": "sha512-ZTaqn/qSqUuAq1YwvOFQfVW1AR/oQJlLSZVustdjwI+GZ8kr0MSHBj0tsXPW1EqHubx50gtBEjbPGsdZwQwCjQ==", + "dev": true + }, + "node_modules/@types/webpack-env": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.17.0.tgz", + "integrity": "sha512-eHSaNYEyxRA5IAG0Ym/yCyf86niZUIF/TpWKofQI/CVfh5HsMEUyfE2kwFxha4ow0s5g0LfISQxpDKjbRDrizw==" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.27.0.tgz", + "integrity": "sha512-DDrIA7GXtmHXr1VCcx9HivA39eprYBIFxbQEHI6NyraRDxCGpxAFiYQAT/1Y0vh1C+o2vfBiy4IuPoXxtTZCAQ==", "dev": true, "dependencies": { - "@babel/types": "^7.17.0" + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/type-utils": "5.27.0", + "@typescript-eslint/utils": "5.27.0", + "debug": "^4.3.4", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.2.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "node_modules/@typescript-eslint/parser": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.27.0.tgz", + "integrity": "sha512-8oGjQF46c52l7fMiPPvX4It3u3V3JipssqDfHQ2hcR0AeR8Zge+OYyKUCm5b70X72N1qXt0qgHenwN6Gc2SXZA==", "dev": true, "dependencies": { - "@babel/types": "^7.16.7" + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/typescript-estree": "5.27.0", + "debug": "^4.3.4" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", - "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.27.0.tgz", + "integrity": "sha512-VnykheBQ/sHd1Vt0LJ1JLrMH1GzHO+SzX6VTXuStISIsvRiurue/eRkTqSrG0CexHQgKG8shyJfR4o5VYioB9g==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/visitor-keys": "5.27.0" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz", - "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==", + "node_modules/@typescript-eslint/type-utils": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.27.0.tgz", + "integrity": "sha512-vpTvRRchaf628Hb/Xzfek+85o//zEUotr1SmexKvTfs7czXfYjXVT/a5yDbpzLBX1rhbqxjDdr1Gyo0x1Fc64g==", "dev": true, "dependencies": { - "@babel/types": "^7.16.7" + "@typescript-eslint/utils": "5.27.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", - "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", + "node_modules/@typescript-eslint/types": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.27.0.tgz", + "integrity": "sha512-lY6C7oGm9a/GWhmUDOs3xAVRz4ty/XKlQ2fOLr8GAIryGn0+UBOoJDWyHer3UgrHkenorwvBnphhP+zPmzmw0A==", "dev": true, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz", - "integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.27.0.tgz", + "integrity": "sha512-QywPMFvgZ+MHSLRofLI7BDL+UczFFHyj0vF5ibeChDAJgdTV8k4xgEwF0geFhVlPc1p8r70eYewzpo6ps+9LJQ==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-wrap-function": "^7.16.8", - "@babel/types": "^7.16.8" + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/visitor-keys": "5.27.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" }, "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz", - "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-member-expression-to-functions": "^7.16.7", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/traverse": "^7.16.7", - "@babel/types": "^7.16.7" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", - "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.17.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, - "engines": { - "node": ">=6.9.0" + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", - "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", + "node_modules/@typescript-eslint/utils": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.27.0.tgz", + "integrity": "sha512-nZvCrkIJppym7cIbP3pOwIkAefXOmfGPnCM0LQfzNaKxJHI6VjI8NC662uoiPlaf5f6ymkTy9C3NQXev2mdXmA==", "dev": true, "dependencies": { - "@babel/types": "^7.16.0" + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/typescript-estree": "5.27.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.27.0.tgz", + "integrity": "sha512-46cYrteA2MrIAjv9ai44OQDUoCZyHeGIc4lsjCUX2WT6r4C+kidz1bNiR4017wHOPUythYeH+Sc7/cFP97KEAA==", "dev": true, "dependencies": { - "@babel/types": "^7.16.7" + "@typescript-eslint/types": "5.27.0", + "eslint-visitor-keys": "^3.3.0" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", "dev": true, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "node_modules/@vitejs/plugin-vue": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.3.3.tgz", + "integrity": "sha512-SmQLDyhz+6lGJhPELsBdzXGc+AcaT8stgkbiTFGpXPe8Tl1tJaBw1A6pxDqDuRsVkD8uscrkx3hA7QDOoKYtyw==", "dev": true, "engines": { - "node": ">=6.9.0" + "node": ">=12.0.0" + }, + "peerDependencies": { + "vite": "^2.5.10", + "vue": "^3.2.25" } }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz", - "integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==", + "node_modules/@volar/code-gen": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@volar/code-gen/-/code-gen-0.35.2.tgz", + "integrity": "sha512-MoZHuNnPfUWnCNkQUI5+U+gvLTxrU+XlCTusdNOTFYUUAa+M68MH0RxFIS9Ybj4uAUWTcZx0Ow1q5t/PZozo+Q==", "dev": true, "dependencies": { - "@babel/helper-function-name": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.16.8", - "@babel/types": "^7.16.8" - }, - "engines": { - "node": ">=6.9.0" + "@volar/source-map": "0.35.2" } }, - "node_modules/@babel/helpers": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.8.tgz", - "integrity": "sha512-QcL86FGxpfSJwGtAvv4iG93UL6bmqBdmoVY0CMCU2g+oD2ezQse3PT5Pa+jiD6LJndBQi0EDlpzOWNlLuhz5gw==", + "node_modules/@volar/source-map": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-0.35.2.tgz", + "integrity": "sha512-PFHh9wN/qMkOWYyvmB8ckvIzolrpNOvK5EBdxxdTpiPJhfYjW82rMDBnYf6RxCe7yQxrUrmve6BWVO7flxWNVQ==", + "dev": true + }, + "node_modules/@volar/vue-code-gen": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@volar/vue-code-gen/-/vue-code-gen-0.35.2.tgz", + "integrity": "sha512-8H6P8EtN06eSVGjtcJhGqZzFIg6/nWoHVOlnhc5vKqC7tXwpqPbyMQae0tO7pLBd5qSb/dYU5GQcBAHsi2jgyA==", "dev": true, "dependencies": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" - }, - "engines": { - "node": ">=6.9.0" + "@volar/code-gen": "0.35.2", + "@volar/source-map": "0.35.2", + "@vue/compiler-core": "^3.2.36", + "@vue/compiler-dom": "^3.2.36", + "@vue/shared": "^3.2.36" } }, - "node_modules/@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", + "node_modules/@volar/vue-typescript": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@volar/vue-typescript/-/vue-typescript-0.35.2.tgz", + "integrity": "sha512-PZI6Urb+Vr5Dvgf9xysM8X7TP09inWDy1wjDtprBoBhxS7r0Dg3V0qZuJa7sSGz7M0QMa5R/CBaZPhlxFCfJBw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" + "@volar/code-gen": "0.35.2", + "@volar/source-map": "0.35.2", + "@volar/vue-code-gen": "0.35.2", + "@vue/compiler-sfc": "^3.2.36", + "@vue/reactivity": "^3.2.36" } }, - "node_modules/@babel/parser": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.8.tgz", - "integrity": "sha512-BoHhDJrJXqcg+ZL16Xv39H9n+AqJ4pcDrQBGZN+wHxIysrLZ3/ECwCBUch/1zUNhnsXULcONU3Ei5Hmkfk6kiQ==", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" + "node_modules/@vue/compiler-core": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.36.tgz", + "integrity": "sha512-bbyZM5hvBicv0PW3KUfVi+x3ylHnfKG7DOn5wM+f2OztTzTjLEyBb/5yrarIYpmnGitVGbjZqDbODyW4iK8hqw==", + "dependencies": { + "@babel/parser": "^7.16.4", + "@vue/shared": "3.2.36", + "estree-walker": "^2.0.2", + "source-map": "^0.6.1" } }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz", - "integrity": "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==", - "dev": true, + "node_modules/@vue/compiler-dom": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.36.tgz", + "integrity": "sha512-tcOTAOiW4s24QLnq+ON6J+GRONXJ+A/mqKCORi0LSlIh8XQlNnlm24y8xIL8la+ZDgkdbjarQ9ZqYSvEja6gVA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "@vue/compiler-core": "3.2.36", + "@vue/shared": "3.2.36" } }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz", - "integrity": "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==", - "dev": true, + "node_modules/@vue/compiler-sfc": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.36.tgz", + "integrity": "sha512-AvGb4bTj4W8uQ4BqaSxo7UwTEqX5utdRSMyHy58OragWlt8nEACQ9mIeQh3K4di4/SX+41+pJrLIY01lHAOFOA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", - "@babel/plugin-proposal-optional-chaining": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.36", + "@vue/compiler-dom": "3.2.36", + "@vue/compiler-ssr": "3.2.36", + "@vue/reactivity-transform": "3.2.36", + "@vue/shared": "3.2.36", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7", + "postcss": "^8.1.10", + "source-map": "^0.6.1" } }, - "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz", - "integrity": "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==", - "dev": true, + "node_modules/@vue/compiler-ssr": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.36.tgz", + "integrity": "sha512-+KugInUFRvOxEdLkZwE+W43BqHyhBh0jpYXhmqw1xGq2dmE6J9eZ8UUSOKNhdHtQ/iNLWWeK/wPZkVLUf3YGaw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-remap-async-to-generator": "^7.16.8", - "@babel/plugin-syntax-async-generators": "^7.8.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@vue/compiler-dom": "3.2.36", + "@vue/shared": "3.2.36" } }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz", - "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==", + "node_modules/@vue/devtools-api": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.1.4.tgz", + "integrity": "sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ==" + }, + "node_modules/@vue/eslint-config-prettier": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-7.0.0.tgz", + "integrity": "sha512-/CTc6ML3Wta1tCe1gUeO0EYnVXfo3nJXsIhZ8WJr3sov+cGASr6yuiibJTL6lmIBm7GobopToOuB3B6AWyV0Iw==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-prettier": "^4.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "eslint": ">= 7.28.0", + "prettier": ">= 2.0.0" } }, - "node_modules/@babel/plugin-proposal-class-static-block": { - "version": "7.17.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.17.6.tgz", - "integrity": "sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA==", + "node_modules/@vue/eslint-config-typescript": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-10.0.0.tgz", + "integrity": "sha512-F94cL8ug3FaYXlCfU5/wiGjk1qeadmoBpRGAOBq+qre3Smdupa59dd6ZJrsfRODpsMPyTG7330juMDsUvpZ3Rw==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.17.6", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-class-static-block": "^7.14.5" + "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/parser": "^5.0.0", + "vue-eslint-parser": "^8.0.0" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "peerDependencies": { - "@babel/core": "^7.12.0" + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0", + "eslint-plugin-vue": "^8.0.1" } }, - "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.17.8.tgz", - "integrity": "sha512-U69odN4Umyyx1xO1rTII0IDkAEC+RNlcKXtqOblfpzqy1C+aOplb76BQNq0+XdpVkOaPlpEDwd++joY8FNFJKA==", - "dev": true, + "node_modules/@vue/reactivity": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.36.tgz", + "integrity": "sha512-c2qvopo0crh9A4GXi2/2kfGYMxsJW4tVILrqRPydVGZHhq0fnzy6qmclWOhBFckEhmyxmpHpdJtIRYGeKcuhnA==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.17.6", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7", - "@babel/plugin-syntax-decorators": "^7.17.0", - "charcodes": "^0.2.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@vue/shared": "3.2.36" } }, - "node_modules/@babel/plugin-proposal-dynamic-import": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz", - "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==", - "dev": true, + "node_modules/@vue/reactivity-transform": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.36.tgz", + "integrity": "sha512-Jk5o2BhpODC9XTA7o4EL8hSJ4JyrFWErLtClG3NH8wDS7ri9jBDWxI7/549T7JY9uilKsaNM+4pJASLj5dtRwA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.36", + "@vue/shared": "3.2.36", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7" } }, - "node_modules/@babel/plugin-proposal-export-namespace-from": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz", - "integrity": "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==", - "dev": true, + "node_modules/@vue/runtime-core": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.36.tgz", + "integrity": "sha512-PTWBD+Lub+1U3/KhbCExrfxyS14hstLX+cBboxVHaz+kXoiDLNDEYAovPtxeTutbqtClIXtft+wcGdC+FUQ9qQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@vue/reactivity": "3.2.36", + "@vue/shared": "3.2.36" } }, - "node_modules/@babel/plugin-proposal-json-strings": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz", - "integrity": "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==", - "dev": true, + "node_modules/@vue/runtime-dom": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.36.tgz", + "integrity": "sha512-gYPYblm7QXHVuBohqNRRT7Wez0f2Mx2D40rb4fleehrJU9CnkjG0phhcGEZFfGwCmHZRqBCRgbFWE98bPULqkg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-json-strings": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@vue/runtime-core": "3.2.36", + "@vue/shared": "3.2.36", + "csstype": "^2.6.8" } }, - "node_modules/@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz", - "integrity": "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==", - "dev": true, + "node_modules/@vue/server-renderer": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.36.tgz", + "integrity": "sha512-uZE0+jfye6yYXWvAQYeHZv+f50sRryvy16uiqzk3jn8hEY8zTjI+rzlmZSGoE915k+W/Ol9XSw6vxOUD8dGkUg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" + "@vue/compiler-ssr": "3.2.36", + "@vue/shared": "3.2.36" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "vue": "3.2.36" } }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz", - "integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==", + "node_modules/@vue/shared": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.36.tgz", + "integrity": "sha512-JtB41wXl7Au3+Nl3gD16Cfpj7k/6aCroZ6BbOiCMFCMvrOpkg/qQUXTso2XowaNqBbnkuGHurLAqkLBxNGc1hQ==" + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" } }, - "node_modules/@babel/plugin-proposal-numeric-separator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz", - "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==", + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "peer": true }, - "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz", - "integrity": "sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==", + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", "dev": true, - "dependencies": { - "@babel/compat-data": "^7.17.0", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "peer": true }, - "node_modules/@babel/plugin-proposal-optional-catch-binding": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz", - "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==", + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "peer": true }, - "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz", - "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==", + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" } }, - "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.16.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz", - "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==", + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.16.10", - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "peer": true }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz", - "integrity": "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==", + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-create-class-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" } }, - "node_modules/@babel/plugin-proposal-unicode-property-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz", - "integrity": "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==", + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@xtuc/ieee754": "^1.2.0" } }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@xtuc/long": "4.2.2" } }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "peer": true }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" } }, - "node_modules/@babel/plugin-syntax-decorators": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.17.0.tgz", - "integrity": "sha512-qWe85yCXsvDEluNP0OyeQjH63DlhAR3W7K9BxxU1MvbDb48tgBG+Ao6IJJ6smPDrrVzSQZrbF6donpkFBMcs3A==", + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" } }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" } }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" } }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" } }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz", - "integrity": "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==", + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "peer": true }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "peer": true }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "node_modules/acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "bin": { + "acorn": "bin/acorn" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=0.4.0" } }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "node_modules/acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, + "optional": true, + "peer": true, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "acorn": "^8" } }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "node_modules/acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" } }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "node_modules/acorn-node/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "bin": { + "acorn": "bin/acorn" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=0.4.0" } }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "node_modules/acorn-node/node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=0.4.0" } }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz", - "integrity": "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==", + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, + "optional": true, + "peer": true, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "ajv": "^6.9.1" } }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz", - "integrity": "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==", + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-remap-async-to-generator": "^7.16.8" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=8" } }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz", - "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==", - "dev": true, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=6.9.0" + "node": ">=8" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz", - "integrity": "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==", + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz", - "integrity": "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "globals": "^11.1.0" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 8" } }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz", - "integrity": "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/arg": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", + "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==", + "dev": true }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.7.tgz", - "integrity": "sha512-XVh0r5yq9sLR4vZ6eVZe8FKfIcSgaTBxVBRSYokRj2qksf6QerYnTxz9/GTuKTH/n/HwLP7t6gtlybHetJ/6hQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz", - "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==", + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=8" } }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz", - "integrity": "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==", + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/autoprefixer": { + "version": "10.4.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz", + "integrity": "sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "browserslist": "^4.20.3", + "caniuse-lite": "^1.0.30001335", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" }, "engines": { - "node": ">=6.9.0" + "node": "^10 || ^12 || >=14" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.1.0" } }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz", - "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==", - "dev": true, + "node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" } }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz", - "integrity": "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==", + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=8" } }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz", - "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==", - "dev": true, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dependencies": { - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz", - "integrity": "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==", + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "fill-range": "^7.0.1" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=8" } }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz", - "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==", + "node_modules/browserslist": { + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", + "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "caniuse-lite": "^1.0.30001332", + "electron-to-chromium": "^1.4.118", + "escalade": "^3.1.1", + "node-releases": "^2.0.3", + "picocolors": "^1.0.0" }, - "engines": { - "node": ">=6.9.0" + "bin": { + "browserslist": "cli.js" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz", - "integrity": "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==", + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "peer": true }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.17.7.tgz", - "integrity": "sha512-ITPmR2V7MqioMJyrxUo2onHNC3e+MvfFiFIR0RP21d3PtlVb6sfzoxNKiphSZUOM9hEIdzCcZe83ieX3yoqjUA==", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.17.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "babel-plugin-dynamic-import-node": "^2.3.3" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6" } }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.17.8.tgz", - "integrity": "sha512-39reIkMTUVagzgA5x88zDYXPCMT6lcaRKs1+S9K6NKBPErbgO/w/kP8GlNQTC87b412ZTlmNgr3k2JrWgHH+Bw==", + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", "dev": true, - "dependencies": { - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-module-transforms": "^7.17.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "babel-plugin-dynamic-import-node": "^2.3.3" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 6" } }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz", - "integrity": "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==", + "node_modules/caniuse-lite": { + "version": "1.0.30001344", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001344.tgz", + "integrity": "sha512-0ZFjnlCaXNOAYcV7i+TtdKBp0L/3XEU2MF/x6Du1lrh+SRX4IfzIVL4HNJg5pB2PmFb8rszIGyOvsZnqqRoc2g==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dependencies": { - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=10" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz", - "integrity": "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==", - "dev": true, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=8" } }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz", - "integrity": "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==", + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" }, "engines": { - "node": ">=6.9.0" + "node": ">= 8.10.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz", - "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==", + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 6" } }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz", - "integrity": "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==", + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, + "optional": true, + "peer": true, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6.0" } }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz", - "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==", - "dev": true, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "color-name": "~1.1.4" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=7.0.0" } }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz", - "integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==", - "dev": true, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dependencies": { - "regenerator-transform": "^0.14.2" + "delayed-stream": "~1.0.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 0.8" } }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz", - "integrity": "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/core-js": { + "version": "3.22.8", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.8.tgz", + "integrity": "sha512-UoGQ/cfzGYIuiq6Z7vWL1HfkE9U9IZ4Ub+0XSiJTCzvbZzgPA69oDF2f+lgJ6dFFLEdjW5O6svvoKzXX23xFkA==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" } }, - "node_modules/@babel/plugin-transform-runtime": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz", - "integrity": "sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A==", + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "babel-plugin-polyfill-corejs2": "^0.3.0", - "babel-plugin-polyfill-corejs3": "^0.5.0", - "babel-plugin-polyfill-regenerator": "^0.3.0", - "semver": "^6.3.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 8" } }, - "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz", - "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "cssesc": "bin/cssesc" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=4" } }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz", - "integrity": "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==", + "node_modules/csstype": { + "version": "2.6.20", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", + "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" + "ms": "2.1.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=6.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz", - "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" - }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==", + "dev": true + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=0.4.0" } }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz", - "integrity": "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==", + "node_modules/detective": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", + "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" }, - "engines": { - "node": ">=6.9.0" + "bin": { + "detective": "bin/detective.js" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=0.8.0" } }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz", - "integrity": "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==", + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "path-type": "^4.0.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=8" } }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz", - "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==", + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "esutils": "^2.0.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz", - "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==", - "dev": true, + "node_modules/ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" + "jake": "^10.8.5" }, - "engines": { - "node": ">=6.9.0" + "bin": { + "ejs": "bin/cli.js" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@babel/preset-env": { - "version": "7.16.11", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz", - "integrity": "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==", + "node_modules/electron-to-chromium": { + "version": "1.4.143", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.143.tgz", + "integrity": "sha512-2hIgvu0+pDfXIqmVmV5X6iwMjQ2KxDsWKwM+oI1fABEOy/Dqmll0QJRmIQ3rm+XaoUa/qKrmy5h7LSTFQ6Ldzg==", + "dev": true + }, + "node_modules/enhanced-resolve": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz", + "integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "@babel/compat-data": "^7.16.8", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-validator-option": "^7.16.7", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.7", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.7", - "@babel/plugin-proposal-async-generator-functions": "^7.16.8", - "@babel/plugin-proposal-class-properties": "^7.16.7", - "@babel/plugin-proposal-class-static-block": "^7.16.7", - "@babel/plugin-proposal-dynamic-import": "^7.16.7", - "@babel/plugin-proposal-export-namespace-from": "^7.16.7", - "@babel/plugin-proposal-json-strings": "^7.16.7", - "@babel/plugin-proposal-logical-assignment-operators": "^7.16.7", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7", - "@babel/plugin-proposal-numeric-separator": "^7.16.7", - "@babel/plugin-proposal-object-rest-spread": "^7.16.7", - "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", - "@babel/plugin-proposal-optional-chaining": "^7.16.7", - "@babel/plugin-proposal-private-methods": "^7.16.11", - "@babel/plugin-proposal-private-property-in-object": "^7.16.7", - "@babel/plugin-proposal-unicode-property-regex": "^7.16.7", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.16.7", - "@babel/plugin-transform-async-to-generator": "^7.16.8", - "@babel/plugin-transform-block-scoped-functions": "^7.16.7", - "@babel/plugin-transform-block-scoping": "^7.16.7", - "@babel/plugin-transform-classes": "^7.16.7", - "@babel/plugin-transform-computed-properties": "^7.16.7", - "@babel/plugin-transform-destructuring": "^7.16.7", - "@babel/plugin-transform-dotall-regex": "^7.16.7", - "@babel/plugin-transform-duplicate-keys": "^7.16.7", - "@babel/plugin-transform-exponentiation-operator": "^7.16.7", - "@babel/plugin-transform-for-of": "^7.16.7", - "@babel/plugin-transform-function-name": "^7.16.7", - "@babel/plugin-transform-literals": "^7.16.7", - "@babel/plugin-transform-member-expression-literals": "^7.16.7", - "@babel/plugin-transform-modules-amd": "^7.16.7", - "@babel/plugin-transform-modules-commonjs": "^7.16.8", - "@babel/plugin-transform-modules-systemjs": "^7.16.7", - "@babel/plugin-transform-modules-umd": "^7.16.7", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.8", - "@babel/plugin-transform-new-target": "^7.16.7", - "@babel/plugin-transform-object-super": "^7.16.7", - "@babel/plugin-transform-parameters": "^7.16.7", - "@babel/plugin-transform-property-literals": "^7.16.7", - "@babel/plugin-transform-regenerator": "^7.16.7", - "@babel/plugin-transform-reserved-words": "^7.16.7", - "@babel/plugin-transform-shorthand-properties": "^7.16.7", - "@babel/plugin-transform-spread": "^7.16.7", - "@babel/plugin-transform-sticky-regex": "^7.16.7", - "@babel/plugin-transform-template-literals": "^7.16.7", - "@babel/plugin-transform-typeof-symbol": "^7.16.7", - "@babel/plugin-transform-unicode-escapes": "^7.16.7", - "@babel/plugin-transform-unicode-regex": "^7.16.7", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.16.8", - "babel-plugin-polyfill-corejs2": "^0.3.0", - "babel-plugin-polyfill-corejs3": "^0.5.0", - "babel-plugin-polyfill-regenerator": "^0.3.0", - "core-js-compat": "^3.20.2", - "semver": "^6.3.0" + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=10.13.0" } }, - "node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", "dev": true, - "bin": { - "semver": "bin/semver.js" - } + "optional": true, + "peer": true }, - "node_modules/@babel/preset-modules": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", - "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "node_modules/esbuild": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.42.tgz", + "integrity": "sha512-V0uPZotCEHokJdNqyozH6qsaQXqmZEOiZWrXnds/zaH/0SyrIayRXWRB98CENO73MIZ9T3HBIOsmds5twWtmgw==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.8.tgz", - "integrity": "sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA==", - "dependencies": { - "regenerator-runtime": "^0.13.4" + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=6.9.0" + "node": ">=12" + }, + "optionalDependencies": { + "esbuild-android-64": "0.14.42", + "esbuild-android-arm64": "0.14.42", + "esbuild-darwin-64": "0.14.42", + "esbuild-darwin-arm64": "0.14.42", + "esbuild-freebsd-64": "0.14.42", + "esbuild-freebsd-arm64": "0.14.42", + "esbuild-linux-32": "0.14.42", + "esbuild-linux-64": "0.14.42", + "esbuild-linux-arm": "0.14.42", + "esbuild-linux-arm64": "0.14.42", + "esbuild-linux-mips64le": "0.14.42", + "esbuild-linux-ppc64le": "0.14.42", + "esbuild-linux-riscv64": "0.14.42", + "esbuild-linux-s390x": "0.14.42", + "esbuild-netbsd-64": "0.14.42", + "esbuild-openbsd-64": "0.14.42", + "esbuild-sunos-64": "0.14.42", + "esbuild-windows-32": "0.14.42", + "esbuild-windows-64": "0.14.42", + "esbuild-windows-arm64": "0.14.42" } }, - "node_modules/@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "node_modules/esbuild-android-64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.42.tgz", + "integrity": "sha512-P4Y36VUtRhK/zivqGVMqhptSrFILAGlYp0Z8r9UQqHJ3iWztRCNWnlBzD9HRx0DbueXikzOiwyOri+ojAFfW6A==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/traverse": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", - "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", + "node_modules/esbuild-android-arm64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.42.tgz", + "integrity": "sha512-0cOqCubq+RWScPqvtQdjXG3Czb3AWI2CaKw3HeXry2eoA2rrPr85HF7IpdU26UWdBXgPYtlTN1LUiuXbboROhg==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.3", - "@babel/types": "^7.17.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "node_modules/esbuild-darwin-64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.42.tgz", + "integrity": "sha512-ipiBdCA3ZjYgRfRLdQwP82rTiv/YVMtW36hTvAN5ZKAIfxBOyPXY7Cejp3bMXWgzKD8B6O+zoMzh01GZsCuEIA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@eslint/eslintrc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", - "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "node_modules/esbuild-darwin-arm64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.42.tgz", + "integrity": "sha512-bU2tHRqTPOaoH/4m0zYHbFWpiYDmaA0gt90/3BMEFaM0PqVK/a6MA2V/ypV5PO0v8QxN6gH5hBPY4YJ2lopXgA==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.3.2", - "globals": "^13.15.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=12" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", - "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", + "node_modules/esbuild-freebsd-64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.42.tgz", + "integrity": "sha512-75h1+22Ivy07+QvxHyhVqOdekupiTZVLN1PMwCDonAqyXd8TVNJfIRFrdL8QmSJrOJJ5h8H1I9ETyl2L8LQDaw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/esbuild-freebsd-arm64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.42.tgz", + "integrity": "sha512-W6Jebeu5TTDQMJUJVarEzRU9LlKpNkPBbjqSu+GUPTHDCly5zZEQq9uHkmHHl7OKm+mQ2zFySN83nmfCeZCyNA==", + "cpu": [ + "arm64" + ], "dev": true, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/@hapi/hoek": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz", - "integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==", - "dev": true - }, - "node_modules/@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "node_modules/esbuild-linux-32": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.42.tgz", + "integrity": "sha512-Ooy/Bj+mJ1z4jlWcK5Dl6SlPlCgQB9zg1UrTCeY8XagvuWZ4qGPyYEWGkT94HUsRi2hKsXvcs6ThTOjBaJSMfg==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "node_modules/esbuild-linux-64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.42.tgz", + "integrity": "sha512-2L0HbzQfbTuemUWfVqNIjOfaTRt9zsvjnme6lnr7/MO9toz/MJ5tZhjqrG6uDWDxhsaHI2/nsDgrv8uEEN2eoA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10.10.0" + "node": ">=12" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", - "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", + "node_modules/esbuild-linux-arm": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.42.tgz", + "integrity": "sha512-STq69yzCMhdRaWnh29UYrLSr/qaWMm/KqwaRF1pMEK7kDiagaXhSL1zQGXbYv94GuGY/zAwzK98+6idCMUOOCg==", + "cpu": [ + "arm" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.0.0" + "node": ">=12" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.11", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", - "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", - "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", + "node_modules/esbuild-linux-arm64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.42.tgz", + "integrity": "sha512-c3Ug3e9JpVr8jAcfbhirtpBauLxzYPpycjWulD71CF6ZSY26tvzmXMJYooQ2YKqDY4e/fPu5K8bm7MiXMnyxuA==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@kyvg/vue3-notification": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@kyvg/vue3-notification/-/vue3-notification-2.3.4.tgz", - "integrity": "sha512-20Km1L75gncIZCjosT1OKbJl9HhNiOd7LRXqVIqlehHHem9NgBjQhDFz6XGo1RcF0MyA4/BC7kV7tcq/PMT+tA==", - "peerDependencies": { - "vue": "^3.0.0" + "node_modules/esbuild-linux-mips64le": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.42.tgz", + "integrity": "sha512-QuvpHGbYlkyXWf2cGm51LBCHx6eUakjaSrRpUqhPwjh/uvNUYvLmz2LgPTTPwCqaKt0iwL+OGVL0tXA5aDbAbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@nitro_repo/nitro_repo-api-wrapper": { - "resolved": "../nitro_repo-api-wrapper", - "link": true - }, - "node_modules/@node-ipc/js-queue": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@node-ipc/js-queue/-/js-queue-2.0.3.tgz", - "integrity": "sha512-fL1wpr8hhD5gT2dA1qifeVaoDFlQR5es8tFuKqjHX+kdOtdNHnxkVZbtIrR2rxnMFvehkjaZRNV2H/gPXlb0hw==", + "node_modules/esbuild-linux-ppc64le": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.42.tgz", + "integrity": "sha512-8ohIVIWDbDT+i7lCx44YCyIRrOW1MYlks9fxTo0ME2LS/fxxdoJBwHWzaDYhjvf8kNpA+MInZvyOEAGoVDrMHg==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "easy-stack": "1.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=1.0.0" + "node": ">=12" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/esbuild-linux-riscv64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.42.tgz", + "integrity": "sha512-DzDqK3TuoXktPyG1Lwx7vhaF49Onv3eR61KwQyxYo4y5UKTpL3NmuarHSIaSVlTFDDpcIajCDwz5/uwKLLgKiQ==", + "cpu": [ + "riscv64" + ], "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 8" + "node": ">=12" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/esbuild-linux-s390x": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.42.tgz", + "integrity": "sha512-YFRhPCxl8nb//Wn6SiS5pmtplBi4z9yC2gLrYoYI/tvwuB1jldir9r7JwAGy1Ck4D7sE7wBN9GFtUUX/DLdcEQ==", + "cpu": [ + "s390x" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 8" + "node": ">=12" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/esbuild-netbsd-64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.42.tgz", + "integrity": "sha512-QYSD2k+oT9dqB/4eEM9c+7KyNYsIPgzYOSrmfNGDIyJrbT1d+CFVKvnKahDKNJLfOYj8N4MgyFaU9/Ytc6w5Vw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">= 8" + "node": ">=12" } }, - "node_modules/@polka/url": { - "version": "1.0.0-next.21", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", - "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==", - "dev": true - }, - "node_modules/@rollup/pluginutils": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", - "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "node_modules/esbuild-openbsd-64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.42.tgz", + "integrity": "sha512-M2meNVIKWsm2HMY7+TU9AxM7ZVwI9havdsw6m/6EzdXysyCFFSoaTQ/Jg03izjCsK17FsVRHqRe26Llj6x0MNA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">= 8.0.0" + "node": ">=12" } }, - "node_modules/@sideway/address": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", - "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "node_modules/esbuild-sunos-64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.42.tgz", + "integrity": "sha512-uXV8TAZEw36DkgW8Ak3MpSJs1ofBb3Smkc/6pZ29sCAN1KzCAQzsje4sUwugf+FVicrHvlamCOlFZIXgct+iqQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0" + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@sideway/formula": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", - "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==", - "dev": true - }, - "node_modules/@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", - "dev": true - }, - "node_modules/@soda/friendly-errors-webpack-plugin": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.8.1.tgz", - "integrity": "sha512-h2ooWqP8XuFqTXT+NyAFbrArzfQA7R6HTezADrvD9Re8fxMLTPPniLdqVTdDaO0eIoLaAwKT+d6w+5GeTk7Vbg==", + "node_modules/esbuild-windows-32": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.42.tgz", + "integrity": "sha512-4iw/8qWmRICWi9ZOnJJf9sYt6wmtp3hsN4TdI5NqgjfOkBVMxNdM9Vt3626G1Rda9ya2Q0hjQRD9W1o+m6Lz6g==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "chalk": "^3.0.0", - "error-stack-parser": "^2.0.6", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=8.0.0" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" + "node": ">=12" } }, - "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/esbuild-windows-64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.42.tgz", + "integrity": "sha512-j3cdK+Y3+a5H0wHKmLGTJcq0+/2mMBHPWkItR3vytp/aUGD/ua/t2BLdfBIzbNN9nLCRL9sywCRpOpFMx3CxzA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=12" } }, - "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "node_modules/esbuild-windows-arm64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.42.tgz", + "integrity": "sha512-+lRAARnF+hf8J0mN27ujO+VbhPbDqJ8rCcJKye4y7YZLV6C4n3pTRThAb388k/zqF5uM0lS5O201u0OqoWSicw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": ">=6" } }, - "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/has-flag": { + "node_modules/escape-string-regexp": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "engines": { - "node": ">=8" - } - }, - "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.16.0.tgz", + "integrity": "sha512-MBndsoXY/PeVTDJeWsYj7kLZ5hQpJOfMYLsF6LicLHQWbRDG19lK5jOix4DPl8yY4SUFcE3txy86OzFLWT+yoA==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@eslint/eslintrc": "^1.3.0", + "@humanwhocodes/config-array": "^0.9.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.2", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@soda/get-current-script": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@soda/get-current-script/-/get-current-script-1.0.2.tgz", - "integrity": "sha512-T7VNNlYVM1SgQ+VsMYhnDkcGmWhQdL0bDyGm5TlQ3GBXnJscEClUUOKduWTmm2zCnvNLC1hc3JpuXjs/nFOc5w==", - "dev": true - }, - "node_modules/@transloadit/prettier-bytes": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz", - "integrity": "sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA==" - }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "node_modules/eslint-config-prettier": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", + "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", "dev": true, - "engines": { - "node": ">=10.13.0" + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" } }, - "node_modules/@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "node_modules/eslint-plugin-prettier": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", + "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", "dev": true, "dependencies": { - "@types/connect": "*", - "@types/node": "*" + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } } }, - "node_modules/@types/bonjour": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", - "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", + "node_modules/eslint-plugin-vue": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-8.0.1.tgz", + "integrity": "sha512-h7SJFNECfkx89CeH3VCGGhLcm4VLOsOZ+DUSGk0h/aCqm9Outm/sIkoOvNpCebsb0U+uBzb93v2yZ6k7Vzy6LQ==", "dev": true, "dependencies": { - "@types/node": "*" + "eslint-utils": "^3.0.0", + "natural-compare": "^1.4.0", + "semver": "^7.3.5", + "vue-eslint-parser": "^8.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "dependencies": { - "@types/node": "*" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" } }, - "node_modules/@types/connect-history-api-fallback": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz", - "integrity": "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==", + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "dev": true, "dependencies": { - "@types/express-serve-static-core": "*", - "@types/node": "*" + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" } }, - "node_modules/@types/cookie": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz", - "integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==", - "optional": true - }, - "node_modules/@types/eslint": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz", - "integrity": "sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng==", + "node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" + "engines": { + "node": ">=10" } }, - "node_modules/@types/eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", "dev": true, "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "node_modules/@types/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", "dev": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.28", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", - "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" + "engines": { + "node": ">=4.0" } }, - "node_modules/@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", - "dev": true - }, - "node_modules/@types/http-proxy": { - "version": "1.17.8", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz", - "integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==", + "node_modules/espree": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", + "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", "dev": true, "dependencies": { - "@types/node": "*" + "acorn": "^8.7.1", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "node_modules/@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "dev": true - }, - "node_modules/@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "node_modules/@types/node": { - "version": "17.0.23", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", - "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==", - "dev": true - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "node_modules/@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true - }, - "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true - }, - "node_modules/@types/retry": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", - "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", - "dev": true - }, - "node_modules/@types/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", "dev": true, - "dependencies": { - "@types/express": "*" + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@types/serve-static": { - "version": "1.13.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", - "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, "dependencies": { - "@types/mime": "^1", - "@types/node": "*" + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" } }, - "node_modules/@types/sockjs": { - "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", - "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "dependencies": { - "@types/node": "*" + "engines": { + "node": ">=4.0" } }, - "node_modules/@types/webpack-env": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.16.3.tgz", - "integrity": "sha512-9gtOPPkfyNoEqCQgx4qJKkuNm/x0R2hKR7fdl7zvTJyHnIisuE/LfvXOsYWL0o3qq6uiBnKZNNNzi3l0y/X+xw==", - "dev": true - }, - "node_modules/@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "dependencies": { - "@types/node": "*" + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" } }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.26.0.tgz", - "integrity": "sha512-oGCmo0PqnRZZndr+KwvvAUvD3kNE4AfyoGCwOZpoCncSh4MVD06JTE8XQa2u9u+NX5CsyZMBTEc2C72zx38eYA==", + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.26.0", - "@typescript-eslint/type-utils": "5.26.0", - "@typescript-eslint/utils": "5.26.0", - "debug": "^4.3.4", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.2.0", - "regexpp": "^3.2.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=4.0" } }, - "node_modules/@typescript-eslint/parser": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.26.0.tgz", - "integrity": "sha512-n/IzU87ttzIdnAH5vQ4BBDnLPly7rC5VnjN3m0xBG82HK6rhRxnCb3w/GyWbNDghPd+NktJqB/wl6+YkzZ5T5Q==", + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.26.0", - "@typescript-eslint/types": "5.26.0", - "@typescript-eslint/typescript-estree": "5.26.0", - "debug": "^4.3.4" - }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=4.0" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.26.0.tgz", - "integrity": "sha512-gVzTJUESuTwiju/7NiTb4c5oqod8xt5GhMbExKsCTp6adU3mya6AGJ4Pl9xC7x2DX9UYFsjImC0mA62BCY22Iw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.26.0", - "@typescript-eslint/visitor-keys": "5.26.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.26.0.tgz", - "integrity": "sha512-7ccbUVWGLmcRDSA1+ADkDBl5fP87EJt0fnijsMFTVHXKGduYMgienC/i3QwoVhDADUAPoytgjbZbCOMj4TY55A==", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, - "dependencies": { - "@typescript-eslint/utils": "5.26.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=0.10.0" } }, - "node_modules/@typescript-eslint/types": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.26.0.tgz", - "integrity": "sha512-8794JZFE1RN4XaExLWLI2oSXsVImNkl79PzTOOWt9h0UHROwJedNOD2IJyfL0NbddFllcktGIO2aOu10avQQyA==", + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, + "optional": true, + "peer": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=0.8.x" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.26.0.tgz", - "integrity": "sha512-EyGpw6eQDsfD6jIqmXP3rU5oHScZ51tL/cZgFbFBvWuCwrIptl+oueUZzSmLtxFuSOQ9vDcJIs+279gnJkfd1w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.26.0", - "@typescript-eslint/visitor-keys": "5.26.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true }, - "node_modules/@typescript-eslint/utils": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.26.0.tgz", - "integrity": "sha512-PJFwcTq2Pt4AMOKfe3zQOdez6InIDOjUJJD3v3LyEtxHGVVRK3Vo7Dd923t/4M9hSH2q2CLvcTdxlLPjcIk3eg==", + "node_modules/fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", "dev": true, "dependencies": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.26.0", - "@typescript-eslint/types": "5.26.0", - "@typescript-eslint/typescript-estree": "5.26.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "node": ">=8.6.0" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.26.0.tgz", - "integrity": "sha512-wei+ffqHanYDOQgg/fS6Hcar6wAWv0CUPQ3TZzOWd2BLfgP539rb49bwua8WRAs7R6kOSLn82rfEu2ro6Llt8Q==", + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.26.0", - "eslint-visitor-keys": "^3.3.0" + "is-glob": "^4.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">= 6" } }, - "node_modules/@uppy/core": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@uppy/core/-/core-2.2.0.tgz", - "integrity": "sha512-qdDoNCjrVjjOmFCFCxc+HEbtbQ9K0k6LKNbZZwWK7d4Cx3xEa6VsxmqVhfFL6ekH2gyboqYV8Z5IbRkJT/0Nqg==", - "peer": true, - "dependencies": { - "@transloadit/prettier-bytes": "0.0.7", - "@uppy/store-default": "^2.0.3", - "@uppy/utils": "^4.0.7", - "lodash.throttle": "^4.1.1", - "mime-match": "^1.0.2", - "namespace-emitter": "^2.0.1", - "nanoid": "^3.1.25", - "preact": "^10.5.13" - } - }, - "node_modules/@uppy/dashboard": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@uppy/dashboard/-/dashboard-2.1.4.tgz", - "integrity": "sha512-H9SIuDJCMThBm9VUkb4Rkvl2qAll5tDi7l7Z6A0+07HkfVFVJv8Aq6Lh/sCAVv9v9M7KKBu0X2eCc8o5+22+zA==", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, "dependencies": { - "@transloadit/prettier-bytes": "0.0.7", - "@uppy/informer": "^2.0.5", - "@uppy/provider-views": "^2.0.7", - "@uppy/status-bar": "^2.1.2", - "@uppy/thumbnail-generator": "^2.1.0", - "@uppy/utils": "^4.0.5", - "classnames": "^2.2.6", - "is-shallow-equal": "^1.0.1", - "lodash.debounce": "^4.0.8", - "memoize-one": "^5.0.4", - "nanoid": "^3.1.25", - "preact": "^10.5.13" - }, - "peerDependencies": { - "@uppy/core": "^2.1.5" + "reusify": "^1.0.4" } }, - "node_modules/@uppy/drag-drop": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@uppy/drag-drop/-/drag-drop-2.1.0.tgz", - "integrity": "sha512-kmxhXVlIS/viyjV+yypCzHDJ0A9MVfPo348tHsAYGNmH25NkjEUmM7DAgb2qmALvzCH3BRFuloq+glLH4i18+g==", + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, "dependencies": { - "@uppy/utils": "^4.0.7", - "preact": "^10.5.13" + "flat-cache": "^3.0.4" }, - "peerDependencies": { - "@uppy/core": "^2.2.0" + "engines": { + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/@uppy/file-input": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@uppy/file-input/-/file-input-2.0.6.tgz", - "integrity": "sha512-Au/J96B6yiGZkjNpLO+/hV43Beq71K3JP2p1f9Eh0EgcgLtqczmM8pggyj6vAduywamUTMWGaADKcdxYKLAFew==", + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", "dependencies": { - "@uppy/utils": "^4.0.7", - "preact": "^10.5.13" - }, - "peerDependencies": { - "@uppy/core": "^2.1.9" + "minimatch": "^5.0.1" } }, - "node_modules/@uppy/informer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@uppy/informer/-/informer-2.0.5.tgz", - "integrity": "sha512-XBiTo+NYUMkG3RnwFXmQTnwOcTaBMzMqSTTZZ1/1NndxP1TmpmqonuQQIHlegHUHhF5T+GVAle2rMe+c8iSlsA==", + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dependencies": { - "@uppy/utils": "^4.0.4", - "preact": "^10.5.13" - }, - "peerDependencies": { - "@uppy/core": "^2.1.3" + "balanced-match": "^1.0.0" } }, - "node_modules/@uppy/progress-bar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@uppy/progress-bar/-/progress-bar-2.0.4.tgz", - "integrity": "sha512-W0ATXPP6Ufhb3B0hPPDlO3VVknohpkOA/o/LFVdkOIpq3+mKxkb1+/Nlt3uTa6gxO57O1D6+Kg+l9WKIqpyTbg==", + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", "dependencies": { - "@uppy/utils": "^4.0.3", - "preact": "^10.5.13" + "brace-expansion": "^2.0.1" }, - "peerDependencies": { - "@uppy/core": "^2.0.0" + "engines": { + "node": ">=10" } }, - "node_modules/@uppy/provider-views": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@uppy/provider-views/-/provider-views-2.0.8.tgz", - "integrity": "sha512-rgCehk4yQFcxbXxdAKEDZe1wiecgZfuJ2FtPUk1atF9IHg7/MekCTLLbKBKh5saLX+uPIuqUXnbLIa+7XKPrgw==", + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, "dependencies": { - "@uppy/utils": "^4.0.5", - "classnames": "^2.2.6", - "preact": "^10.5.13" + "to-regex-range": "^5.0.1" }, - "peerDependencies": { - "@uppy/core": "^2.1.6" + "engines": { + "node": ">=8" } }, - "node_modules/@uppy/status-bar": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@uppy/status-bar/-/status-bar-2.1.3.tgz", - "integrity": "sha512-+rGZruKzptQ8wVfKXCwDBR9Mw1a/8GECKQ6EwEDzfJxhwz1Tm6kdh5DHDOUlftPTJGJED3bKye7K7fjEhwWfew==", + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, "dependencies": { - "@transloadit/prettier-bytes": "0.0.7", - "@uppy/utils": "^4.0.5", - "classnames": "^2.2.6", - "lodash.throttle": "^4.1.1", - "preact": "^10.5.13" + "flatted": "^3.1.0", + "rimraf": "^3.0.2" }, - "peerDependencies": { - "@uppy/core": "^2.1.6" + "engines": { + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/@uppy/store-default": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@uppy/store-default/-/store-default-2.0.3.tgz", - "integrity": "sha512-2BGlN1sW0cFv4rOqTK8dfSg579S984N1HxCJxLFqeW9nWD6zd/O8Omyd85tbxGQ+FLZLTmLOm/feD0YeCBMahg==", - "peer": true + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true }, - "node_modules/@uppy/thumbnail-generator": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@uppy/thumbnail-generator/-/thumbnail-generator-2.1.1.tgz", - "integrity": "sha512-iV7Q6Z3huN3RgXiXStKXsHCk6doRzxtkkiQkejpVD8NPODWvgOpL8EFjTqii//3sZJYgquZTWQkMuAJVuoFSSw==", - "dependencies": { - "@uppy/utils": "^4.0.5", - "exifr": "^7.0.0" + "node_modules/follow-redirects": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" }, - "peerDependencies": { - "@uppy/core": "^2.1.5" + "peerDependenciesMeta": { + "debug": { + "optional": true + } } }, - "node_modules/@uppy/utils": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-4.0.7.tgz", - "integrity": "sha512-nKViMT8XchKy+NWpb3DtVKuzZBmW7au26LrMq89EsvTwIOT6UR9+7bmz/+zr3+lc7UC7vMgNChIC6G+/Ya9wWQ==", + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dependencies": { - "lodash.throttle": "^4.1.1" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/@uppy/vue": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@uppy/vue/-/vue-0.4.7.tgz", - "integrity": "sha512-gIDmHA463J6QKwUSZoKsb4qYNu/IaoG3AemJIuV8PcnA/poLn09icLusZDG7IY1WbWEvPogq8P24p37FRoB3bw==", - "dependencies": { - "@uppy/dashboard": "^2.1.4", - "@uppy/drag-drop": "^2.0.7", - "@uppy/file-input": "^2.0.6", - "@uppy/progress-bar": "^2.0.4", - "@uppy/status-bar": "^2.1.3", - "shallow-equal": "^1.2.1" + "node_modules/fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "dev": true, + "engines": { + "node": "*" }, - "peerDependencies": { - "@uppy/core": "^2.1.9", - "vue": ">=2.6.11" + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" } }, - "node_modules/@vitejs/plugin-vue": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.3.3.tgz", - "integrity": "sha512-SmQLDyhz+6lGJhPELsBdzXGc+AcaT8stgkbiTFGpXPe8Tl1tJaBw1A6pxDqDuRsVkD8uscrkx3hA7QDOoKYtyw==", + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "vite": "^2.5.10", - "vue": "^3.2.25" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/@vue/babel-helper-vue-jsx-merge-props": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.2.1.tgz", - "integrity": "sha512-QOi5OW45e2R20VygMSNhyQHvpdUwQZqGPc748JLGCYEy+yp8fNFNdbNIGAgZmi9e+2JHPd6i6idRuqivyicIkA==", + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, - "node_modules/@vue/babel-helper-vue-transform-on": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.0.2.tgz", - "integrity": "sha512-hz4R8tS5jMn8lDq6iD+yWL6XNB699pGIVLk7WSJnn1dbpjaazsjZQkieJoRX6gW5zpYSCFqQ7jUquPNY65tQYA==", + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", "dev": true }, - "node_modules/@vue/babel-plugin-jsx": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.1.1.tgz", - "integrity": "sha512-j2uVfZjnB5+zkcbc/zsOc0fSNGCMMjaEXP52wdwdIfn0qjFfEYpYZBFKFg+HHnQeJCVrjOeO0YxgaL7DMrym9w==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.0.0", - "@babel/template": "^7.0.0", - "@babel/traverse": "^7.0.0", - "@babel/types": "^7.0.0", - "@vue/babel-helper-vue-transform-on": "^1.0.2", - "camelcase": "^6.0.0", - "html-tags": "^3.1.0", - "svg-tags": "^1.0.0" - } - }, - "node_modules/@vue/babel-plugin-transform-vue-jsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.2.1.tgz", - "integrity": "sha512-HJuqwACYehQwh1fNT8f4kyzqlNMpBuUK4rSiSES5D4QsYncv5fxFsLyrxFPG2ksO7t5WP+Vgix6tt6yKClwPzA==", + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.2.0", - "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", - "html-tags": "^2.0.0", - "lodash.kebabcase": "^4.1.1", - "svg-tags": "^1.0.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@vue/babel-plugin-transform-vue-jsx/node_modules/html-tags": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", - "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", - "dev": true, "engines": { - "node": ">=4" - } - }, - "node_modules/@vue/babel-preset-app": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-5.0.4.tgz", - "integrity": "sha512-vf4KqrmuOSnoEYGUiHPeMoxhh6wpiucLWXISn7xYFU80pK1lqcuhbl6tpurAanUIyRO/ENDUQBH7RAdbLNq1bA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.16", - "@babel/helper-compilation-targets": "^7.12.16", - "@babel/helper-module-imports": "^7.12.13", - "@babel/plugin-proposal-class-properties": "^7.12.13", - "@babel/plugin-proposal-decorators": "^7.12.13", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-jsx": "^7.12.13", - "@babel/plugin-transform-runtime": "^7.12.15", - "@babel/preset-env": "^7.12.16", - "@babel/runtime": "^7.12.13", - "@vue/babel-plugin-jsx": "^1.0.3", - "@vue/babel-preset-jsx": "^1.1.2", - "babel-plugin-dynamic-import-node": "^2.3.3", - "core-js": "^3.8.3", - "core-js-compat": "^3.8.3", - "semver": "^7.3.4" - }, - "peerDependencies": { - "@babel/core": "*", - "core-js": "^3", - "vue": "^2 || ^3.2.13" + "node": "*" }, - "peerDependenciesMeta": { - "core-js": { - "optional": true - }, - "vue": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@vue/babel-preset-jsx": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@vue/babel-preset-jsx/-/babel-preset-jsx-1.2.4.tgz", - "integrity": "sha512-oRVnmN2a77bYDJzeGSt92AuHXbkIxbf/XXSE3klINnh9AXBmVS1DGa1f0d+dDYpLfsAKElMnqKTQfKn7obcL4w==", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "dependencies": { - "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", - "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", - "@vue/babel-sugar-composition-api-inject-h": "^1.2.1", - "@vue/babel-sugar-composition-api-render-instance": "^1.2.4", - "@vue/babel-sugar-functional-vue": "^1.2.2", - "@vue/babel-sugar-inject-h": "^1.2.2", - "@vue/babel-sugar-v-model": "^1.2.3", - "@vue/babel-sugar-v-on": "^1.2.3" + "is-glob": "^4.0.3" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=10.13.0" } }, - "node_modules/@vue/babel-sugar-composition-api-inject-h": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-inject-h/-/babel-sugar-composition-api-inject-h-1.2.1.tgz", - "integrity": "sha512-4B3L5Z2G+7s+9Bwbf+zPIifkFNcKth7fQwekVbnOA3cr3Pq71q71goWr97sk4/yyzH8phfe5ODVzEjX7HU7ItQ==", + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true, - "dependencies": { - "@babel/plugin-syntax-jsx": "^7.2.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "peer": true }, - "node_modules/@vue/babel-sugar-composition-api-render-instance": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-render-instance/-/babel-sugar-composition-api-render-instance-1.2.4.tgz", - "integrity": "sha512-joha4PZznQMsxQYXtR3MnTgCASC9u3zt9KfBxIeuI5g2gscpTsSKRDzWQt4aqNIpx6cv8On7/m6zmmovlNsG7Q==", + "node_modules/globals": { + "version": "13.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", + "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", "dev": true, "dependencies": { - "@babel/plugin-syntax-jsx": "^7.2.0" + "type-fest": "^0.20.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@vue/babel-sugar-functional-vue": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-functional-vue/-/babel-sugar-functional-vue-1.2.2.tgz", - "integrity": "sha512-JvbgGn1bjCLByIAU1VOoepHQ1vFsroSA/QkzdiSs657V79q6OwEWLCQtQnEXD/rLTA8rRit4rMOhFpbjRFm82w==", + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "dependencies": { - "@babel/plugin-syntax-jsx": "^7.2.0" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@vue/babel-sugar-inject-h": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-inject-h/-/babel-sugar-inject-h-1.2.2.tgz", - "integrity": "sha512-y8vTo00oRkzQTgufeotjCLPAvlhnpSkcHFEp60+LJUwygGcd5Chrpn5480AQp/thrxVm8m2ifAk0LyFel9oCnw==", + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true, - "dependencies": { - "@babel/plugin-syntax-jsx": "^7.2.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "peer": true }, - "node_modules/@vue/babel-sugar-v-model": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.2.3.tgz", - "integrity": "sha512-A2jxx87mySr/ulAsSSyYE8un6SIH0NWHiLaCWpodPCVOlQVODCaSpiR4+IMsmBr73haG+oeCuSvMOM+ttWUqRQ==", + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "dependencies": { - "@babel/plugin-syntax-jsx": "^7.2.0", - "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", - "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", - "camelcase": "^5.0.0", - "html-tags": "^2.0.0", - "svg-tags": "^1.0.0" + "function-bind": "^1.1.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">= 0.4.0" } }, - "node_modules/@vue/babel-sugar-v-model/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/@vue/babel-sugar-v-model/node_modules/html-tags": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", - "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true, "engines": { - "node": ">=4" + "node": ">= 4" } }, - "node_modules/@vue/babel-sugar-v-on": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.2.3.tgz", - "integrity": "sha512-kt12VJdz/37D3N3eglBywV8GStKNUhNrsxChXIV+o0MwVXORYuhDTHJRKPgLJRb/EY3vM2aRFQdxJBp9CLikjw==", + "node_modules/immutable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz", + "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==", + "dev": true + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "dependencies": { - "@babel/plugin-syntax-jsx": "^7.2.0", - "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", - "camelcase": "^5.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@vue/babel-sugar-v-on/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "engines": { - "node": ">=6" + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/@vue/cli-overlay": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@vue/cli-overlay/-/cli-overlay-5.0.4.tgz", - "integrity": "sha512-ZTLAAydILjvx0XHUGSNu/cQDpmvLTMYUutDf2vf6XGkSWYqncQ6RwkeMSQhvQNlgpa/ovwIgrlGxLoojFRwdVg==", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "node_modules/@vue/cli-plugin-babel": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-babel/-/cli-plugin-babel-5.0.4.tgz", - "integrity": "sha512-413ZwOWLtgw5vWJoMbrv36crW3qTas4Iru8sU7cRb0IqEZbS28R9X4PVtO8Pek2NYFbrs2XKRYOB7GblB6hVqg==", + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "dependencies": { - "@babel/core": "^7.12.16", - "@vue/babel-preset-app": "^5.0.4", - "@vue/cli-shared-utils": "^5.0.4", - "babel-loader": "^8.2.2", - "thread-loader": "^3.0.0", - "webpack": "^5.54.0" + "binary-extensions": "^2.0.0" }, - "peerDependencies": { - "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0" + "engines": { + "node": ">=8" } }, - "node_modules/@vue/cli-plugin-eslint": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-eslint/-/cli-plugin-eslint-5.0.4.tgz", - "integrity": "sha512-NLBEKFTFJhYHMzQ3z+sb6xlkcNaN/RcbZ3hiCY72aJe4YOO8jEAp0XkPzlHd4xYkMW7jrmOwwLOPw+3BJ4b77Q==", + "node_modules/is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", "dev": true, "dependencies": { - "@vue/cli-shared-utils": "^5.0.4", - "eslint-webpack-plugin": "^3.1.0", - "globby": "^11.0.2", - "webpack": "^5.54.0", - "yorkie": "^2.0.0" + "has": "^1.0.3" }, - "peerDependencies": { - "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0", - "eslint": ">=7.5.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@vue/cli-plugin-router": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-router/-/cli-plugin-router-5.0.4.tgz", - "integrity": "sha512-lylzCuH3Br0BcTz5IxxSffpyoF9dQ2k4jTdK8QlWrnRanWGw7P9C0kYMr9rohHaXpvAlu6bio392gbNIWpEepg==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, - "dependencies": { - "@vue/cli-shared-utils": "^5.0.4" - }, - "peerDependencies": { - "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@vue/cli-plugin-typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-typescript/-/cli-plugin-typescript-5.0.4.tgz", - "integrity": "sha512-ITIt9hDc94gI4UCdsoAKYtFp2LAXF9fNYQqXminTnctd0UuTSXGvQcLmCnMYgKfKPVVcAWfG3vCMiB5bsd+Kyg==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "dependencies": { - "@babel/core": "^7.12.16", - "@types/webpack-env": "^1.15.2", - "@vue/cli-shared-utils": "^5.0.4", - "babel-loader": "^8.2.2", - "fork-ts-checker-webpack-plugin": "^6.4.0", - "globby": "^11.0.2", - "thread-loader": "^3.0.0", - "ts-loader": "^9.2.5", - "webpack": "^5.54.0", - "yorkie": "^2.0.0" - }, - "peerDependencies": { - "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0", - "cache-loader": "^4.1.0", - "typescript": ">=2", - "vue": "^2 || ^3.2.13", - "vue-template-compiler": "^2.0.0" + "is-extglob": "^2.1.1" }, - "peerDependenciesMeta": { - "cache-loader": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - } + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@vue/cli-plugin-vuex": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-vuex/-/cli-plugin-vuex-5.0.4.tgz", - "integrity": "sha512-dBwiD6mT9+V2HTHcwaWE8qFNgTk5I/NUvxYVeUN3Mmmpo4y/1RxXnr7BlKGnaQsTypb2RFk3KowqIJtg7s+E3Q==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "peerDependencies": { - "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0" + "engines": { + "node": ">=0.12.0" } }, - "node_modules/@vue/cli-service": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@vue/cli-service/-/cli-service-5.0.4.tgz", - "integrity": "sha512-xRiLNTFYmMCT9edZpyYXHijW5xot3gbZpcWDOXUOhKPHN4qs4XqWALnZlU97JYjZOr3XIr/ZvyciyEfrlUVqSA==", - "dev": true, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", "dependencies": { - "@babel/helper-compilation-targets": "^7.12.16", - "@soda/friendly-errors-webpack-plugin": "^1.8.0", - "@soda/get-current-script": "^1.0.2", - "@types/minimist": "^1.2.0", - "@vue/cli-overlay": "^5.0.4", - "@vue/cli-plugin-router": "^5.0.4", - "@vue/cli-plugin-vuex": "^5.0.4", - "@vue/cli-shared-utils": "^5.0.4", - "@vue/component-compiler-utils": "^3.3.0", - "@vue/vue-loader-v15": "npm:vue-loader@^15.9.7", - "@vue/web-component-wrapper": "^1.3.0", - "acorn": "^8.0.5", - "acorn-walk": "^8.0.2", - "address": "^1.1.2", - "autoprefixer": "^10.2.4", - "browserslist": "^4.16.3", - "case-sensitive-paths-webpack-plugin": "^2.3.0", - "cli-highlight": "^2.1.10", - "clipboardy": "^2.3.0", - "cliui": "^7.0.4", - "copy-webpack-plugin": "^9.0.1", - "css-loader": "^6.5.0", - "css-minimizer-webpack-plugin": "^3.0.2", - "cssnano": "^5.0.0", - "debug": "^4.1.1", - "default-gateway": "^6.0.3", - "dotenv": "^10.0.0", - "dotenv-expand": "^5.1.0", - "fs-extra": "^9.1.0", - "globby": "^11.0.2", - "hash-sum": "^2.0.0", - "html-webpack-plugin": "^5.1.0", - "is-file-esm": "^1.0.0", - "launch-editor-middleware": "^2.2.1", - "lodash.defaultsdeep": "^4.6.1", - "lodash.mapvalues": "^4.6.0", - "mini-css-extract-plugin": "^2.5.3", - "minimist": "^1.2.5", - "module-alias": "^2.2.2", - "portfinder": "^1.0.26", - "postcss": "^8.2.6", - "postcss-loader": "^6.1.1", - "progress-webpack-plugin": "^1.0.12", - "ssri": "^8.0.1", - "terser-webpack-plugin": "^5.1.1", - "thread-loader": "^3.0.0", - "vue-loader": "^17.0.0", - "vue-style-loader": "^4.1.3", - "webpack": "^5.54.0", - "webpack-bundle-analyzer": "^4.4.0", - "webpack-chain": "^6.5.1", - "webpack-dev-server": "^4.7.3", - "webpack-merge": "^5.7.3", - "webpack-virtual-modules": "^0.4.2", - "whatwg-fetch": "^3.6.2" + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" }, "bin": { - "vue-cli-service": "bin/vue-cli-service.js" + "jake": "bin/cli.js" }, "engines": { - "node": "^12.0.0 || >= 14.0.0" - }, - "peerDependencies": { - "vue-template-compiler": "^2.0.0", - "webpack-sources": "*" - }, - "peerDependenciesMeta": { - "cache-loader": { - "optional": true - }, - "less-loader": { - "optional": true - }, - "pug-plain-loader": { - "optional": true - }, - "raw-loader": { - "optional": true - }, - "sass-loader": { - "optional": true - }, - "stylus-loader": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - }, - "webpack-sources": { - "optional": true - } + "node": ">=10" } }, - "node_modules/@vue/cli-shared-utils": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@vue/cli-shared-utils/-/cli-shared-utils-5.0.4.tgz", - "integrity": "sha512-nfAsj8Nopu5sVHMBIaut/YL7NaJFVmTBSTJD7LM17jc5uytrM9JwiRtzCiv3JWRBG78Xdb/s2Xb/1YR4fkdmkQ==", - "dev": true, - "dependencies": { - "@achrinza/node-ipc": "9.2.2", - "chalk": "^4.1.2", - "execa": "^1.0.0", - "joi": "^17.4.0", - "launch-editor": "^2.2.1", - "lru-cache": "^6.0.0", - "node-fetch": "^2.6.7", - "open": "^8.0.2", - "ora": "^5.3.0", - "read-pkg": "^5.1.1", - "semver": "^7.3.4", - "strip-ansi": "^6.0.0" - } - }, - "node_modules/@vue/cli-shared-utils/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/jake/node_modules/async": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "color-convert": "^2.0.1" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">= 10.13.0" } }, - "node_modules/@vue/cli-shared-utils/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "argparse": "^2.0.1" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@vue/cli-shared-utils/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } + "optional": true, + "peer": true }, - "node_modules/@vue/cli-shared-utils/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, - "node_modules/@vue/cli-shared-utils/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true }, - "node_modules/@vue/cli-shared-utils/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/@vue/compiler-core": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.36.tgz", - "integrity": "sha512-bbyZM5hvBicv0PW3KUfVi+x3ylHnfKG7DOn5wM+f2OztTzTjLEyBb/5yrarIYpmnGitVGbjZqDbODyW4iK8hqw==", - "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/shared": "3.2.36", - "estree-walker": "^2.0.2", - "source-map": "^0.6.1" + "node": ">= 0.8.0" } }, - "node_modules/@vue/compiler-core/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/lilconfig": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz", + "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", + "dev": true, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@vue/compiler-dom": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.36.tgz", - "integrity": "sha512-tcOTAOiW4s24QLnq+ON6J+GRONXJ+A/mqKCORi0LSlIh8XQlNnlm24y8xIL8la+ZDgkdbjarQ9ZqYSvEja6gVA==", - "dependencies": { - "@vue/compiler-core": "3.2.36", - "@vue/shared": "3.2.36" - } - }, - "node_modules/@vue/compiler-sfc": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.36.tgz", - "integrity": "sha512-AvGb4bTj4W8uQ4BqaSxo7UwTEqX5utdRSMyHy58OragWlt8nEACQ9mIeQh3K4di4/SX+41+pJrLIY01lHAOFOA==", - "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.36", - "@vue/compiler-dom": "3.2.36", - "@vue/compiler-ssr": "3.2.36", - "@vue/reactivity-transform": "3.2.36", - "@vue/shared": "3.2.36", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7", - "postcss": "^8.1.10", - "source-map": "^0.6.1" + "node": ">=10" } }, - "node_modules/@vue/compiler-sfc/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "optional": true, + "peer": true, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@vue/compiler-ssr": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.36.tgz", - "integrity": "sha512-+KugInUFRvOxEdLkZwE+W43BqHyhBh0jpYXhmqw1xGq2dmE6J9eZ8UUSOKNhdHtQ/iNLWWeK/wPZkVLUf3YGaw==", - "dependencies": { - "@vue/compiler-dom": "3.2.36", - "@vue/shared": "3.2.36" + "node": ">=6.11.5" } }, - "node_modules/@vue/component-compiler-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz", - "integrity": "sha512-97sfH2mYNU+2PzGrmK2haqffDpVASuib9/w2/noxiFi31Z54hW+q3izKQXXQZSNhtiUpAI36uSuYepeBe4wpHQ==", + "node_modules/local-pkg": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.1.tgz", + "integrity": "sha512-lL87ytIGP2FU5PWwNDo0w3WhIo2gopIAxPg9RxDYF7m4rr5ahuZxP22xnJHIvaLTe4Z9P6uKKY2UHiwyB4pcrw==", "dev": true, - "dependencies": { - "consolidate": "^0.15.1", - "hash-sum": "^1.0.2", - "lru-cache": "^4.1.2", - "merge-source-map": "^1.1.0", - "postcss": "^7.0.36", - "postcss-selector-parser": "^6.0.2", - "source-map": "~0.6.1", - "vue-template-es2015-compiler": "^1.9.0" + "engines": { + "node": ">=14" }, - "optionalDependencies": { - "prettier": "^1.18.2 || ^2.0.0" + "funding": { + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/@vue/component-compiler-utils/node_modules/hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, - "node_modules/@vue/component-compiler-utils/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/@vue/component-compiler-utils/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/@vue/component-compiler-utils/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" + "yallist": "^4.0.0" }, "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" + "node": ">=10" } }, - "node_modules/@vue/component-compiler-utils/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dependencies": { + "sourcemap-codec": "^1.4.8" } }, - "node_modules/@vue/component-compiler-utils/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "optional": true, + "peer": true }, - "node_modules/@vue/devtools-api": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.1.4.tgz", - "integrity": "sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ==" + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } }, - "node_modules/@vue/eslint-config-prettier": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-7.0.0.tgz", - "integrity": "sha512-/CTc6ML3Wta1tCe1gUeO0EYnVXfo3nJXsIhZ8WJr3sov+cGASr6yuiibJTL6lmIBm7GobopToOuB3B6AWyV0Iw==", + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "dependencies": { - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-prettier": "^4.0.0" + "braces": "^3.0.2", + "picomatch": "^2.3.1" }, - "peerDependencies": { - "eslint": ">= 7.28.0", - "prettier": ">= 2.0.0" + "engines": { + "node": ">=8.6" } }, - "node_modules/@vue/reactivity": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.36.tgz", - "integrity": "sha512-c2qvopo0crh9A4GXi2/2kfGYMxsJW4tVILrqRPydVGZHhq0fnzy6qmclWOhBFckEhmyxmpHpdJtIRYGeKcuhnA==", - "dependencies": { - "@vue/shared": "3.2.36" + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" } }, - "node_modules/@vue/reactivity-transform": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.36.tgz", - "integrity": "sha512-Jk5o2BhpODC9XTA7o4EL8hSJ4JyrFWErLtClG3NH8wDS7ri9jBDWxI7/549T7JY9uilKsaNM+4pJASLj5dtRwA==", + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.36", - "@vue/shared": "3.2.36", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7" + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/@vue/runtime-core": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.36.tgz", - "integrity": "sha512-PTWBD+Lub+1U3/KhbCExrfxyS14hstLX+cBboxVHaz+kXoiDLNDEYAovPtxeTutbqtClIXtft+wcGdC+FUQ9qQ==", + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dependencies": { - "@vue/reactivity": "3.2.36", - "@vue/shared": "3.2.36" + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "node_modules/@vue/runtime-dom": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.36.tgz", - "integrity": "sha512-gYPYblm7QXHVuBohqNRRT7Wez0f2Mx2D40rb4fleehrJU9CnkjG0phhcGEZFfGwCmHZRqBCRgbFWE98bPULqkg==", + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/node-releases": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", + "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "dependencies": { - "@vue/runtime-core": "3.2.36", - "@vue/shared": "3.2.36", - "csstype": "^2.6.8" + "wrappy": "1" } }, - "node_modules/@vue/server-renderer": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.36.tgz", - "integrity": "sha512-uZE0+jfye6yYXWvAQYeHZv+f50sRryvy16uiqzk3jn8hEY8zTjI+rzlmZSGoE915k+W/Ol9XSw6vxOUD8dGkUg==", + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, "dependencies": { - "@vue/compiler-ssr": "3.2.36", - "@vue/shared": "3.2.36" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" }, - "peerDependencies": { - "vue": "3.2.36" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/@vue/shared": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.36.tgz", - "integrity": "sha512-JtB41wXl7Au3+Nl3gD16Cfpj7k/6aCroZ6BbOiCMFCMvrOpkg/qQUXTso2XowaNqBbnkuGHurLAqkLBxNGc1hQ==" - }, - "node_modules/@vue/vue-loader-v15": { - "name": "vue-loader", - "version": "15.9.8", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.8.tgz", - "integrity": "sha512-GwSkxPrihfLR69/dSV3+5CdMQ0D+jXg8Ma1S4nQXKJAznYFX14vHdc/NetQc34Dw+rBbIJyP7JOuVb9Fhprvog==", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "dependencies": { - "@vue/component-compiler-utils": "^3.1.0", - "hash-sum": "^1.0.2", - "loader-utils": "^1.1.0", - "vue-hot-reload-api": "^2.3.0", - "vue-style-loader": "^4.1.0" - }, - "peerDependencies": { - "css-loader": "*", - "webpack": "^3.0.0 || ^4.1.0 || ^5.0.0-0" + "callsites": "^3.0.0" }, - "peerDependenciesMeta": { - "cache-loader": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - } + "engines": { + "node": ">=6" } }, - "node_modules/@vue/vue-loader-v15/node_modules/hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", - "dev": true + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/@vue/web-component-wrapper": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz", - "integrity": "sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "node_modules/@vueuse/core": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-5.3.0.tgz", - "integrity": "sha512-bBL1/JMRHFWmbgQzUZHF4WOwlqfenR1B8+elriXsbnHlogQM5foSz9++WyDBR0YPIVgCJq7fvNLqd4T7+cjc5w==", - "dependencies": { - "@vueuse/shared": "5.3.0", - "vue-demi": "*" + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" }, "funding": { - "url": "https://github.com/sponsors/antfu" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/@vueuse/core/node_modules/vue-demi": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.4.tgz", - "integrity": "sha512-ztPDkFt0TSUdoq1ZI6oD730vgztBkiByhUW7L1cOTebiSBqSYfSQgnhYakYigBkyAybqCTH7h44yZuDJf2xILQ==", - "hasInstallScript": true, - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" - }, - "engines": { - "node": ">=12" + "node_modules/pinia": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.14.tgz", + "integrity": "sha512-0nPuZR4TetT/WcLN+feMSjWJku3SQU7dBbXC6uw+R6FLQJCsg+/0pzXyD82T1FmAYe0lsx+jnEDQ1BLgkRKlxA==", + "dependencies": { + "@vue/devtools-api": "^6.1.4", + "vue-demi": "*" }, "funding": { - "url": "https://github.com/sponsors/antfu" + "url": "https://github.com/sponsors/posva" }, "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" + "@vue/composition-api": "^1.4.0", + "typescript": ">=4.4.4", + "vue": "^2.6.14 || ^3.2.0" }, "peerDependenciesMeta": { "@vue/composition-api": { "optional": true + }, + "typescript": { + "optional": true } } }, - "node_modules/@vueuse/integrations": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-5.3.0.tgz", - "integrity": "sha512-qZg0b656O5alOOfl9p4BucRumhzHoKmKWUxYjkCwWh+3nPSP5R1+r1wFi1lg6ELPoTCww0LXTlPCZAmz9dSLjA==", - "dependencies": { - "@vueuse/shared": "5.3.0", - "vue-demi": "*" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "optionalDependencies": { - "axios": "^0.21.1", - "focus-trap": "^6.6.0", - "jwt-decode": "^3.1.2", - "nprogress": "^0.2.0", - "qrcode": "^1.4.4", - "universal-cookie": "^4.0.4" - } - }, - "node_modules/@vueuse/integrations/node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "optional": true, - "dependencies": { - "follow-redirects": "^1.14.0" - } - }, - "node_modules/@vueuse/integrations/node_modules/vue-demi": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.4.tgz", - "integrity": "sha512-ztPDkFt0TSUdoq1ZI6oD730vgztBkiByhUW7L1cOTebiSBqSYfSQgnhYakYigBkyAybqCTH7h44yZuDJf2xILQ==", + "node_modules/pinia/node_modules/vue-demi": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.1.tgz", + "integrity": "sha512-xmkJ56koG3ptpLnpgmIzk9/4nFf4CqduSJbUM0OdPoU87NwRuZ6x49OLhjSa/fC15fV+5CbEnrxU4oyE022svg==", "hasInstallScript": true, "bin": { "vue-demi-fix": "bin/vue-demi-fix.js", @@ -3479,18474 +2952,3368 @@ } } }, - "node_modules/@vueuse/shared": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-5.3.0.tgz", - "integrity": "sha512-qZfkPFH0qTScFpYiPOFpTcxWriRhlM3bgSzl3DFTgr/U0eZg3w2EFWaRZHdWeSvAUdNQyjOC4Toa8S0zJyEjHw==", + "node_modules/postcss": { + "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], "dependencies": { - "vue-demi": "*" + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" }, - "funding": { - "url": "https://github.com/sponsors/antfu" + "engines": { + "node": "^10 || ^12 || >=14" } }, - "node_modules/@vueuse/shared/node_modules/vue-demi": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.4.tgz", - "integrity": "sha512-ztPDkFt0TSUdoq1ZI6oD730vgztBkiByhUW7L1cOTebiSBqSYfSQgnhYakYigBkyAybqCTH7h44yZuDJf2xILQ==", - "hasInstallScript": true, - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" + "node_modules/postcss-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", + "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" }, "engines": { - "node": ">=12" + "node": "^12 || ^14 || >= 16" }, "funding": { - "url": "https://github.com/sponsors/antfu" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" }, "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dev": true, + "dependencies": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" }, "peerDependenciesMeta": { - "@vue/composition-api": { + "postcss": { + "optional": true + }, + "ts-node": { "optional": true } } }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "node_modules/postcss-nested": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", + "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", "dev": true, "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + "postcss-selector-parser": "^6.0.6" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" } }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", "dev": true, "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" } }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "node_modules/prettier": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz", + "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==", "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, "dependencies": { - "@xtuc/long": "4.2.2" + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true + "node_modules/prismjs": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.28.0.tgz", + "integrity": "sha512-8aaXdYvl1F7iC7Xm1spqSaY/OJBpYW3v+KJ+F17iYxvdc8sfjW194COK5wVhMZX45tGteiBQgdvD/nhxcRwylw==", + "engines": { + "node": ">=6" + } }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" + "engines": { + "node": ">=6" } }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "safe-buffer": "^5.1.0" } }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" } }, - "node_modules/@webcomponents/webcomponentsjs": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@webcomponents/webcomponentsjs/-/webcomponentsjs-2.6.0.tgz", - "integrity": "sha512-Moog+Smx3ORTbWwuPqoclr+uvfLnciVd6wdCaVscHPrxbmQ/IJKm3wbB7hpzJtXWjAq2l/6QMlO85aZiOdtv5Q==" - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true, - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, "engines": { - "node": ">= 0.6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" } }, - "node_modules/acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "node_modules/resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", "dev": true, + "dependencies": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, "bin": { - "acorn": "bin/acorn" + "resolve": "bin/resolve" }, - "engines": { - "node": ">=0.4.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, - "peerDependencies": { - "acorn": "^8" + "engines": { + "node": ">=4" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "node_modules/acorn-node": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", - "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/acorn-node/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "node_modules/rollup": { + "version": "2.75.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.75.5.tgz", + "integrity": "sha512-JzNlJZDison3o2mOxVmb44Oz7t74EfSd1SQrplQk0wSaXV7uLQXtVdHbxlcT3w+8tZ1TL4r/eLfc7nAbz38BBA==", "dev": true, "bin": { - "acorn": "bin/acorn" + "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=0.4.0" + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/acorn-node/node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, - "engines": { - "node": ">=0.4.0" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" } }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, - "engines": { - "node": ">=0.4.0" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "optional": true, + "peer": true }, - "node_modules/address": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", - "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==", + "node_modules/sass": { + "version": "1.52.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.52.1.tgz", + "integrity": "sha512-fSzYTbr7z8oQnVJ3Acp9hV80dM1fkMN7mSD/25mpcct9F7FPBMOI8krEYALgU1aZoqGhQNhTPsuSmxjnIvAm4Q==", "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, "engines": { - "node": ">= 0.12.0" + "node": ">=12.0.0" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" }, "engines": { - "node": ">=8" + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "lru-cache": "^6.0.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } + "randombytes": "^2.1.0" } }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "shebang-regex": "^3.0.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">=8" } }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" + "engines": { + "node": ">=8" } }, - "node_modules/ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true, - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "devOptional": true, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", - "dev": true + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/arg": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", - "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==", - "dev": true - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", - "dev": true - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "lodash": "^4.17.14" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/at-least-node": { + "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, "engines": { - "node": ">= 4.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/autoprefixer": { - "version": "10.4.4", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.4.tgz", - "integrity": "sha512-Tm8JxsB286VweiZ5F0anmbyGiNI3v3wGv3mz9W+cxEDYB/6jbnj6GM9H9mK3wIL8ftgl+C07Lcwb8PG5PCCPzA==", + "node_modules/tailwindcss": { + "version": "3.0.24", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.24.tgz", + "integrity": "sha512-H3uMmZNWzG6aqmg9q07ZIRNIawoiEcNFKDfL+YzOPuPsXuDXxJxB9icqzLgdzKNwjG3SAro2h9SYav8ewXNgig==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - } - ], "dependencies": { - "browserslist": "^4.20.2", - "caniuse-lite": "^1.0.30001317", - "fraction.js": "^4.2.0", - "normalize-range": "^0.1.2", + "arg": "^5.0.1", + "chokidar": "^3.5.3", + "color-name": "^1.1.4", + "detective": "^5.2.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "lilconfig": "^2.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" + "postcss": "^8.4.12", + "postcss-js": "^4.0.0", + "postcss-load-config": "^3.1.4", + "postcss-nested": "5.0.6", + "postcss-selector-parser": "^6.0.10", + "postcss-value-parser": "^4.2.0", + "quick-lru": "^5.1.1", + "resolve": "^1.22.0" }, "bin": { - "autoprefixer": "bin/autoprefixer" + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": ">=12.13.0" }, "peerDependencies": { - "postcss": "^8.1.0" + "postcss": "^8.0.9" } }, - "node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", - "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">=6" } }, - "node_modules/babel-loader": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.4.tgz", - "integrity": "sha512-8dytA3gcvPPPv4Grjhnt8b5IIiTcq/zeXOPk4iTYI0SVXcsmuGg7JtBRDp8S9X+gJfhQ8ektjXZlDu1Bb33U8A==", + "node_modules/terser": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.0.tgz", + "integrity": "sha512-JC6qfIEkPBd9j1SMO3Pfn+A6w2kQV54tv+ABQLgZr7dA3k/DL/OBoYSWxzVpZev3J+bUHXfr55L8Mox7AaNo6g==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "find-cache-dir": "^3.3.1", - "loader-utils": "^2.0.0", - "make-dir": "^3.1.0", - "schema-utils": "^2.6.5" + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" }, - "engines": { - "node": ">= 8.9" + "bin": { + "terser": "bin/terser" }, - "peerDependencies": { - "@babel/core": "^7.0.0", - "webpack": ">=2" + "engines": { + "node": ">=10" } }, - "node_modules/babel-loader/node_modules/loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "node_modules/terser-webpack-plugin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz", + "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1", + "terser": "^5.7.2" }, "engines": { - "node": ">=8.9.0" + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } } }, - "node_modules/babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dev": true, - "dependencies": { - "object.assign": "^4.1.0" - } + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", - "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.3.1", - "semver": "^6.1.1" + "is-number": "^7.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=8.0" } }, - "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", - "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.1", - "core-js-compat": "^3.21.0" + "tslib": "^1.8.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", - "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.1" + "prelude-ls": "^1.2.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.2.tgz", + "integrity": "sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "node_modules/unplugin": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-0.6.3.tgz", + "integrity": "sha512-CoW88FQfCW/yabVc4bLrjikN9HC8dEvMU4O7B6K2jsYMPK0l6iAnd9dpJwqGcmXJKRCU9vwSsy653qg+RK0G6A==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" + "dependencies": { + "chokidar": "^3.5.3", + "webpack-sources": "^3.2.3", + "webpack-virtual-modules": "^0.4.3" + }, + "peerDependencies": { + "esbuild": ">=0.13", + "rollup": "^2.50.0", + "vite": "^2.3.0", + "webpack": "4 || 5" + }, + "peerDependenciesMeta": { + "esbuild": { + "optional": true }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "rollup": { + "optional": true }, - { - "type": "consulting", - "url": "https://feross.org/support" + "vite": { + "optional": true + }, + "webpack": { + "optional": true } - ] - }, - "node_modules/batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", - "dev": true - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "engines": { - "node": "*" } }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "node_modules/unplugin-vue-components": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-0.19.6.tgz", + "integrity": "sha512-APvrJ9Hpid1MLT0G4PWerMJgARhNw6dzz0pcCwCxaO2DR7VyvDacMqjOQNC6ukq7FSw3wzD8VH+9i3EFXwkGmw==", "dev": true, + "dependencies": { + "@antfu/utils": "^0.5.1", + "@rollup/pluginutils": "^4.2.1", + "chokidar": "^3.5.3", + "debug": "^4.3.4", + "fast-glob": "^3.2.11", + "local-pkg": "^0.4.1", + "magic-string": "^0.26.1", + "minimatch": "^5.0.1", + "resolve": "^1.22.0", + "unplugin": "^0.6.3" + }, "engines": { - "node": ">=8" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@babel/parser": "^7.15.8", + "@babel/traverse": "^7.15.4", + "vue": "2 || 3" + }, + "peerDependenciesMeta": { + "@babel/parser": { + "optional": true + }, + "@babel/traverse": { + "optional": true + } } }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "node_modules/unplugin-vue-components/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "balanced-match": "^1.0.0" } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", + "node_modules/unplugin-vue-components/node_modules/magic-string": { + "version": "0.26.2", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.2.tgz", + "integrity": "sha512-NzzlXpclt5zAbmo6h6jNc8zl2gNRGHvmsZW4IvZhTC4W7k4OlLP+S5YLussa/r3ixNT66KOQfNORlXHSOy/X4A==", "dev": true, "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.7", - "raw-body": "2.4.3", - "type-is": "~1.6.18" + "sourcemap-codec": "^1.4.8" }, "engines": { - "node": ">= 0.8" + "node": ">=12" } }, - "node_modules/body-parser/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "node_modules/unplugin-vue-components/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">= 0.8" + "node": ">=10" } }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "dependencies": { - "ms": "2.0.0" + "punycode": "^2.1.0" } }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "node_modules/body-scroll-lock": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/body-scroll-lock/-/body-scroll-lock-3.1.5.tgz", - "integrity": "sha512-Yi1Xaml0EvNA0OYWxXiYNqY24AfWkbA6w5vxE7GWxtKfzIbZM+Qw+aSmkgsbWzbHiy/RCSkUZBplVxTA+E4jJg==" + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true }, - "node_modules/bonjour": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", - "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "node_modules/vite": { + "version": "2.9.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.9.tgz", + "integrity": "sha512-ffaam+NgHfbEmfw/Vuh6BHKKlI/XIAhxE5QSS7gFLIngxg171mg1P3a4LSRME0z2ZU1ScxoKzphkipcYwSD5Ew==", "dev": true, "dependencies": { - "array-flatten": "^2.1.0", - "deep-equal": "^1.0.1", - "dns-equal": "^1.0.0", - "dns-txt": "^2.0.2", - "multicast-dns": "^6.0.1", - "multicast-dns-service-types": "^1.1.0" + "esbuild": "^0.14.27", + "postcss": "^8.4.13", + "resolve": "^1.22.0", + "rollup": "^2.59.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": ">=12.2.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "less": "*", + "sass": "*", + "stylus": "*" + }, + "peerDependenciesMeta": { + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + } } }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "node_modules/boxicons": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/boxicons/-/boxicons-2.1.2.tgz", - "integrity": "sha512-NAEj0xmE64Hv6q7yjvyEVsdA+XIESHLe/S/bkCd2A197LQNpZ5ftopxmD3DMatZ1lndGIzxxqqFnWrD1oB3IIg==", + "node_modules/vite-plugin-ejs": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/vite-plugin-ejs/-/vite-plugin-ejs-1.4.4.tgz", + "integrity": "sha512-R3Xt8bPlU/jrzia7iC4sA1bQTRM+JjMrVAk/CTRX8w1EHD8G6xVbSZ6XJbW6kj94M4jEyDu32BAq4JaGoOtnkw==", "dependencies": { - "@webcomponents/webcomponentsjs": "^2.0.2", - "prop-types": "^15.6.0", - "react": "^16.0.0", - "react-dom": "^16.0.0", - "react-interactive": "^0.8.1", - "react-router-dom": "^4.2.2" + "ejs": "^3.1.6" } }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/vue": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.36.tgz", + "integrity": "sha512-5yTXmrE6gW8IQgttzHW5bfBiFA6mx35ZXHjGLDmKYzW6MMmYvCwuKybANRepwkMYeXw2v1buGg3/lPICY5YlZw==", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@vue/compiler-dom": "3.2.36", + "@vue/compiler-sfc": "3.2.36", + "@vue/runtime-dom": "3.2.36", + "@vue/server-renderer": "3.2.36", + "@vue/shared": "3.2.36" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "node_modules/vue-class-component": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/vue-class-component/-/vue-class-component-8.0.0-rc.1.tgz", + "integrity": "sha512-w1nMzsT/UdbDAXKqhwTmSoyuJzUXKrxLE77PCFVuC6syr8acdFDAq116xgvZh9UCuV0h+rlCtxXolr3Hi3HyPQ==", + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/vue-eslint-parser": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz", + "integrity": "sha512-dzHGG3+sYwSf6zFBa0Gi9ZDshD7+ad14DGOdTLjruRVgZXe2J+DcZ9iUhyR48z5g1PqRa20yt3Njna/veLJL/g==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "debug": "^4.3.2", + "eslint-scope": "^7.0.0", + "eslint-visitor-keys": "^3.1.0", + "espree": "^9.0.0", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.5" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=6.0.0" } }, - "node_modules/browserslist": { - "version": "4.20.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz", - "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==", + "node_modules/vue-eslint-parser/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], "dependencies": { - "caniuse-lite": "^1.0.30001317", - "electron-to-chromium": "^1.4.84", - "escalade": "^3.1.1", - "node-releases": "^2.0.2", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist": "cli.js" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/buffer-indexof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", - "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", - "dev": true - }, - "node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "node_modules/vue-eslint-parser/node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", "dev": true, "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/vue-eslint-parser/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "engines": { - "node": ">=6" + "node": ">=4.0" } }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" + "node_modules/vue-final-modal": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/vue-final-modal/-/vue-final-modal-3.4.4.tgz", + "integrity": "sha512-4nOLU+cMcUqAT0kg+64+Hi96kkQPOph2LOJa7Fl58BXlTyhfRxaMuz3M91wi2ooMIL4poWA8428P5GIAXSpuZg==" + }, + "node_modules/vue-meta": { + "version": "3.0.0-alpha.10", + "resolved": "https://registry.npmjs.org/vue-meta/-/vue-meta-3.0.0-alpha.10.tgz", + "integrity": "sha512-rYeIGkhm1gKBcReEkPHiV6LV2Y6BZTMGTkGw1mQIZTxfFcVJL0srLZsL1zAmLeTGxMrlDYylMQEVSYRkDnwz3A==", + "peerDependencies": { + "vue": "^3.0.0" } }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, + "node_modules/vue-prism-editor": { + "version": "2.0.0-alpha.2", + "resolved": "https://registry.npmjs.org/vue-prism-editor/-/vue-prism-editor-2.0.0-alpha.2.tgz", + "integrity": "sha512-Gu42ba9nosrE+gJpnAEuEkDMqG9zSUysIR8SdXUw8MQKDjBnnNR9lHC18uOr/ICz7yrA/5c7jHJr9lpElODC7w==", "engines": { "node": ">=10" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, - "engines": { - "node": ">= 6" + "peerDependencies": { + "vue": "^3.0.0" } }, - "node_modules/caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dev": true, + "node_modules/vue-router": { + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.15.tgz", + "integrity": "sha512-xa+pIN9ZqORdIW1MkN2+d9Ui2pCM1b/UMgwYUCZOiFYHAvz/slKKBDha8DLrh5aCG/RibtrpyhKjKOZ85tYyWg==", "dependencies": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001320", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001320.tgz", - "integrity": "sha512-MWPzG54AGdo3nWx7zHZTefseM5Y1ccM7hlQKHRqJkPozUaw3hNbBTMmLn16GG2FUzjR13Cr3NPfhIieX5PzXDA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - } - ] - }, - "node_modules/case-sensitive-paths-webpack-plugin": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", - "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", - "dev": true, - "engines": { - "node": ">=4" + "@vue/devtools-api": "^6.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" } }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/vue-tsc": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-0.35.2.tgz", + "integrity": "sha512-aqY16VlODHzqtKGUkqdumNpH+s5ABCkufRyvMKQlL/mua+N2DfSVnHufzSNNUMr7vmOO0YsNg27jsspBMq4iGA==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "@volar/vue-typescript": "0.35.2" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/charcodes": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/charcodes/-/charcodes-0.2.0.tgz", - "integrity": "sha512-Y4kiDb+AM4Ecy58YkuZrrSRJBDQdQ2L+NyS1vHHFtNtUjgutcZfx3yp1dAONI/oPaPmyGfCLx5CxL+zauIMyKQ==", - "dev": true, - "engines": { - "node": ">=6" + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": "*" } }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "node_modules/watchpack": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", + "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "optional": true, + "peer": true, "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" }, "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "node": ">=10.13.0" } }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/webpack": { + "version": "5.72.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.1.tgz", + "integrity": "sha512-dXG5zXCLspQR4krZVR6QgajnZOjW2K/djHvdcRaDQvsjV9z9vaW6+ja5dZOYbqBBjF6kGXka/2ZyxNdc+8Jung==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "is-glob": "^4.0.1" + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.9.3", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.3.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" }, "engines": { - "node": ">= 6" + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } } }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", "dev": true, "engines": { - "node": ">=6.0" + "node": ">=10.13.0" } }, - "node_modules/ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "node_modules/webpack-virtual-modules": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.4.3.tgz", + "integrity": "sha512-5NUqC2JquIL2pBAAo/VfBP6KuGkHIZQXW/lNKupLPfhViwh8wNsu0BObtl09yuKZszeEUfbXz8xhrHvSG16Nqw==", "dev": true }, - "node_modules/classnames": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", - "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" - }, - "node_modules/clean-css": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz", - "integrity": "sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg==", + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "dependencies": { - "source-map": "~0.6.0" + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" }, "engines": { - "node": ">= 10.0" + "node": ">= 8" } }, - "node_modules/clean-css/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true, "engines": { - "node": ">=6" + "node": ">=0.4" } }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, - "node_modules/cli-highlight": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", - "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "highlight.js": "^10.7.1", - "mz": "^2.4.0", - "parse5": "^5.1.1", - "parse5-htmlparser2-tree-adapter": "^6.0.0", - "yargs": "^16.0.0" - }, - "bin": { - "highlight": "bin/highlight" - }, "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" + "node": ">= 6" } + } + }, + "dependencies": { + "@antfu/utils": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.5.2.tgz", + "integrity": "sha512-CQkeV+oJxUazwjlHD0/3ZD08QWKuGQkhnrKo3e6ly5pd48VUpXbb77q0xMU4+vc2CkJnDS02Eq/M9ugyX20XZA==", + "dev": true }, - "node_modules/cli-highlight/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } + "@babel/parser": { + "version": "7.18.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.4.tgz", + "integrity": "sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==" }, - "node_modules/cli-highlight/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "@eslint/eslintrc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", + "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.3.2", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" } }, - "node_modules/cli-highlight/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "@humanwhocodes/config-array": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", + "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" } }, - "node_modules/cli-highlight/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, - "node_modules/cli-highlight/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "@jridgewell/gen-mapping": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz", + "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==", "dev": true, - "engines": { - "node": ">=8" + "optional": true, + "peer": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" } }, - "node_modules/cli-highlight/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "@jridgewell/resolve-uri": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", + "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } + "optional": true, + "peer": true }, - "node_modules/cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "@jridgewell/set-array": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz", + "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==", "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "optional": true, + "peer": true }, - "node_modules/clipboardy": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz", - "integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==", + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", "dev": true, - "dependencies": { - "arch": "^2.1.1", - "execa": "^1.0.0", - "is-wsl": "^2.1.1" - }, - "engines": { - "node": ">=8" + "optional": true, + "peer": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" } }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "@jridgewell/sourcemap-codec": { + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", + "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } + "optional": true, + "peer": true }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "@jridgewell/trace-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz", + "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==", "dev": true, - "engines": { - "node": ">=0.8" + "optional": true, + "peer": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } + "@kyvg/vue3-notification": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@kyvg/vue3-notification/-/vue3-notification-2.3.4.tgz", + "integrity": "sha512-20Km1L75gncIZCjosT1OKbJl9HhNiOd7LRXqVIqlehHHem9NgBjQhDFz6XGo1RcF0MyA4/BC7kV7tcq/PMT+tA==", + "requires": {} }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, - "dependencies": { - "color-name": "1.1.3" + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" } }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/colord": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz", - "integrity": "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==", - "dev": true - }, - "node_modules/colorette": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", - "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" } }, - "node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", "dev": true, - "engines": { - "node": ">= 12" + "requires": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" } }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true + "@rushstack/eslint-patch": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.3.tgz", + "integrity": "sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw==" }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "@types/eslint": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.2.tgz", + "integrity": "sha512-Z1nseZON+GEnFjJc04sv4NSALGjhFwy6K0HXt7qsn5ArfAKtb63dXNJHf+1YW6IpOIYRBGUbu3GwJdj8DGnCjA==", "dev": true, - "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, - "engines": { - "node": ">= 0.6" + "optional": true, + "peer": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" } }, - "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "@types/eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", "dev": true, - "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" + "optional": true, + "peer": true, + "requires": { + "@types/eslint": "*", + "@types/estree": "*" } }, - "node_modules/compression/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", "dev": true, - "dependencies": { - "ms": "2.0.0" - } + "optional": true, + "peer": true }, - "node_modules/compression/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "dev": true }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "node_modules/connect-history-api-fallback": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "@types/node": { + "version": "17.0.38", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.38.tgz", + "integrity": "sha512-5jY9RhV7c0Z4Jy09G+NIDTsCZ5G0L5n+Z+p+Y7t5VJHM30bgwzSjVtlcBxqAj+6L/swIlvtOSzr8rBk/aNyV2g==", "dev": true, - "engines": { - "node": ">=0.8" - } + "optional": true, + "peer": true }, - "node_modules/consolidate": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz", - "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==", - "dev": true, - "dependencies": { - "bluebird": "^3.1.1" - }, - "engines": { - "node": ">= 0.10.0" - } + "@types/prismjs": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.0.tgz", + "integrity": "sha512-ZTaqn/qSqUuAq1YwvOFQfVW1AR/oQJlLSZVustdjwI+GZ8kr0MSHBj0tsXPW1EqHubx50gtBEjbPGsdZwQwCjQ==", + "dev": true + }, + "@types/webpack-env": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.17.0.tgz", + "integrity": "sha512-eHSaNYEyxRA5IAG0Ym/yCyf86niZUIF/TpWKofQI/CVfh5HsMEUyfE2kwFxha4ow0s5g0LfISQxpDKjbRDrizw==" }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "@typescript-eslint/eslint-plugin": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.27.0.tgz", + "integrity": "sha512-DDrIA7GXtmHXr1VCcx9HivA39eprYBIFxbQEHI6NyraRDxCGpxAFiYQAT/1Y0vh1C+o2vfBiy4IuPoXxtTZCAQ==", "dev": true, - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" + "requires": { + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/type-utils": "5.27.0", + "@typescript-eslint/utils": "5.27.0", + "debug": "^4.3.4", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.2.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" } }, - "node_modules/content-disposition/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "@typescript-eslint/parser": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.27.0.tgz", + "integrity": "sha512-8oGjQF46c52l7fMiPPvX4It3u3V3JipssqDfHQ2hcR0AeR8Zge+OYyKUCm5b70X72N1qXt0qgHenwN6Gc2SXZA==", "dev": true, - "engines": { - "node": ">= 0.6" + "requires": { + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/typescript-estree": "5.27.0", + "debug": "^4.3.4" } }, - "node_modules/convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "@typescript-eslint/scope-manager": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.27.0.tgz", + "integrity": "sha512-VnykheBQ/sHd1Vt0LJ1JLrMH1GzHO+SzX6VTXuStISIsvRiurue/eRkTqSrG0CexHQgKG8shyJfR4o5VYioB9g==", "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" + "requires": { + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/visitor-keys": "5.27.0" } }, - "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "devOptional": true, - "engines": { - "node": ">= 0.6" + "@typescript-eslint/type-utils": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.27.0.tgz", + "integrity": "sha512-vpTvRRchaf628Hb/Xzfek+85o//zEUotr1SmexKvTfs7czXfYjXVT/a5yDbpzLBX1rhbqxjDdr1Gyo0x1Fc64g==", + "dev": true, + "requires": { + "@typescript-eslint/utils": "5.27.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" } }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "@typescript-eslint/types": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.27.0.tgz", + "integrity": "sha512-lY6C7oGm9a/GWhmUDOs3xAVRz4ty/XKlQ2fOLr8GAIryGn0+UBOoJDWyHer3UgrHkenorwvBnphhP+zPmzmw0A==", "dev": true }, - "node_modules/copy-webpack-plugin": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-9.1.0.tgz", - "integrity": "sha512-rxnR7PaGigJzhqETHGmAcxKnLZSR5u1Y3/bcIv/1FnqXedcL/E2ewK7ZCNrArJKCiSv8yVXhTqetJh8inDvfsA==", + "@typescript-eslint/typescript-estree": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.27.0.tgz", + "integrity": "sha512-QywPMFvgZ+MHSLRofLI7BDL+UczFFHyj0vF5ibeChDAJgdTV8k4xgEwF0geFhVlPc1p8r70eYewzpo6ps+9LJQ==", "dev": true, - "dependencies": { - "fast-glob": "^3.2.7", - "glob-parent": "^6.0.1", - "globby": "^11.0.3", - "normalize-path": "^3.0.0", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" + "requires": { + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/visitor-keys": "5.27.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" } }, - "node_modules/copy-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "@typescript-eslint/utils": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.27.0.tgz", + "integrity": "sha512-nZvCrkIJppym7cIbP3pOwIkAefXOmfGPnCM0LQfzNaKxJHI6VjI8NC662uoiPlaf5f6ymkTy9C3NQXev2mdXmA==", "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/core-js": { - "version": "3.22.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.7.tgz", - "integrity": "sha512-Jt8SReuDKVNZnZEzyEQT5eK6T2RRCXkfTq7Lo09kpm+fHjgGewSbNjV+Wt4yZMhPDdzz2x1ulI5z/w4nxpBseg==", - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" + "requires": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/typescript-estree": "5.27.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" } }, - "node_modules/core-js-compat": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.21.1.tgz", - "integrity": "sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g==", + "@typescript-eslint/visitor-keys": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.27.0.tgz", + "integrity": "sha512-46cYrteA2MrIAjv9ai44OQDUoCZyHeGIc4lsjCUX2WT6r4C+kidz1bNiR4017wHOPUythYeH+Sc7/cFP97KEAA==", "dev": true, - "dependencies": { - "browserslist": "^4.19.1", - "semver": "7.0.0" + "requires": { + "@typescript-eslint/types": "5.27.0", + "eslint-visitor-keys": "^3.3.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" + "dependencies": { + "eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true + } } }, - "node_modules/core-js-compat/node_modules/semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "@vitejs/plugin-vue": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.3.3.tgz", + "integrity": "sha512-SmQLDyhz+6lGJhPELsBdzXGc+AcaT8stgkbiTFGpXPe8Tl1tJaBw1A6pxDqDuRsVkD8uscrkx3hA7QDOoKYtyw==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "requires": {} + }, + "@volar/code-gen": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@volar/code-gen/-/code-gen-0.35.2.tgz", + "integrity": "sha512-MoZHuNnPfUWnCNkQUI5+U+gvLTxrU+XlCTusdNOTFYUUAa+M68MH0RxFIS9Ybj4uAUWTcZx0Ow1q5t/PZozo+Q==", + "dev": true, + "requires": { + "@volar/source-map": "0.35.2" } }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "@volar/source-map": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-0.35.2.tgz", + "integrity": "sha512-PFHh9wN/qMkOWYyvmB8ckvIzolrpNOvK5EBdxxdTpiPJhfYjW82rMDBnYf6RxCe7yQxrUrmve6BWVO7flxWNVQ==", "dev": true }, - "node_modules/cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "@volar/vue-code-gen": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@volar/vue-code-gen/-/vue-code-gen-0.35.2.tgz", + "integrity": "sha512-8H6P8EtN06eSVGjtcJhGqZzFIg6/nWoHVOlnhc5vKqC7tXwpqPbyMQae0tO7pLBd5qSb/dYU5GQcBAHsi2jgyA==", "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - }, - "engines": { - "node": ">=8" + "requires": { + "@volar/code-gen": "0.35.2", + "@volar/source-map": "0.35.2", + "@vue/compiler-core": "^3.2.36", + "@vue/compiler-dom": "^3.2.36", + "@vue/shared": "^3.2.36" } }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "@volar/vue-typescript": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@volar/vue-typescript/-/vue-typescript-0.35.2.tgz", + "integrity": "sha512-PZI6Urb+Vr5Dvgf9xysM8X7TP09inWDy1wjDtprBoBhxS7r0Dg3V0qZuJa7sSGz7M0QMa5R/CBaZPhlxFCfJBw==", "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" + "requires": { + "@volar/code-gen": "0.35.2", + "@volar/source-map": "0.35.2", + "@volar/vue-code-gen": "0.35.2", + "@vue/compiler-sfc": "^3.2.36", + "@vue/reactivity": "^3.2.36" } }, - "node_modules/css-declaration-sorter": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.2.1.tgz", - "integrity": "sha512-4qvWVSwnc5f1ZxCe80LccU5aenhZdhuCCyaOSMhr3dDAOTXtJNfAvthW+5x0UV4k1pWzE1EwNk4ztSDCk6WzKw==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.0.9" + "@vue/compiler-core": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.36.tgz", + "integrity": "sha512-bbyZM5hvBicv0PW3KUfVi+x3ylHnfKG7DOn5wM+f2OztTzTjLEyBb/5yrarIYpmnGitVGbjZqDbODyW4iK8hqw==", + "requires": { + "@babel/parser": "^7.16.4", + "@vue/shared": "3.2.36", + "estree-walker": "^2.0.2", + "source-map": "^0.6.1" } }, - "node_modules/css-loader": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz", - "integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==", - "dev": true, - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.7", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.3.5" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" + "@vue/compiler-dom": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.36.tgz", + "integrity": "sha512-tcOTAOiW4s24QLnq+ON6J+GRONXJ+A/mqKCORi0LSlIh8XQlNnlm24y8xIL8la+ZDgkdbjarQ9ZqYSvEja6gVA==", + "requires": { + "@vue/compiler-core": "3.2.36", + "@vue/shared": "3.2.36" } }, - "node_modules/css-minimizer-webpack-plugin": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz", - "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==", - "dev": true, - "dependencies": { - "cssnano": "^5.0.6", - "jest-worker": "^27.0.2", - "postcss": "^8.3.5", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0", + "@vue/compiler-sfc": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.36.tgz", + "integrity": "sha512-AvGb4bTj4W8uQ4BqaSxo7UwTEqX5utdRSMyHy58OragWlt8nEACQ9mIeQh3K4di4/SX+41+pJrLIY01lHAOFOA==", + "requires": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.36", + "@vue/compiler-dom": "3.2.36", + "@vue/compiler-ssr": "3.2.36", + "@vue/reactivity-transform": "3.2.36", + "@vue/shared": "3.2.36", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7", + "postcss": "^8.1.10", "source-map": "^0.6.1" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@parcel/css": { - "optional": true - }, - "clean-css": { - "optional": true - }, - "csso": { - "optional": true - }, - "esbuild": { - "optional": true - } } }, - "node_modules/css-minimizer-webpack-plugin/node_modules/ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "@vue/compiler-ssr": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.36.tgz", + "integrity": "sha512-+KugInUFRvOxEdLkZwE+W43BqHyhBh0jpYXhmqw1xGq2dmE6J9eZ8UUSOKNhdHtQ/iNLWWeK/wPZkVLUf3YGaw==", + "requires": { + "@vue/compiler-dom": "3.2.36", + "@vue/shared": "3.2.36" } }, - "node_modules/css-minimizer-webpack-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "@vue/devtools-api": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.1.4.tgz", + "integrity": "sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ==" + }, + "@vue/eslint-config-prettier": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-7.0.0.tgz", + "integrity": "sha512-/CTc6ML3Wta1tCe1gUeO0EYnVXfo3nJXsIhZ8WJr3sov+cGASr6yuiibJTL6lmIBm7GobopToOuB3B6AWyV0Iw==", "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" + "requires": { + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-prettier": "^4.0.0" } }, - "node_modules/css-minimizer-webpack-plugin/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/css-minimizer-webpack-plugin/node_modules/schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "@vue/eslint-config-typescript": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-10.0.0.tgz", + "integrity": "sha512-F94cL8ug3FaYXlCfU5/wiGjk1qeadmoBpRGAOBq+qre3Smdupa59dd6ZJrsfRODpsMPyTG7330juMDsUvpZ3Rw==", "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "requires": { + "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/parser": "^5.0.0", + "vue-eslint-parser": "^8.0.0" } }, - "node_modules/css-minimizer-webpack-plugin/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/css-select": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz", - "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^5.1.0", - "domhandler": "^4.3.0", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dev": true, - "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/css-tree/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/css-what": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", - "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", - "dev": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cssnano": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.5.tgz", - "integrity": "sha512-VZO1e+bRRVixMeia1zKagrv0lLN1B/r/u12STGNNUFxnp97LIFgZHQa0JxqlwEkvzUyA9Oz/WnCTAFkdEbONmg==", - "dev": true, - "dependencies": { - "cssnano-preset-default": "^5.2.5", - "lilconfig": "^2.0.3", - "yaml": "^1.10.2" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/cssnano" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-preset-default": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.5.tgz", - "integrity": "sha512-WopL7PzN7sos3X8B54/QGl+CZUh1f0qN4ds+y2d5EPwRSSc3jsitVw81O+Uyop0pXyOfPfZxnc+LmA8w/Ki/WQ==", - "dev": true, - "dependencies": { - "css-declaration-sorter": "^6.0.3", - "cssnano-utils": "^3.1.0", - "postcss-calc": "^8.2.3", - "postcss-colormin": "^5.3.0", - "postcss-convert-values": "^5.1.0", - "postcss-discard-comments": "^5.1.1", - "postcss-discard-duplicates": "^5.1.0", - "postcss-discard-empty": "^5.1.1", - "postcss-discard-overridden": "^5.1.0", - "postcss-merge-longhand": "^5.1.3", - "postcss-merge-rules": "^5.1.1", - "postcss-minify-font-values": "^5.1.0", - "postcss-minify-gradients": "^5.1.1", - "postcss-minify-params": "^5.1.2", - "postcss-minify-selectors": "^5.2.0", - "postcss-normalize-charset": "^5.1.0", - "postcss-normalize-display-values": "^5.1.0", - "postcss-normalize-positions": "^5.1.0", - "postcss-normalize-repeat-style": "^5.1.0", - "postcss-normalize-string": "^5.1.0", - "postcss-normalize-timing-functions": "^5.1.0", - "postcss-normalize-unicode": "^5.1.0", - "postcss-normalize-url": "^5.1.0", - "postcss-normalize-whitespace": "^5.1.1", - "postcss-ordered-values": "^5.1.1", - "postcss-reduce-initial": "^5.1.0", - "postcss-reduce-transforms": "^5.1.0", - "postcss-svgo": "^5.1.0", - "postcss-unique-selectors": "^5.1.1" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", - "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "dev": true, - "dependencies": { - "css-tree": "^1.1.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/csstype": { - "version": "2.6.20", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", - "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==" - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/deep-equal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", - "dev": true, - "dependencies": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/default-gateway/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/default-gateway/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-gateway/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-gateway/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "dependencies": { - "clone": "^1.0.2" - } - }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true - }, - "node_modules/del": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", - "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", - "dev": true, - "dependencies": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "node_modules/detect-hover": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-hover/-/detect-hover-1.0.3.tgz", - "integrity": "sha512-HtLoY+tClgYucJNiovNICGWFp9nOGVmHY44s7L62iPqORXM9vujeWFaVcqtA7XRvp/2Y+4RBUfHbDKFGN+xxZQ==" - }, - "node_modules/detect-it": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/detect-it/-/detect-it-3.0.7.tgz", - "integrity": "sha512-RxpgcdbatUX6epJE09K16iJqF7x6iEcEdoL18FR2zpBO4JhnL7aMOAUoUEyexdtbWOSfTmoDWmeD6mwRBQyRXg==", - "dependencies": { - "detect-hover": "^1.0.3", - "detect-passive-events": "^1.0.5", - "detect-pointer": "^1.0.3", - "detect-touch-events": "^2.0.2" - } - }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true - }, - "node_modules/detect-passive-events": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/detect-passive-events/-/detect-passive-events-1.0.5.tgz", - "integrity": "sha512-foW7Q35wwOCxVzW0xLf5XeB5Fhe7oyRgvkBYdiP9IWgLMzjqUqTvsJv9ymuEWGjY6AoDXD3OC294+Z9iuOw0QA==" - }, - "node_modules/detect-pointer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-pointer/-/detect-pointer-1.0.3.tgz", - "integrity": "sha512-d0o/Puo3fiGSCXy6H039h9Kwz+mmYCGKZ/qtPFnpN3WfsumjC1C9b5KKvRu+aYnfdI8peqN/iAe7dPd85qIt2g==" - }, - "node_modules/detect-touch-events": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/detect-touch-events/-/detect-touch-events-2.0.2.tgz", - "integrity": "sha512-g8GWBkJLiIDRJfRXEdrd1wMXpNyGId2DkbfuwFahSb4OCvn717hyRJtAcEDISfp3zkwEhZ4Y4woHPA6DeyB3Fw==" - }, - "node_modules/detective": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", - "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", - "dev": true, - "dependencies": { - "acorn-node": "^1.6.1", - "defined": "^1.0.0", - "minimist": "^1.1.1" - }, - "bin": { - "detective": "bin/detective.js" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true - }, - "node_modules/dijkstrajs": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.2.tgz", - "integrity": "sha512-QV6PMaHTCNmKSeP6QoXhVTw9snc9VD8MulTT0Bd99Pacp4SS1cjcrYPgBPmibqKVtMJJfqC6XvOXgPMEEPH/fg==", - "optional": true - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true - }, - "node_modules/dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", - "dev": true - }, - "node_modules/dns-packet": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz", - "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==", - "dev": true, - "dependencies": { - "ip": "^1.1.0", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/dns-txt": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", - "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", - "dev": true, - "dependencies": { - "buffer-indexof": "^1.0.0" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dev": true, - "dependencies": { - "utila": "~0.4" - } - }, - "node_modules/dom-serializer": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", - "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", - "dev": true - }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "node_modules/easy-stack": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.1.tgz", - "integrity": "sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "node_modules/ejs": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.7.tgz", - "integrity": "sha512-BIar7R6abbUxDA3bfXrO4DSgwo8I+fB5/1zgujl3HLLjwd6+9iOnrT+t3grn2qbk9vOgBubXOFwX2m9axoFaGw==", - "dependencies": { - "jake": "^10.8.5" - }, - "bin": { - "ejs": "bin/cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.94", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.94.tgz", - "integrity": "sha512-CoOKsuACoa0PAG3hQXxbh/XDiFcjGuSyGKUi09cjMHOt6RCi7/EXgXhaFF3I+aC89Omudqmkzd0YOQKxwtf/Bg==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "devOptional": true - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/encode-utf8": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz", - "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==", - "optional": true - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz", - "integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/enhanced-resolve/node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/equal-vue": { - "version": "0.79.3", - "resolved": "https://registry.npmjs.org/equal-vue/-/equal-vue-0.79.3.tgz", - "integrity": "sha512-+/ZXStdr8tteQWxvmNuLc2PwbmHmWjLvW+fwHOLTErjYueexC3472hlEXPusU9H0z/MF6p6SEHdNo9uUdObokw==", - "dependencies": { - "@vueuse/core": "^5.0.3", - "@vueuse/integrations": "^5.0.3", - "body-scroll-lock": "^3.1.5", - "tinycolor2": "^1.4.2", - "vue": "^3.0.5" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/error-stack-parser": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.7.tgz", - "integrity": "sha512-chLOW0ZGRf4s8raLrDxa5sdkvPec5YdvwbFnqJme4rk0rFajP8mPtrDL1+I+CwrQDCjswDA5sREX7jYQDQs9vA==", - "dev": true, - "dependencies": { - "stackframe": "^1.1.1" - } - }, - "node_modules/es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true - }, - "node_modules/esbuild": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.28.tgz", - "integrity": "sha512-YLNprkCcMVKQ5sekmCKEQ3Obu/L7s6+iij38xNKyBeSmSsTWur4Ky/9zB3XIGT8SCJITG/bZwAR2l7YOAXch4Q==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "esbuild-android-64": "0.14.28", - "esbuild-android-arm64": "0.14.28", - "esbuild-darwin-64": "0.14.28", - "esbuild-darwin-arm64": "0.14.28", - "esbuild-freebsd-64": "0.14.28", - "esbuild-freebsd-arm64": "0.14.28", - "esbuild-linux-32": "0.14.28", - "esbuild-linux-64": "0.14.28", - "esbuild-linux-arm": "0.14.28", - "esbuild-linux-arm64": "0.14.28", - "esbuild-linux-mips64le": "0.14.28", - "esbuild-linux-ppc64le": "0.14.28", - "esbuild-linux-riscv64": "0.14.28", - "esbuild-linux-s390x": "0.14.28", - "esbuild-netbsd-64": "0.14.28", - "esbuild-openbsd-64": "0.14.28", - "esbuild-sunos-64": "0.14.28", - "esbuild-windows-32": "0.14.28", - "esbuild-windows-64": "0.14.28", - "esbuild-windows-arm64": "0.14.28" - } - }, - "node_modules/esbuild-android-64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.28.tgz", - "integrity": "sha512-A52C3zq+9tNwCqZ+4kVLBxnk/WnrYM8P2+QNvNE9B6d2OVPs214lp3g6UyO+dKDhUdefhfPCuwkP8j2A/+szNA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-android-arm64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.28.tgz", - "integrity": "sha512-sm0fDEGElZhMC3HLZeECI2juE4aG7uPfMBMqNUhy9CeX399Pz8rC6e78OXMXInGjSdEAwQmCOHmfsP7uv3Q8rA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-darwin-64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.28.tgz", - "integrity": "sha512-nzDd7mQ44FvsFHtOafZdBgn3Li5SMsnMnoz1J2MM37xJmR3wGNTFph88KypjHgWqwbxCI7MXS1U+sN4qDeeW6Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-darwin-arm64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.28.tgz", - "integrity": "sha512-XEq/bLR/glsUl+uGrBimQzOVs/CmwI833fXUhP9xrLI3IJ+rKyrZ5IA8u+1crOEf1LoTn8tV+hInmX6rGjbScw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.28.tgz", - "integrity": "sha512-rTKLgUj/HEcPeE5XZ7IZwWpFx7IWMfprN7QRk/TUJE1s1Ipb58esboIesUpjirJz/BwrgHq+FDG9ChAI8dZAtQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-arm64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.28.tgz", - "integrity": "sha512-sBffxD1UMOsB7aWMoExmipycjcy3HJGwmqE4GQZUTZvdiH4GhjgUiVdtPyt7kSCdL40JqnWQJ4b1l8Y51oCF4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-32": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.28.tgz", - "integrity": "sha512-+Wxidh3fBEQ9kHcCsD4etlBTMb1n6QY2uXv3rFhVn88CY/JP782MhA57/ipLMY4kOLeSKEuFGN4rtjHuhmRMig==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.28.tgz", - "integrity": "sha512-7+xgsC4LvR6cnzaBdiljNnPDjbkwzahogN+S9uy9AoYw7ZjPnnXc6sjQAVCbqGb7MEgrWdpa6u/Tao79i4lWxg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.28.tgz", - "integrity": "sha512-L5isjmlLbh9E0WVllXiVETbScgMbth/+XkXQii1WwgO1RvLIfaGrVFz8d2n6EH/ImtgYxPYGx+OcvIKQBc91Rg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.28.tgz", - "integrity": "sha512-EjRHgwg+kgXABzyoPGPOPg4d5wZqRnZ/ZAxBDzLY+i6DS8OUfTSlZHWIOZzU4XF7125WxRBg9ULbrFJBl+57Eg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-mips64le": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.28.tgz", - "integrity": "sha512-krx9SSg7yfiUKk64EmjefOyiEF6nv2bRE4um/LiTaQ6Y/6FP4UF3/Ou/AxZVyR154uSRq63xejcAsmswXAYRsw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-ppc64le": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.28.tgz", - "integrity": "sha512-LD0Xxu9g+DNuhsEBV5QuVZ4uKVBMup0xPIruLweuAf9/mHXFnaCuNXUBF5t0DxKl7GQ5MSioKtnb92oMo+QXEw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-riscv64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.28.tgz", - "integrity": "sha512-L/DWfRh2P0vxq4Y+qieSNXKGdMg+e9Qe8jkbN2/8XSGYDTPzO2OcAxSujob4qIh7iSl+cknbXV+BvH0YFR0jbg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-s390x": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.28.tgz", - "integrity": "sha512-rrgxmsbmL8QQknWGnAL9bGJRQYLOi2AzXy5OTwfhxnj9eqjo5mSVbJXjgiq5LPUAMQZGdPH5yaNK0obAXS81Zw==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-netbsd-64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.28.tgz", - "integrity": "sha512-h8wntIyOR8/xMVVM6TvJxxWKh4AjmLK87IPKpuVi8Pq0kyk0RMA+eo4PFGk5j2XK0D7dj8PcSF5NSlP9kN/j0A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-openbsd-64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.28.tgz", - "integrity": "sha512-HBv18rVapbuDx52/fhZ/c/w6TXyaQAvRxiDDn5Hz/pBcwOs3cdd2WxeIKlWmDoqm2JMx5EVlq4IWgoaRX9mVkw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-sunos-64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.28.tgz", - "integrity": "sha512-zlIxePhZxKYheR2vBCgPVvTixgo/ozOfOMoP6RZj8dxzquU1NgeyhjkcRXucbLCtmoNJ+i4PtWwPZTLuDd3bGg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-32": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.28.tgz", - "integrity": "sha512-am9DIJxXlld1BOAY/VlvBQHMUCPL7S3gB/lnXIY3M4ys0gfuRqPf4EvMwZMzYUbFKBY+/Qb8SRgPRRGhwnJ8Kg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.28.tgz", - "integrity": "sha512-78PhySDnmRZlsPNp/W/5Fim8iivlBQQxfhBFIqR7xwvfDmCFUSByyMKP7LCHgNtb04yNdop8nJJkJaQ8Xnwgiw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-arm64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.28.tgz", - "integrity": "sha512-VhXGBTo6HELD8zyHXynV6+L2jWx0zkKnGx4TmEdSBK7UVFACtOyfUqpToG0EtnYyRZ0HESBhzPSVpP781ovmvA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/eslint": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.16.0.tgz", - "integrity": "sha512-MBndsoXY/PeVTDJeWsYj7kLZ5hQpJOfMYLsF6LicLHQWbRDG19lK5jOix4DPl8yY4SUFcE3txy86OzFLWT+yoA==", - "dev": true, - "dependencies": { - "@eslint/eslintrc": "^1.3.0", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.2", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-prettier": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", - "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-prettier": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", - "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", - "dev": true, - "dependencies": { - "prettier-linter-helpers": "^1.0.0" - }, - "engines": { - "node": ">=6.0.0" - }, - "peerDependencies": { - "eslint": ">=7.28.0", - "prettier": ">=2.0.0" - }, - "peerDependenciesMeta": { - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-vue": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.0.1.tgz", - "integrity": "sha512-/w/9/vzz+4bSYtp5UqXgJ0CfycXTMtpp6lkz7/fMp0CcJxPWyRP6Pr88ihhrsNEcVt2ZweMupWRNYa+5Md41LQ==", - "dev": true, - "dependencies": { - "eslint-utils": "^3.0.0", - "natural-compare": "^1.4.0", - "nth-check": "^2.0.1", - "postcss-selector-parser": "^6.0.9", - "semver": "^7.3.5", - "vue-eslint-parser": "^9.0.1", - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": "^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/eslint-plugin-vue/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint-plugin-vue/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint-plugin-vue/node_modules/vue-eslint-parser": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.0.2.tgz", - "integrity": "sha512-uCPQwTGjOtAYrwnU+76pYxalhjsh7iFBsHwBqDHiOPTxtICDaraO4Szw54WFTNZTAEsgHHzqFOu1mmnBOBRzDA==", - "dev": true, - "dependencies": { - "debug": "^4.3.4", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", - "esquery": "^1.4.0", - "lodash": "^4.17.21", - "semver": "^7.3.6" - }, - "engines": { - "node": "^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=6.0.0" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint-webpack-plugin": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.1.1.tgz", - "integrity": "sha512-xSucskTN9tOkfW7so4EaiFIkulWLXwCB/15H917lR6pTv0Zot6/fetFucmENRb7J5whVSFKIvwnrnsa78SG2yg==", - "dev": true, - "dependencies": { - "@types/eslint": "^7.28.2", - "jest-worker": "^27.3.1", - "micromatch": "^4.0.4", - "normalize-path": "^3.0.0", - "schema-utils": "^3.1.1" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0", - "webpack": "^5.0.0" - } - }, - "node_modules/eslint-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", - "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", - "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", - "dev": true, - "dependencies": { - "acorn": "^8.7.1", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/event-pubsub": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz", - "integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/execa/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/execa/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/execa/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/execa/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/exifr": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/exifr/-/exifr-7.1.3.tgz", - "integrity": "sha512-g/aje2noHivrRSLbAUtBPWFbxKdKhgj/xr1vATDdUXPOFYJlQ62Ft0oy+72V6XLIpDJfHs6gXLbBLAolqOXYRw==" - }, - "node_modules/express": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", - "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", - "dev": true, - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.19.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.4.2", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.9.7", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.17.2", - "serve-static": "1.14.2", - "setprototypeof": "1.2.0", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true - }, - "node_modules/express/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/fast-xml-parser": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.0.8.tgz", - "integrity": "sha512-N4XqZaRMuHMvOFwFlqeBTlvrnXU+QN8wvCl2g9fHzMx2BnLoIYRDwy6XwI8FxogHMFI9OfGQBCddgckvSLTnvg==", - "dependencies": { - "strnum": "^1.0.5" - }, - "bin": { - "fxparser": "src/cli/cli.js" - }, - "funding": { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" - } - }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/filelist": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.3.tgz", - "integrity": "sha512-LwjCsruLWQULGYKy7TX0OPtrL9kLpojOFKc5VCTxdFTV7w5zbsgqVKfnkKG7Qgjtq50gKfO56hJv88OfcGb70Q==", - "dependencies": { - "minimatch": "^5.0.1" - } - }, - "node_modules/filelist/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/filelist/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "devOptional": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", - "dev": true - }, - "node_modules/focus-trap": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-6.7.3.tgz", - "integrity": "sha512-8xCEKndV4KrseGhFKKKmczVA14yx1/hnmFICPOjcFjToxCJYj/NHH43tPc3YE/PLnLRNZoFug0EcWkGQde/miQ==", - "optional": true, - "dependencies": { - "tabbable": "^5.2.1" - } - }, - "node_modules/follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/fork-ts-checker-webpack-plugin": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz", - "integrity": "sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.8.3", - "@types/json-schema": "^7.0.5", - "chalk": "^4.1.0", - "chokidar": "^3.4.2", - "cosmiconfig": "^6.0.0", - "deepmerge": "^4.2.2", - "fs-extra": "^9.0.0", - "glob": "^7.1.6", - "memfs": "^3.1.2", - "minimatch": "^3.0.4", - "schema-utils": "2.7.0", - "semver": "^7.3.2", - "tapable": "^1.0.0" - }, - "engines": { - "node": ">=10", - "yarn": ">=1.0.0" - }, - "peerDependencies": { - "eslint": ">= 6", - "typescript": ">= 2.7", - "vue-template-compiler": "*", - "webpack": ">= 4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - } - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fraction.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", - "dev": true, - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://www.patreon.com/infusion" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fs-monkey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", - "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "devOptional": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", - "dev": true - }, - "node_modules/gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "dev": true, - "dependencies": { - "duplexer": "^0.1.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hash-sum": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz", - "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==", - "dev": true - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/history": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", - "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", - "dependencies": { - "@babel/runtime": "^7.1.2", - "loose-envify": "^1.2.0", - "resolve-pathname": "^3.0.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0", - "value-equal": "^1.0.1" - } - }, - "node_modules/hoist-non-react-statics": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz", - "integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==" - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "node_modules/hpack.js/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/hpack.js/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/hpack.js/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/html-entities": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", - "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", - "dev": true - }, - "node_modules/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "dev": true, - "dependencies": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - }, - "bin": { - "html-minifier-terser": "cli.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/html-tags": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", - "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/html-webpack-plugin": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", - "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", - "dev": true, - "dependencies": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/html-webpack-plugin" - }, - "peerDependencies": { - "webpack": "^5.20.0" - } - }, - "node_modules/html-webpack-plugin/node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", - "dev": true - }, - "node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-parser-js": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz", - "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==", - "dev": true - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-proxy-middleware": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.4.tgz", - "integrity": "sha512-m/4FxX17SUvz4lJ5WPXOHDUuCwIqXLfLHs1s0uZ3oYjhoXlx9csYxaOa0ElDEJ+h8Q4iJ1s+lTMbiCa4EXIJqg==", - "dev": true, - "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/immutable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz", - "integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==", - "dev": true - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dependencies": { - "loose-envify": "^1.0.0" - } - }, - "node_modules/ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, - "node_modules/ipaddr.js": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", - "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-ci": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", - "dev": true, - "dependencies": { - "ci-info": "^1.5.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/is-core-module": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", - "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-file-esm": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-file-esm/-/is-file-esm-1.0.0.tgz", - "integrity": "sha512-rZlaNKb4Mr8WlRu2A9XdeoKgnO5aA53XdPHgCKVyCrQ/rWi89RET1+bq37Ru46obaQXeiX4vmFIm1vks41hoSA==", - "dev": true, - "dependencies": { - "read-pkg-up": "^7.0.1" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "devOptional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shallow-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shallow-equal/-/is-shallow-equal-1.0.1.tgz", - "integrity": "sha512-lq5RvK+85Hs5J3p4oA4256M1FEffzmI533ikeDHvJd42nouRRx5wBzt36JuviiGe5dIPyHON/d0/Up+PBo6XkQ==" - }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jake": { - "version": "10.8.5", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", - "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", - "dependencies": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.1", - "minimatch": "^3.0.4" - }, - "bin": { - "jake": "bin/cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jake/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jake/node_modules/async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" - }, - "node_modules/jake/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jake/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jake/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/jake/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/jake/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/javascript-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz", - "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==", - "dev": true - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/jest-worker/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/joi": { - "version": "17.6.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.6.0.tgz", - "integrity": "sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw==", - "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", - "@sideway/formula": "^3.0.0", - "@sideway/pinpoint": "^2.0.0" - } - }, - "node_modules/js-message": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz", - "integrity": "sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==", - "dev": true, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jwt-decode": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", - "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==", - "optional": true - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/klona": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", - "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/launch-editor": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.3.0.tgz", - "integrity": "sha512-3QrsCXejlWYHjBPFXTyGNhPj4rrQdB+5+r5r3wArpLH201aR+nWUgw/zKKkTmilCfY/sv6u8qo98pNvtg8LUTA==", - "dev": true, - "dependencies": { - "picocolors": "^1.0.0", - "shell-quote": "^1.6.1" - } - }, - "node_modules/launch-editor-middleware": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/launch-editor-middleware/-/launch-editor-middleware-2.3.0.tgz", - "integrity": "sha512-GJR64trLdFFwCoL9DMn/d1SZX0OzTDPixu4mcfWTShQ4tIqCHCGvlg9fOEYQXyBlrSMQwylsJfUWncheShfV2w==", - "dev": true, - "dependencies": { - "launch-editor": "^2.3.0" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lilconfig": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz", - "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", - "dev": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/loader-utils/node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/local-pkg": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.1.tgz", - "integrity": "sha512-lL87ytIGP2FU5PWwNDo0w3WhIo2gopIAxPg9RxDYF7m4rr5ahuZxP22xnJHIvaLTe4Z9P6uKKY2UHiwyB4pcrw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "devOptional": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" - }, - "node_modules/lodash.defaultsdeep": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz", - "integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==", - "dev": true - }, - "node_modules/lodash.kebabcase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", - "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=", - "dev": true - }, - "node_modules/lodash.mapvalues": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", - "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", - "dev": true - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.throttle": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", - "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=" - }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", - "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", - "dev": true, - "dependencies": { - "ansi-escapes": "^3.0.0", - "cli-cursor": "^2.0.0", - "wrap-ansi": "^3.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "dependencies": { - "restore-cursor": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "dependencies": { - "mimic-fn": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "dependencies": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", - "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", - "dev": true, - "dependencies": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dependencies": { - "sourcemap-codec": "^1.4.8" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memfs": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz", - "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==", - "dev": true, - "dependencies": { - "fs-monkey": "1.0.3" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/memoize-one": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", - "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "node_modules/merge-source-map": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", - "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", - "dev": true, - "dependencies": { - "source-map": "^0.6.1" - } - }, - "node_modules/merge-source-map/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mime-match/-/mime-match-1.0.2.tgz", - "integrity": "sha1-P4fDHprxpf1IX7nbE0Qosju7e6g=", - "peer": true, - "dependencies": { - "wildcard": "^1.1.0" - } - }, - "node_modules/mime-match/node_modules/wildcard": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz", - "integrity": "sha1-pwIEUwhNjNLv5wup02liY94XEKU=", - "peer": true - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/mini-css-extract-plugin": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.0.tgz", - "integrity": "sha512-ndG8nxCEnAemsg4FSgS+yNyHKgkTB4nPKqCOgh65j3/30qqC5RaSQQXMm++Y6sb6E1zRSxPkztj9fqxhS1Eo6w==", - "dev": true, - "dependencies": { - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/mini-css-extract-plugin/node_modules/ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/mini-css-extract-plugin/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, - "node_modules/minipass": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", - "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/module-alias": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.2.2.tgz", - "integrity": "sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q==", - "dev": true - }, - "node_modules/mrmime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz", - "integrity": "sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/multicast-dns": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", - "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", - "dev": true, - "dependencies": { - "dns-packet": "^1.3.1", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" - } - }, - "node_modules/multicast-dns-service-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", - "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", - "dev": true - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/namespace-emitter": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/namespace-emitter/-/namespace-emitter-2.0.1.tgz", - "integrity": "sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==", - "peer": true - }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-forge": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.0.tgz", - "integrity": "sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA==", - "dev": true, - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/node-releases": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", - "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", - "dev": true - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/nprogress": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", - "integrity": "sha1-y480xTIT2JVyP8urkH6UIq28r7E=", - "optional": true - }, - "node_modules/nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", - "dev": true, - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "dev": true, - "bin": { - "opener": "bin/opener-bin.js" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ora/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ora/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/ora/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/ora/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ora/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "devOptional": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "devOptional": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-retry": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz", - "integrity": "sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==", - "dev": true, - "dependencies": { - "@types/retry": "^0.12.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "devOptional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse5": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", - "dev": true - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "dependencies": { - "parse5": "^6.0.1" - } - }, - "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "devOptional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pinia": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.14.tgz", - "integrity": "sha512-0nPuZR4TetT/WcLN+feMSjWJku3SQU7dBbXC6uw+R6FLQJCsg+/0pzXyD82T1FmAYe0lsx+jnEDQ1BLgkRKlxA==", - "dependencies": { - "@vue/devtools-api": "^6.1.4", - "vue-demi": "*" - }, - "funding": { - "url": "https://github.com/sponsors/posva" - }, - "peerDependencies": { - "@vue/composition-api": "^1.4.0", - "typescript": ">=4.4.4", - "vue": "^2.6.14 || ^3.2.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "node_modules/pinia/node_modules/vue-demi": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.5.tgz", - "integrity": "sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==", - "hasInstallScript": true, - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pngjs": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", - "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", - "optional": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/portfinder": { - "version": "1.0.28", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", - "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", - "dev": true, - "dependencies": { - "async": "^2.6.2", - "debug": "^3.1.1", - "mkdirp": "^0.5.5" - }, - "engines": { - "node": ">= 0.12.0" - } - }, - "node_modules/portfinder/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/postcss": { - "version": "8.4.13", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.13.tgz", - "integrity": "sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], - "dependencies": { - "nanoid": "^3.3.3", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-calc": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", - "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.9", - "postcss-value-parser": "^4.2.0" - }, - "peerDependencies": { - "postcss": "^8.2.2" - } - }, - "node_modules/postcss-colormin": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.0.tgz", - "integrity": "sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg==", - "dev": true, - "dependencies": { - "browserslist": "^4.16.6", - "caniuse-api": "^3.0.0", - "colord": "^2.9.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-convert-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.0.tgz", - "integrity": "sha512-GkyPbZEYJiWtQB0KZ0X6qusqFHUepguBCNFi9t5JJc7I2OTXG7C0twbTLvCfaKOLl3rSXmpAwV7W5txd91V84g==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-comments": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.1.tgz", - "integrity": "sha512-5JscyFmvkUxz/5/+TB3QTTT9Gi9jHkcn8dcmmuN68JQcv3aQg4y88yEHHhwFB52l/NkaJ43O0dbksGMAo49nfQ==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-duplicates": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", - "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-empty": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", - "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-overridden": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", - "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-js": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", - "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", - "dev": true, - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.3.3" - } - }, - "node_modules/postcss-load-config": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", - "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", - "dev": true, - "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" - }, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/postcss-loader": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", - "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", - "dev": true, - "dependencies": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.5" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" - } - }, - "node_modules/postcss-loader/node_modules/cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/postcss-merge-longhand": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.3.tgz", - "integrity": "sha512-lX8GPGvZ0iGP/IboM7HXH5JwkXvXod1Rr8H8ixwiA372hArk0zP4ZcCy4z4Prg/bfNlbbTf0KCOjCF9kKnpP/w==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^5.1.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-merge-rules": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.1.tgz", - "integrity": "sha512-8wv8q2cXjEuCcgpIB1Xx1pIy8/rhMPIQqYKNzEdyx37m6gpq83mQQdCxgIkFgliyEnKvdwJf/C61vN4tQDq4Ww==", - "dev": true, - "dependencies": { - "browserslist": "^4.16.6", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^3.1.0", - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-font-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", - "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-gradients": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", - "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", - "dev": true, - "dependencies": { - "colord": "^2.9.1", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-params": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.2.tgz", - "integrity": "sha512-aEP+p71S/urY48HWaRHasyx4WHQJyOYaKpQ6eXl8k0kxg66Wt/30VR6/woh8THgcpRbonJD5IeD+CzNhPi1L8g==", - "dev": true, - "dependencies": { - "browserslist": "^4.16.6", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-selectors": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.0.tgz", - "integrity": "sha512-vYxvHkW+iULstA+ctVNx0VoRAR4THQQRkG77o0oa4/mBS0OzGvvzLIvHDv/nNEM0crzN2WIyFU5X7wZhaUK3RA==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", - "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-nested": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", - "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.6" - }, - "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-normalize-charset": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", - "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-display-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", - "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-positions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.0.tgz", - "integrity": "sha512-8gmItgA4H5xiUxgN/3TVvXRoJxkAWLW6f/KKhdsH03atg0cB8ilXnrB5PpSshwVu/dD2ZsRFQcR1OEmSBDAgcQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-repeat-style": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.0.tgz", - "integrity": "sha512-IR3uBjc+7mcWGL6CtniKNQ4Rr5fTxwkaDHwMBDGGs1x9IVRkYIT/M4NelZWkAOBdV6v3Z9S46zqaKGlyzHSchw==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-string": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", - "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-timing-functions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", - "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-unicode": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.0.tgz", - "integrity": "sha512-J6M3MizAAZ2dOdSjy2caayJLQT8E8K9XjLce8AUQMwOrCvjCHv24aLC/Lps1R1ylOfol5VIDMaM/Lo9NGlk1SQ==", - "dev": true, - "dependencies": { - "browserslist": "^4.16.6", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", - "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", - "dev": true, - "dependencies": { - "normalize-url": "^6.0.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-whitespace": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", - "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-ordered-values": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.1.tgz", - "integrity": "sha512-7lxgXF0NaoMIgyihL/2boNAEZKiW0+HkMhdKMTD93CjW8TdCy2hSdj8lsAo+uwm7EDG16Da2Jdmtqpedl0cMfw==", - "dev": true, - "dependencies": { - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-reduce-initial": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.0.tgz", - "integrity": "sha512-5OgTUviz0aeH6MtBjHfbr57tml13PuedK/Ecg8szzd4XRMbYxH4572JFG067z+FqBIf6Zp/d+0581glkvvWMFw==", - "dev": true, - "dependencies": { - "browserslist": "^4.16.6", - "caniuse-api": "^3.0.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-reduce-transforms": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", - "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-svgo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", - "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0", - "svgo": "^2.7.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-unique-selectors": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", - "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/preact": { - "version": "10.7.1", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.7.1.tgz", - "integrity": "sha512-MufnRFz39aIhs9AMFisonjzTud1PK1bY+jcJLo6m2T9Uh8AqjD77w11eAAawmjUogoGOnipECq7e/1RClIKsxg==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/preact" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz", - "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/pretty-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", - "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", - "dev": true, - "dependencies": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" - } - }, - "node_modules/prismjs": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.28.0.tgz", - "integrity": "sha512-8aaXdYvl1F7iC7Xm1spqSaY/OJBpYW3v+KJ+F17iYxvdc8sfjW194COK5wVhMZX45tGteiBQgdvD/nhxcRwylw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/progress-webpack-plugin": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/progress-webpack-plugin/-/progress-webpack-plugin-1.0.12.tgz", - "integrity": "sha512-b0dMK6D7pFicDzSdh+sU0p/gp3n5QAGwjPbgacmYB/eVQpayzf9lKTQLYMnTAbk69fKoXSoVNl/+IkobJblL1A==", - "dev": true, - "dependencies": { - "chalk": "^2.1.0", - "figures": "^2.0.0", - "log-update": "^2.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "peerDependencies": { - "webpack": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qrcode": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.0.tgz", - "integrity": "sha512-9MgRpgVc+/+47dFvQeD6U2s0Z92EsKzcHogtum4QB+UNd025WOJSHvn/hjk9xmzj7Stj95CyUAs31mrjxliEsQ==", - "optional": true, - "dependencies": { - "dijkstrajs": "^1.0.1", - "encode-utf8": "^1.0.3", - "pngjs": "^5.0.0", - "yargs": "^15.3.1" - }, - "bin": { - "qrcode": "bin/qrcode" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/qrcode/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "optional": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/qrcode/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qrcode/node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "optional": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/qrcode/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "optional": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/qrcode/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "optional": true - }, - "node_modules/qrcode/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "optional": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/qrcode/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "optional": true - }, - "node_modules/qrcode/node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "optional": true, - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/qrcode/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "optional": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", - "dev": true, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/react": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", - "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - }, - "peerDependencies": { - "react": "^16.14.0" - } - }, - "node_modules/react-interactive": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/react-interactive/-/react-interactive-0.8.3.tgz", - "integrity": "sha512-mmRvA9aKP7zu9kVfP1AX1egX8tFlnE3DDXq92z0JTZezfOpmeQBzr77O1+mTV54OOmn+M2t6c5kFD5VnuFoM7A==", - "dependencies": { - "detect-it": "^3.0.3", - "object-assign": "^4.1.1", - "prop-types": "^15.6.0" - }, - "peerDependencies": { - "react": ">=15" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/react-router": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz", - "integrity": "sha512-yrvL8AogDh2X42Dt9iknk4wF4V8bWREPirFfS9gLU1huk6qK41sg7Z/1S81jjTrGHxa3B8R3J6xIkDAA6CVarg==", - "dependencies": { - "history": "^4.7.2", - "hoist-non-react-statics": "^2.5.0", - "invariant": "^2.2.4", - "loose-envify": "^1.3.1", - "path-to-regexp": "^1.7.0", - "prop-types": "^15.6.1", - "warning": "^4.0.1" - }, - "peerDependencies": { - "react": ">=15" - } - }, - "node_modules/react-router-dom": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-4.3.1.tgz", - "integrity": "sha512-c/MlywfxDdCp7EnB7YfPMOfMD3tOtIjrQlj/CKfNMBxdmpJP8xcz5P/UAFn3JbnQCNUxsHyVVqllF9LhgVyFCA==", - "dependencies": { - "history": "^4.7.2", - "invariant": "^2.2.4", - "loose-envify": "^1.3.1", - "prop-types": "^15.6.1", - "react-router": "^4.3.1", - "warning": "^4.0.1" - }, - "peerDependencies": { - "react": ">=15" - } - }, - "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", - "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", - "dev": true, - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" - }, - "node_modules/regenerator-transform": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", - "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz", - "integrity": "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/regexpu-core": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz", - "integrity": "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==", - "dev": true, - "dependencies": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.0.1", - "regjsgen": "^0.6.0", - "regjsparser": "^0.8.2", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsgen": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", - "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==", - "dev": true - }, - "node_modules/regjsparser": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", - "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", - "dev": true, - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - } - }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/renderkid": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", - "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", - "dev": true, - "dependencies": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "devOptional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "optional": true - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "node_modules/resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.8.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-pathname": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", - "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rollup": { - "version": "2.70.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.70.1.tgz", - "integrity": "sha512-CRYsI5EuzLbXdxC6RnYhOuRdtz4bhejPMSWjsFLfVM/7w/85n2szZv6yExqUXsBdz5KT8eoubeyDUDjhLHEslA==", - "dev": true, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=10.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/sass": { - "version": "1.52.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.52.1.tgz", - "integrity": "sha512-fSzYTbr7z8oQnVJ3Acp9hV80dM1fkMN7mSD/25mpcct9F7FPBMOI8krEYALgU1aZoqGhQNhTPsuSmxjnIvAm4Q==", - "dev": true, - "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, - "node_modules/schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", - "dev": true - }, - "node_modules/selfsigned": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.1.tgz", - "integrity": "sha512-LmME957M1zOsUhG+67rAjKfiWFox3SBxE/yymatMZsAx+oMrJ0YQ8AToOnyCm7xbeg2ep37IHLxdu0o2MavQOQ==", - "dev": true, - "dependencies": { - "node-forge": "^1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", - "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "1.8.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", - "dev": true, - "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "node_modules/serve-index/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "node_modules/serve-static": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", - "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", - "dev": true, - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "optional": true - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shallow-equal": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz", - "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/shell-quote": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", - "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", - "dev": true - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/sirv": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.19.tgz", - "integrity": "sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==", - "dev": true, - "dependencies": { - "@polka/url": "^1.0.0-next.20", - "mrmime": "^1.0.0", - "totalist": "^1.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, - "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" - }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", - "dev": true - }, - "node_modules/spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "node_modules/ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "dev": true - }, - "node_modules/stackframe": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.1.tgz", - "integrity": "sha512-h88QkzREN/hy8eRdyNhhsO7RSJ5oyTqxxmmn0dzBIMUclZsjpfmrsg81vp8mjjAs2vAZ72nyWxRUwSwmh0e4xg==", - "dev": true - }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "devOptional": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "devOptional": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", - "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strnum": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", - "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" - }, - "node_modules/stylehacks": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.0.tgz", - "integrity": "sha512-SzLmvHQTrIWfSgljkQCw2++C9+Ne91d/6Sp92I8c5uHTcy/PgeHamwITIbBW9wnFTY/3ZfSXR9HIL6Ikqmcu6Q==", - "dev": true, - "dependencies": { - "browserslist": "^4.16.6", - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/svg-tags": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=", - "dev": true - }, - "node_modules/svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", - "dev": true, - "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/svgo/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/tabbable": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.2.1.tgz", - "integrity": "sha512-40pEZ2mhjaZzK0BnI+QGNjJO8UYx9pP5v7BGe17SORTO0OEuuaAwQTkAp8whcZvqon44wKFOikD+Al11K3JICQ==", - "optional": true - }, - "node_modules/tailwindcss": { - "version": "3.0.24", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.24.tgz", - "integrity": "sha512-H3uMmZNWzG6aqmg9q07ZIRNIawoiEcNFKDfL+YzOPuPsXuDXxJxB9icqzLgdzKNwjG3SAro2h9SYav8ewXNgig==", - "dev": true, - "dependencies": { - "arg": "^5.0.1", - "chokidar": "^3.5.3", - "color-name": "^1.1.4", - "detective": "^5.2.0", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.2.11", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "lilconfig": "^2.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.12", - "postcss-js": "^4.0.0", - "postcss-load-config": "^3.1.4", - "postcss-nested": "5.0.6", - "postcss-selector-parser": "^6.0.10", - "postcss-value-parser": "^4.2.0", - "quick-lru": "^5.1.1", - "resolve": "^1.22.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=12.13.0" - }, - "peerDependencies": { - "postcss": "^8.0.9" - } - }, - "node_modules/tailwindcss/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/terser": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.1.tgz", - "integrity": "sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==", - "dev": true, - "dependencies": { - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz", - "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==", - "dev": true, - "dependencies": { - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1", - "terser": "^5.7.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/terser-webpack-plugin/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/terser/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", - "dev": true, - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/thread-loader": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/thread-loader/-/thread-loader-3.0.4.tgz", - "integrity": "sha512-ByaL2TPb+m6yArpqQUZvP+5S1mZtXsEP7nWKKlAUTm7fCml8kB5s1uI3+eHRP2bk5mVYfRSBI7FFf+tWEyLZwA==", - "dev": true, - "dependencies": { - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.1.0", - "loader-utils": "^2.0.0", - "neo-async": "^2.6.2", - "schema-utils": "^3.0.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.27.0 || ^5.0.0" - } - }, - "node_modules/thread-loader/node_modules/loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/thread-loader/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true - }, - "node_modules/tiny-invariant": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", - "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==" - }, - "node_modules/tiny-warning": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", - "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" - }, - "node_modules/tinycolor2": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz", - "integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==", - "engines": { - "node": "*" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/totalist": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", - "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true - }, - "node_modules/ts-loader": { - "version": "9.2.8", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.8.tgz", - "integrity": "sha512-gxSak7IHUuRtwKf3FIPSW1VpZcqF9+MBrHOvBp9cjHh+525SjtCIJKVGjRKIAfxBwDGDGCFF00rTfzB1quxdSw==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "typescript": "*", - "webpack": "^5.0.0" - } - }, - "node_modules/ts-loader/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ts-loader/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ts-loader/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/ts-loader/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/ts-loader/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ts-loader/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ts-results": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/ts-results/-/ts-results-3.3.0.tgz", - "integrity": "sha512-FWqxGX2NHp5oCyaMd96o2y2uMQmSu8Dey6kvyuFdRJ2AzfmWo3kWa4UsPlCGlfQ/qu03m09ZZtppMoY8EMHuiA==" - }, - "node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.2.tgz", - "integrity": "sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A==", - "devOptional": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", - "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", - "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/universal-cookie": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-4.0.4.tgz", - "integrity": "sha512-lbRVHoOMtItjWbM7TwDLdl8wug7izB0tq3/YVKhT/ahB4VDvWMyvnADfnJI8y6fSvsjh51Ix7lTGC6Tn4rMPhw==", - "optional": true, - "dependencies": { - "@types/cookie": "^0.3.3", - "cookie": "^0.4.0" - } - }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/unplugin": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-0.6.3.tgz", - "integrity": "sha512-CoW88FQfCW/yabVc4bLrjikN9HC8dEvMU4O7B6K2jsYMPK0l6iAnd9dpJwqGcmXJKRCU9vwSsy653qg+RK0G6A==", - "dev": true, - "dependencies": { - "chokidar": "^3.5.3", - "webpack-sources": "^3.2.3", - "webpack-virtual-modules": "^0.4.3" - }, - "peerDependencies": { - "esbuild": ">=0.13", - "rollup": "^2.50.0", - "vite": "^2.3.0", - "webpack": "4 || 5" - }, - "peerDependenciesMeta": { - "esbuild": { - "optional": true - }, - "rollup": { - "optional": true - }, - "vite": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/unplugin-vue-components": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-0.19.6.tgz", - "integrity": "sha512-APvrJ9Hpid1MLT0G4PWerMJgARhNw6dzz0pcCwCxaO2DR7VyvDacMqjOQNC6ukq7FSw3wzD8VH+9i3EFXwkGmw==", - "dev": true, - "dependencies": { - "@antfu/utils": "^0.5.1", - "@rollup/pluginutils": "^4.2.1", - "chokidar": "^3.5.3", - "debug": "^4.3.4", - "fast-glob": "^3.2.11", - "local-pkg": "^0.4.1", - "magic-string": "^0.26.1", - "minimatch": "^5.0.1", - "resolve": "^1.22.0", - "unplugin": "^0.6.3" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@babel/parser": "^7.15.8", - "@babel/traverse": "^7.15.4", - "vue": "2 || 3" - }, - "peerDependenciesMeta": { - "@babel/parser": { - "optional": true - }, - "@babel/traverse": { - "optional": true - } - } - }, - "node_modules/unplugin-vue-components/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/unplugin-vue-components/node_modules/magic-string": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.1.tgz", - "integrity": "sha512-ndThHmvgtieXe8J/VGPjG+Apu7v7ItcD5mhEIvOscWjPF/ccOiLxHaSuCAS2G+3x4GKsAbT8u7zdyamupui8Tg==", - "dev": true, - "dependencies": { - "sourcemap-codec": "^1.4.8" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/unplugin-vue-components/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "node_modules/utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", - "dev": true - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/value-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", - "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/vite": { - "version": "2.9.9", - "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.9.tgz", - "integrity": "sha512-ffaam+NgHfbEmfw/Vuh6BHKKlI/XIAhxE5QSS7gFLIngxg171mg1P3a4LSRME0z2ZU1ScxoKzphkipcYwSD5Ew==", - "dev": true, - "dependencies": { - "esbuild": "^0.14.27", - "postcss": "^8.4.13", - "resolve": "^1.22.0", - "rollup": "^2.59.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": ">=12.2.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "less": "*", - "sass": "*", - "stylus": "*" - }, - "peerDependenciesMeta": { - "less": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - } - } - }, - "node_modules/vite-plugin-ejs": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/vite-plugin-ejs/-/vite-plugin-ejs-1.4.4.tgz", - "integrity": "sha512-R3Xt8bPlU/jrzia7iC4sA1bQTRM+JjMrVAk/CTRX8w1EHD8G6xVbSZ6XJbW6kj94M4jEyDu32BAq4JaGoOtnkw==", - "dependencies": { - "ejs": "^3.1.6" - } - }, - "node_modules/vue": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.36.tgz", - "integrity": "sha512-5yTXmrE6gW8IQgttzHW5bfBiFA6mx35ZXHjGLDmKYzW6MMmYvCwuKybANRepwkMYeXw2v1buGg3/lPICY5YlZw==", - "dependencies": { - "@vue/compiler-dom": "3.2.36", - "@vue/compiler-sfc": "3.2.36", - "@vue/runtime-dom": "3.2.36", - "@vue/server-renderer": "3.2.36", - "@vue/shared": "3.2.36" - } - }, - "node_modules/vue-axios": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/vue-axios/-/vue-axios-3.4.1.tgz", - "integrity": "sha512-8YZYUOQrBEJktxoQtrM4rr2LfVcDaWfJqv8MqtLlgLlkuBvCYKFSZSo6AXQ4YcCzdgccDqstmuaEh68lcH9xWA==", - "peerDependencies": { - "axios": ">= 0.20.0", - "vue": "^3.0.0 || ^2.0.0" - } - }, - "node_modules/vue-class-component": { - "version": "8.0.0-rc.1", - "resolved": "https://registry.npmjs.org/vue-class-component/-/vue-class-component-8.0.0-rc.1.tgz", - "integrity": "sha512-w1nMzsT/UdbDAXKqhwTmSoyuJzUXKrxLE77PCFVuC6syr8acdFDAq116xgvZh9UCuV0h+rlCtxXolr3Hi3HyPQ==", - "peerDependencies": { - "vue": "^3.0.0" - } - }, - "node_modules/vue-color-kit": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/vue-color-kit/-/vue-color-kit-1.0.5.tgz", - "integrity": "sha512-PUQzqdpI7672YYuoHdTLENHldieVMis0u9g2n7NAxiLGdiaqCD/QaYtbDOvtASpN5oSIfKxQgPV+i45MOlkKnw==", - "peerDependencies": { - "vue": "^3.0.5" - } - }, - "node_modules/vue-final-modal": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/vue-final-modal/-/vue-final-modal-3.4.4.tgz", - "integrity": "sha512-4nOLU+cMcUqAT0kg+64+Hi96kkQPOph2LOJa7Fl58BXlTyhfRxaMuz3M91wi2ooMIL4poWA8428P5GIAXSpuZg==" - }, - "node_modules/vue-hot-reload-api": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", - "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==", - "dev": true - }, - "node_modules/vue-loader": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-17.0.0.tgz", - "integrity": "sha512-OWSXjrzIvbF2LtOUmxT3HYgwwubbfFelN8PAP9R9dwpIkj48TVioHhWWSx7W7fk+iF5cgg3CBJRxwTdtLU4Ecg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "hash-sum": "^2.0.0", - "loader-utils": "^2.0.0" - }, - "peerDependencies": { - "webpack": "^4.1.0 || ^5.0.0-0" - } - }, - "node_modules/vue-loader/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/vue-loader/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/vue-loader/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/vue-loader/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/vue-loader/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/vue-loader/node_modules/loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/vue-loader/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/vue-meta": { - "version": "3.0.0-alpha.10", - "resolved": "https://registry.npmjs.org/vue-meta/-/vue-meta-3.0.0-alpha.10.tgz", - "integrity": "sha512-rYeIGkhm1gKBcReEkPHiV6LV2Y6BZTMGTkGw1mQIZTxfFcVJL0srLZsL1zAmLeTGxMrlDYylMQEVSYRkDnwz3A==", - "peerDependencies": { - "vue": "^3.0.0" - } - }, - "node_modules/vue-prism-editor": { - "version": "2.0.0-alpha.2", - "resolved": "https://registry.npmjs.org/vue-prism-editor/-/vue-prism-editor-2.0.0-alpha.2.tgz", - "integrity": "sha512-Gu42ba9nosrE+gJpnAEuEkDMqG9zSUysIR8SdXUw8MQKDjBnnNR9lHC18uOr/ICz7yrA/5c7jHJr9lpElODC7w==", - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "vue": "^3.0.0" - } - }, - "node_modules/vue-router": { - "version": "4.0.15", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.15.tgz", - "integrity": "sha512-xa+pIN9ZqORdIW1MkN2+d9Ui2pCM1b/UMgwYUCZOiFYHAvz/slKKBDha8DLrh5aCG/RibtrpyhKjKOZ85tYyWg==", - "dependencies": { - "@vue/devtools-api": "^6.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/posva" - }, - "peerDependencies": { - "vue": "^3.2.0" - } - }, - "node_modules/vue-style-loader": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz", - "integrity": "sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==", - "dev": true, - "dependencies": { - "hash-sum": "^1.0.2", - "loader-utils": "^1.0.2" - } - }, - "node_modules/vue-style-loader/node_modules/hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", - "dev": true - }, - "node_modules/vue-template-es2015-compiler": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", - "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", - "dev": true - }, - "node_modules/vue3-cookies": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/vue3-cookies/-/vue3-cookies-1.0.6.tgz", - "integrity": "sha512-a1UvVD0qIgxyOqjlSOwnLnqAnz8ASltugEv8yX+96i/WGZAN9fEDci7xO4HIWZE1uToUnRq9JnFhvfDCSo45OA==", - "dependencies": { - "vue": "^3.0.0" - } - }, - "node_modules/warning": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", - "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", - "dependencies": { - "loose-envify": "^1.0.0" - } - }, - "node_modules/watchpack": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", - "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", - "dev": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "dependencies": { - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "dev": true, - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true - }, - "node_modules/webpack": { - "version": "5.70.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz", - "integrity": "sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.4.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.9.2", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.3.1", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-bundle-analyzer": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz", - "integrity": "sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ==", - "dev": true, - "dependencies": { - "acorn": "^8.0.4", - "acorn-walk": "^8.0.0", - "chalk": "^4.1.0", - "commander": "^7.2.0", - "gzip-size": "^6.0.0", - "lodash": "^4.17.20", - "opener": "^1.5.2", - "sirv": "^1.0.7", - "ws": "^7.3.1" - }, - "bin": { - "webpack-bundle-analyzer": "lib/bin/analyzer.js" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/webpack-bundle-analyzer/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpack-chain": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-6.5.1.tgz", - "integrity": "sha512-7doO/SRtLu8q5WM0s7vPKPWX580qhi0/yBHkOxNkv50f6qB76Zy9o2wRTrrPULqYTvQlVHuvbA8v+G5ayuUDsA==", - "dev": true, - "dependencies": { - "deepmerge": "^1.5.2", - "javascript-stringify": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpack-chain/node_modules/deepmerge": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz", - "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-middleware": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz", - "integrity": "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==", - "dev": true, - "dependencies": { - "colorette": "^2.0.10", - "memfs": "^3.4.1", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/webpack-dev-middleware/node_modules/ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/webpack-dev-middleware/node_modules/schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/webpack-dev-server": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz", - "integrity": "sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A==", - "dev": true, - "dependencies": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.2.2", - "ansi-html-community": "^0.0.8", - "bonjour": "^3.5.0", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^1.6.0", - "default-gateway": "^6.0.3", - "del": "^6.0.0", - "express": "^4.17.1", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.0", - "ipaddr.js": "^2.0.1", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "portfinder": "^1.0.28", - "schema-utils": "^4.0.0", - "selfsigned": "^2.0.0", - "serve-index": "^1.9.1", - "sockjs": "^0.3.21", - "spdy": "^4.0.2", - "strip-ansi": "^7.0.0", - "webpack-dev-middleware": "^5.3.1", - "ws": "^8.4.2" - }, - "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" - }, - "engines": { - "node": ">= 12.13.0" - }, - "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-dev-server/node_modules/ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack-dev-server/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/webpack-dev-server/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/webpack-dev-server/node_modules/schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/webpack-dev-server/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/webpack-merge": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", - "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack-virtual-modules": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.4.3.tgz", - "integrity": "sha512-5NUqC2JquIL2pBAAo/VfBP6KuGkHIZQXW/lNKupLPfhViwh8wNsu0BObtl09yuKZszeEUfbXz8xhrHvSG16Nqw==", - "dev": true - }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/webpack/node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/whatwg-fetch": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", - "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==", - "dev": true - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "optional": true - }, - "node_modules/wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/ws": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", - "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yorkie": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yorkie/-/yorkie-2.0.0.tgz", - "integrity": "sha512-jcKpkthap6x63MB4TxwCyuIGkV0oYP/YRyuQU5UO0Yz/E/ZAu+653/uov+phdmO54n6BcvFRyyt0RRrWdN2mpw==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "execa": "^0.8.0", - "is-ci": "^1.0.10", - "normalize-path": "^1.0.0", - "strip-indent": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/yorkie/node_modules/cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "dependencies": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "node_modules/yorkie/node_modules/execa": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", - "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=", - "dev": true, - "dependencies": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/yorkie/node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/yorkie/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/yorkie/node_modules/normalize-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz", - "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yorkie/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yorkie/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yorkie/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/yorkie/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - } - }, - "dependencies": { - "@achrinza/node-ipc": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/@achrinza/node-ipc/-/node-ipc-9.2.2.tgz", - "integrity": "sha512-b90U39dx0cU6emsOvy5hxU4ApNXnE3+Tuo8XQZfiKTGelDwpMwBVgBP7QX6dGTcJgu/miyJuNJ/2naFBliNWEw==", - "dev": true, - "requires": { - "@node-ipc/js-queue": "2.0.3", - "event-pubsub": "4.3.0", - "js-message": "1.0.7" - } - }, - "@ampproject/remapping": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", - "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.0" - } - }, - "@antfu/utils": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.5.2.tgz", - "integrity": "sha512-CQkeV+oJxUazwjlHD0/3ZD08QWKuGQkhnrKo3e6ly5pd48VUpXbb77q0xMU4+vc2CkJnDS02Eq/M9ugyX20XZA==", - "dev": true - }, - "@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.16.7" - } - }, - "@babel/compat-data": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz", - "integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==", - "dev": true - }, - "@babel/core": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.8.tgz", - "integrity": "sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.7", - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-module-transforms": "^7.17.7", - "@babel/helpers": "^7.17.8", - "@babel/parser": "^7.17.8", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "@babel/generator": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", - "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", - "dev": true, - "requires": { - "@babel/types": "^7.17.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", - "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz", - "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.16.7", - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz", - "integrity": "sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.17.5", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.17.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz", - "integrity": "sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-member-expression-to-functions": "^7.16.7", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7" - } - }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz", - "integrity": "sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "regexpu-core": "^5.0.1" - } - }, - "@babel/helper-define-polyfill-provider": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", - "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "@babel/helper-environment-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", - "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz", - "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-function-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", - "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", - "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.17.7.tgz", - "integrity": "sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw==", - "dev": true, - "requires": { - "@babel/types": "^7.17.0" - } - }, - "@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-module-transforms": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", - "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz", - "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", - "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", - "dev": true - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz", - "integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-wrap-function": "^7.16.8", - "@babel/types": "^7.16.8" - } - }, - "@babel/helper-replace-supers": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz", - "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-member-expression-to-functions": "^7.16.7", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/traverse": "^7.16.7", - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-simple-access": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", - "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", - "dev": true, - "requires": { - "@babel/types": "^7.17.0" - } - }, - "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", - "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", - "dev": true, - "requires": { - "@babel/types": "^7.16.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true - }, - "@babel/helper-wrap-function": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz", - "integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.16.8", - "@babel/types": "^7.16.8" - } - }, - "@babel/helpers": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.8.tgz", - "integrity": "sha512-QcL86FGxpfSJwGtAvv4iG93UL6bmqBdmoVY0CMCU2g+oD2ezQse3PT5Pa+jiD6LJndBQi0EDlpzOWNlLuhz5gw==", - "dev": true, - "requires": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" - } - }, - "@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.8.tgz", - "integrity": "sha512-BoHhDJrJXqcg+ZL16Xv39H9n+AqJ4pcDrQBGZN+wHxIysrLZ3/ECwCBUch/1zUNhnsXULcONU3Ei5Hmkfk6kiQ==" - }, - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz", - "integrity": "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz", - "integrity": "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", - "@babel/plugin-proposal-optional-chaining": "^7.16.7" - } - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz", - "integrity": "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-remap-async-to-generator": "^7.16.8", - "@babel/plugin-syntax-async-generators": "^7.8.4" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz", - "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-proposal-class-static-block": { - "version": "7.17.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.17.6.tgz", - "integrity": "sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.17.6", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - } - }, - "@babel/plugin-proposal-decorators": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.17.8.tgz", - "integrity": "sha512-U69odN4Umyyx1xO1rTII0IDkAEC+RNlcKXtqOblfpzqy1C+aOplb76BQNq0+XdpVkOaPlpEDwd++joY8FNFJKA==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.17.6", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7", - "@babel/plugin-syntax-decorators": "^7.17.0", - "charcodes": "^0.2.0" - } - }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz", - "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - } - }, - "@babel/plugin-proposal-export-namespace-from": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz", - "integrity": "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz", - "integrity": "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-json-strings": "^7.8.3" - } - }, - "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz", - "integrity": "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - } - }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz", - "integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - } - }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz", - "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz", - "integrity": "sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.17.0", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.16.7" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz", - "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - } - }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz", - "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - } - }, - "@babel/plugin-proposal-private-methods": { - "version": "7.16.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz", - "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.16.10", - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-proposal-private-property-in-object": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz", - "integrity": "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-create-class-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz", - "integrity": "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-decorators": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.17.0.tgz", - "integrity": "sha512-qWe85yCXsvDEluNP0OyeQjH63DlhAR3W7K9BxxU1MvbDb48tgBG+Ao6IJJ6smPDrrVzSQZrbF6donpkFBMcs3A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-jsx": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz", - "integrity": "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz", - "integrity": "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz", - "integrity": "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-remap-async-to-generator": "^7.16.8" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz", - "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz", - "integrity": "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz", - "integrity": "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "globals": "^11.1.0" - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz", - "integrity": "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.7.tgz", - "integrity": "sha512-XVh0r5yq9sLR4vZ6eVZe8FKfIcSgaTBxVBRSYokRj2qksf6QerYnTxz9/GTuKTH/n/HwLP7t6gtlybHetJ/6hQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz", - "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz", - "integrity": "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz", - "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz", - "integrity": "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz", - "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz", - "integrity": "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz", - "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz", - "integrity": "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.17.7.tgz", - "integrity": "sha512-ITPmR2V7MqioMJyrxUo2onHNC3e+MvfFiFIR0RP21d3PtlVb6sfzoxNKiphSZUOM9hEIdzCcZe83ieX3yoqjUA==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.17.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.17.8.tgz", - "integrity": "sha512-39reIkMTUVagzgA5x88zDYXPCMT6lcaRKs1+S9K6NKBPErbgO/w/kP8GlNQTC87b412ZTlmNgr3k2JrWgHH+Bw==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-module-transforms": "^7.17.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz", - "integrity": "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz", - "integrity": "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz", - "integrity": "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz", - "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz", - "integrity": "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz", - "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz", - "integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==", - "dev": true, - "requires": { - "regenerator-transform": "^0.14.2" - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz", - "integrity": "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-runtime": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz", - "integrity": "sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "babel-plugin-polyfill-corejs2": "^0.3.0", - "babel-plugin-polyfill-corejs3": "^0.5.0", - "babel-plugin-polyfill-regenerator": "^0.3.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz", - "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz", - "integrity": "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz", - "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz", - "integrity": "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz", - "integrity": "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-unicode-escapes": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz", - "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz", - "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/preset-env": { - "version": "7.16.11", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz", - "integrity": "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.16.8", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-validator-option": "^7.16.7", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.7", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.7", - "@babel/plugin-proposal-async-generator-functions": "^7.16.8", - "@babel/plugin-proposal-class-properties": "^7.16.7", - "@babel/plugin-proposal-class-static-block": "^7.16.7", - "@babel/plugin-proposal-dynamic-import": "^7.16.7", - "@babel/plugin-proposal-export-namespace-from": "^7.16.7", - "@babel/plugin-proposal-json-strings": "^7.16.7", - "@babel/plugin-proposal-logical-assignment-operators": "^7.16.7", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7", - "@babel/plugin-proposal-numeric-separator": "^7.16.7", - "@babel/plugin-proposal-object-rest-spread": "^7.16.7", - "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", - "@babel/plugin-proposal-optional-chaining": "^7.16.7", - "@babel/plugin-proposal-private-methods": "^7.16.11", - "@babel/plugin-proposal-private-property-in-object": "^7.16.7", - "@babel/plugin-proposal-unicode-property-regex": "^7.16.7", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.16.7", - "@babel/plugin-transform-async-to-generator": "^7.16.8", - "@babel/plugin-transform-block-scoped-functions": "^7.16.7", - "@babel/plugin-transform-block-scoping": "^7.16.7", - "@babel/plugin-transform-classes": "^7.16.7", - "@babel/plugin-transform-computed-properties": "^7.16.7", - "@babel/plugin-transform-destructuring": "^7.16.7", - "@babel/plugin-transform-dotall-regex": "^7.16.7", - "@babel/plugin-transform-duplicate-keys": "^7.16.7", - "@babel/plugin-transform-exponentiation-operator": "^7.16.7", - "@babel/plugin-transform-for-of": "^7.16.7", - "@babel/plugin-transform-function-name": "^7.16.7", - "@babel/plugin-transform-literals": "^7.16.7", - "@babel/plugin-transform-member-expression-literals": "^7.16.7", - "@babel/plugin-transform-modules-amd": "^7.16.7", - "@babel/plugin-transform-modules-commonjs": "^7.16.8", - "@babel/plugin-transform-modules-systemjs": "^7.16.7", - "@babel/plugin-transform-modules-umd": "^7.16.7", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.8", - "@babel/plugin-transform-new-target": "^7.16.7", - "@babel/plugin-transform-object-super": "^7.16.7", - "@babel/plugin-transform-parameters": "^7.16.7", - "@babel/plugin-transform-property-literals": "^7.16.7", - "@babel/plugin-transform-regenerator": "^7.16.7", - "@babel/plugin-transform-reserved-words": "^7.16.7", - "@babel/plugin-transform-shorthand-properties": "^7.16.7", - "@babel/plugin-transform-spread": "^7.16.7", - "@babel/plugin-transform-sticky-regex": "^7.16.7", - "@babel/plugin-transform-template-literals": "^7.16.7", - "@babel/plugin-transform-typeof-symbol": "^7.16.7", - "@babel/plugin-transform-unicode-escapes": "^7.16.7", - "@babel/plugin-transform-unicode-regex": "^7.16.7", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.16.8", - "babel-plugin-polyfill-corejs2": "^0.3.0", - "babel-plugin-polyfill-corejs3": "^0.5.0", - "babel-plugin-polyfill-regenerator": "^0.3.0", - "core-js-compat": "^3.20.2", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "@babel/preset-modules": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", - "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - } - }, - "@babel/runtime": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.8.tgz", - "integrity": "sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA==", - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" - } - }, - "@babel/traverse": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", - "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.3", - "@babel/types": "^7.17.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - } - }, - "@eslint/eslintrc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", - "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.3.2", - "globals": "^13.15.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "globals": { - "version": "13.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", - "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "@hapi/hoek": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz", - "integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==", - "dev": true - }, - "@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "dev": true, - "requires": { - "@hapi/hoek": "^9.0.0" - } - }, - "@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@jridgewell/resolve-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", - "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", - "dev": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.11", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", - "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", - "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@kyvg/vue3-notification": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@kyvg/vue3-notification/-/vue3-notification-2.3.4.tgz", - "integrity": "sha512-20Km1L75gncIZCjosT1OKbJl9HhNiOd7LRXqVIqlehHHem9NgBjQhDFz6XGo1RcF0MyA4/BC7kV7tcq/PMT+tA==", - "requires": {} - }, - "@nitro_repo/nitro_repo-api-wrapper": { - "version": "file:../nitro_repo-api-wrapper", - "requires": { - "axios": "^0.27.2", - "ts-results": "^3.3.0", - "typedoc": "^0.22.15", - "typescript": "^4.7.2" - } - }, - "@node-ipc/js-queue": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@node-ipc/js-queue/-/js-queue-2.0.3.tgz", - "integrity": "sha512-fL1wpr8hhD5gT2dA1qifeVaoDFlQR5es8tFuKqjHX+kdOtdNHnxkVZbtIrR2rxnMFvehkjaZRNV2H/gPXlb0hw==", - "dev": true, - "requires": { - "easy-stack": "1.0.1" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@polka/url": { - "version": "1.0.0-next.21", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", - "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==", - "dev": true - }, - "@rollup/pluginutils": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", - "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", - "dev": true, - "requires": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - } - }, - "@sideway/address": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", - "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", - "dev": true, - "requires": { - "@hapi/hoek": "^9.0.0" - } - }, - "@sideway/formula": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", - "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==", - "dev": true - }, - "@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", - "dev": true - }, - "@soda/friendly-errors-webpack-plugin": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.8.1.tgz", - "integrity": "sha512-h2ooWqP8XuFqTXT+NyAFbrArzfQA7R6HTezADrvD9Re8fxMLTPPniLdqVTdDaO0eIoLaAwKT+d6w+5GeTk7Vbg==", - "dev": true, - "requires": { - "chalk": "^3.0.0", - "error-stack-parser": "^2.0.6", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@soda/get-current-script": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@soda/get-current-script/-/get-current-script-1.0.2.tgz", - "integrity": "sha512-T7VNNlYVM1SgQ+VsMYhnDkcGmWhQdL0bDyGm5TlQ3GBXnJscEClUUOKduWTmm2zCnvNLC1hc3JpuXjs/nFOc5w==", - "dev": true - }, - "@transloadit/prettier-bytes": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz", - "integrity": "sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA==" - }, - "@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true - }, - "@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dev": true, - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/bonjour": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", - "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/connect-history-api-fallback": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz", - "integrity": "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==", - "dev": true, - "requires": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "@types/cookie": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz", - "integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==", - "optional": true - }, - "@types/eslint": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz", - "integrity": "sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng==", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", - "dev": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "@types/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", - "dev": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.28", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", - "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", - "dev": true - }, - "@types/http-proxy": { - "version": "1.17.8", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz", - "integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "dev": true - }, - "@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "@types/node": { - "version": "17.0.23", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", - "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==", - "dev": true - }, - "@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true - }, - "@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true - }, - "@types/retry": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", - "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", - "dev": true - }, - "@types/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", - "dev": true, - "requires": { - "@types/express": "*" - } - }, - "@types/serve-static": { - "version": "1.13.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", - "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", - "dev": true, - "requires": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "@types/sockjs": { - "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", - "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/webpack-env": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.16.3.tgz", - "integrity": "sha512-9gtOPPkfyNoEqCQgx4qJKkuNm/x0R2hKR7fdl7zvTJyHnIisuE/LfvXOsYWL0o3qq6uiBnKZNNNzi3l0y/X+xw==", - "dev": true - }, - "@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@typescript-eslint/eslint-plugin": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.26.0.tgz", - "integrity": "sha512-oGCmo0PqnRZZndr+KwvvAUvD3kNE4AfyoGCwOZpoCncSh4MVD06JTE8XQa2u9u+NX5CsyZMBTEc2C72zx38eYA==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.26.0", - "@typescript-eslint/type-utils": "5.26.0", - "@typescript-eslint/utils": "5.26.0", - "debug": "^4.3.4", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.2.0", - "regexpp": "^3.2.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/parser": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.26.0.tgz", - "integrity": "sha512-n/IzU87ttzIdnAH5vQ4BBDnLPly7rC5VnjN3m0xBG82HK6rhRxnCb3w/GyWbNDghPd+NktJqB/wl6+YkzZ5T5Q==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.26.0", - "@typescript-eslint/types": "5.26.0", - "@typescript-eslint/typescript-estree": "5.26.0", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.26.0.tgz", - "integrity": "sha512-gVzTJUESuTwiju/7NiTb4c5oqod8xt5GhMbExKsCTp6adU3mya6AGJ4Pl9xC7x2DX9UYFsjImC0mA62BCY22Iw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.26.0", - "@typescript-eslint/visitor-keys": "5.26.0" - } - }, - "@typescript-eslint/type-utils": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.26.0.tgz", - "integrity": "sha512-7ccbUVWGLmcRDSA1+ADkDBl5fP87EJt0fnijsMFTVHXKGduYMgienC/i3QwoVhDADUAPoytgjbZbCOMj4TY55A==", - "dev": true, - "requires": { - "@typescript-eslint/utils": "5.26.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/types": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.26.0.tgz", - "integrity": "sha512-8794JZFE1RN4XaExLWLI2oSXsVImNkl79PzTOOWt9h0UHROwJedNOD2IJyfL0NbddFllcktGIO2aOu10avQQyA==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.26.0.tgz", - "integrity": "sha512-EyGpw6eQDsfD6jIqmXP3rU5oHScZ51tL/cZgFbFBvWuCwrIptl+oueUZzSmLtxFuSOQ9vDcJIs+279gnJkfd1w==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.26.0", - "@typescript-eslint/visitor-keys": "5.26.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.26.0.tgz", - "integrity": "sha512-PJFwcTq2Pt4AMOKfe3zQOdez6InIDOjUJJD3v3LyEtxHGVVRK3Vo7Dd923t/4M9hSH2q2CLvcTdxlLPjcIk3eg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.26.0", - "@typescript-eslint/types": "5.26.0", - "@typescript-eslint/typescript-estree": "5.26.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.26.0.tgz", - "integrity": "sha512-wei+ffqHanYDOQgg/fS6Hcar6wAWv0CUPQ3TZzOWd2BLfgP539rb49bwua8WRAs7R6kOSLn82rfEu2ro6Llt8Q==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.26.0", - "eslint-visitor-keys": "^3.3.0" - } - }, - "@uppy/core": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@uppy/core/-/core-2.2.0.tgz", - "integrity": "sha512-qdDoNCjrVjjOmFCFCxc+HEbtbQ9K0k6LKNbZZwWK7d4Cx3xEa6VsxmqVhfFL6ekH2gyboqYV8Z5IbRkJT/0Nqg==", - "peer": true, - "requires": { - "@transloadit/prettier-bytes": "0.0.7", - "@uppy/store-default": "^2.0.3", - "@uppy/utils": "^4.0.7", - "lodash.throttle": "^4.1.1", - "mime-match": "^1.0.2", - "namespace-emitter": "^2.0.1", - "nanoid": "^3.1.25", - "preact": "^10.5.13" - } - }, - "@uppy/dashboard": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@uppy/dashboard/-/dashboard-2.1.4.tgz", - "integrity": "sha512-H9SIuDJCMThBm9VUkb4Rkvl2qAll5tDi7l7Z6A0+07HkfVFVJv8Aq6Lh/sCAVv9v9M7KKBu0X2eCc8o5+22+zA==", - "requires": { - "@transloadit/prettier-bytes": "0.0.7", - "@uppy/informer": "^2.0.5", - "@uppy/provider-views": "^2.0.7", - "@uppy/status-bar": "^2.1.2", - "@uppy/thumbnail-generator": "^2.1.0", - "@uppy/utils": "^4.0.5", - "classnames": "^2.2.6", - "is-shallow-equal": "^1.0.1", - "lodash.debounce": "^4.0.8", - "memoize-one": "^5.0.4", - "nanoid": "^3.1.25", - "preact": "^10.5.13" - } - }, - "@uppy/drag-drop": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@uppy/drag-drop/-/drag-drop-2.1.0.tgz", - "integrity": "sha512-kmxhXVlIS/viyjV+yypCzHDJ0A9MVfPo348tHsAYGNmH25NkjEUmM7DAgb2qmALvzCH3BRFuloq+glLH4i18+g==", - "requires": { - "@uppy/utils": "^4.0.7", - "preact": "^10.5.13" - } - }, - "@uppy/file-input": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@uppy/file-input/-/file-input-2.0.6.tgz", - "integrity": "sha512-Au/J96B6yiGZkjNpLO+/hV43Beq71K3JP2p1f9Eh0EgcgLtqczmM8pggyj6vAduywamUTMWGaADKcdxYKLAFew==", - "requires": { - "@uppy/utils": "^4.0.7", - "preact": "^10.5.13" - } - }, - "@uppy/informer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@uppy/informer/-/informer-2.0.5.tgz", - "integrity": "sha512-XBiTo+NYUMkG3RnwFXmQTnwOcTaBMzMqSTTZZ1/1NndxP1TmpmqonuQQIHlegHUHhF5T+GVAle2rMe+c8iSlsA==", - "requires": { - "@uppy/utils": "^4.0.4", - "preact": "^10.5.13" - } - }, - "@uppy/progress-bar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@uppy/progress-bar/-/progress-bar-2.0.4.tgz", - "integrity": "sha512-W0ATXPP6Ufhb3B0hPPDlO3VVknohpkOA/o/LFVdkOIpq3+mKxkb1+/Nlt3uTa6gxO57O1D6+Kg+l9WKIqpyTbg==", - "requires": { - "@uppy/utils": "^4.0.3", - "preact": "^10.5.13" - } - }, - "@uppy/provider-views": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@uppy/provider-views/-/provider-views-2.0.8.tgz", - "integrity": "sha512-rgCehk4yQFcxbXxdAKEDZe1wiecgZfuJ2FtPUk1atF9IHg7/MekCTLLbKBKh5saLX+uPIuqUXnbLIa+7XKPrgw==", - "requires": { - "@uppy/utils": "^4.0.5", - "classnames": "^2.2.6", - "preact": "^10.5.13" - } - }, - "@uppy/status-bar": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@uppy/status-bar/-/status-bar-2.1.3.tgz", - "integrity": "sha512-+rGZruKzptQ8wVfKXCwDBR9Mw1a/8GECKQ6EwEDzfJxhwz1Tm6kdh5DHDOUlftPTJGJED3bKye7K7fjEhwWfew==", - "requires": { - "@transloadit/prettier-bytes": "0.0.7", - "@uppy/utils": "^4.0.5", - "classnames": "^2.2.6", - "lodash.throttle": "^4.1.1", - "preact": "^10.5.13" - } - }, - "@uppy/store-default": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@uppy/store-default/-/store-default-2.0.3.tgz", - "integrity": "sha512-2BGlN1sW0cFv4rOqTK8dfSg579S984N1HxCJxLFqeW9nWD6zd/O8Omyd85tbxGQ+FLZLTmLOm/feD0YeCBMahg==", - "peer": true - }, - "@uppy/thumbnail-generator": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@uppy/thumbnail-generator/-/thumbnail-generator-2.1.1.tgz", - "integrity": "sha512-iV7Q6Z3huN3RgXiXStKXsHCk6doRzxtkkiQkejpVD8NPODWvgOpL8EFjTqii//3sZJYgquZTWQkMuAJVuoFSSw==", - "requires": { - "@uppy/utils": "^4.0.5", - "exifr": "^7.0.0" - } - }, - "@uppy/utils": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-4.0.7.tgz", - "integrity": "sha512-nKViMT8XchKy+NWpb3DtVKuzZBmW7au26LrMq89EsvTwIOT6UR9+7bmz/+zr3+lc7UC7vMgNChIC6G+/Ya9wWQ==", - "requires": { - "lodash.throttle": "^4.1.1" - } - }, - "@uppy/vue": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@uppy/vue/-/vue-0.4.7.tgz", - "integrity": "sha512-gIDmHA463J6QKwUSZoKsb4qYNu/IaoG3AemJIuV8PcnA/poLn09icLusZDG7IY1WbWEvPogq8P24p37FRoB3bw==", - "requires": { - "@uppy/dashboard": "^2.1.4", - "@uppy/drag-drop": "^2.0.7", - "@uppy/file-input": "^2.0.6", - "@uppy/progress-bar": "^2.0.4", - "@uppy/status-bar": "^2.1.3", - "shallow-equal": "^1.2.1" - } - }, - "@vitejs/plugin-vue": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.3.3.tgz", - "integrity": "sha512-SmQLDyhz+6lGJhPELsBdzXGc+AcaT8stgkbiTFGpXPe8Tl1tJaBw1A6pxDqDuRsVkD8uscrkx3hA7QDOoKYtyw==", - "dev": true, - "requires": {} - }, - "@vue/babel-helper-vue-jsx-merge-props": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.2.1.tgz", - "integrity": "sha512-QOi5OW45e2R20VygMSNhyQHvpdUwQZqGPc748JLGCYEy+yp8fNFNdbNIGAgZmi9e+2JHPd6i6idRuqivyicIkA==", - "dev": true - }, - "@vue/babel-helper-vue-transform-on": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.0.2.tgz", - "integrity": "sha512-hz4R8tS5jMn8lDq6iD+yWL6XNB699pGIVLk7WSJnn1dbpjaazsjZQkieJoRX6gW5zpYSCFqQ7jUquPNY65tQYA==", - "dev": true - }, - "@vue/babel-plugin-jsx": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.1.1.tgz", - "integrity": "sha512-j2uVfZjnB5+zkcbc/zsOc0fSNGCMMjaEXP52wdwdIfn0qjFfEYpYZBFKFg+HHnQeJCVrjOeO0YxgaL7DMrym9w==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.0.0", - "@babel/template": "^7.0.0", - "@babel/traverse": "^7.0.0", - "@babel/types": "^7.0.0", - "@vue/babel-helper-vue-transform-on": "^1.0.2", - "camelcase": "^6.0.0", - "html-tags": "^3.1.0", - "svg-tags": "^1.0.0" - } - }, - "@vue/babel-plugin-transform-vue-jsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.2.1.tgz", - "integrity": "sha512-HJuqwACYehQwh1fNT8f4kyzqlNMpBuUK4rSiSES5D4QsYncv5fxFsLyrxFPG2ksO7t5WP+Vgix6tt6yKClwPzA==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.2.0", - "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", - "html-tags": "^2.0.0", - "lodash.kebabcase": "^4.1.1", - "svg-tags": "^1.0.0" - }, - "dependencies": { - "html-tags": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", - "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", - "dev": true - } - } - }, - "@vue/babel-preset-app": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-5.0.4.tgz", - "integrity": "sha512-vf4KqrmuOSnoEYGUiHPeMoxhh6wpiucLWXISn7xYFU80pK1lqcuhbl6tpurAanUIyRO/ENDUQBH7RAdbLNq1bA==", - "dev": true, - "requires": { - "@babel/core": "^7.12.16", - "@babel/helper-compilation-targets": "^7.12.16", - "@babel/helper-module-imports": "^7.12.13", - "@babel/plugin-proposal-class-properties": "^7.12.13", - "@babel/plugin-proposal-decorators": "^7.12.13", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-jsx": "^7.12.13", - "@babel/plugin-transform-runtime": "^7.12.15", - "@babel/preset-env": "^7.12.16", - "@babel/runtime": "^7.12.13", - "@vue/babel-plugin-jsx": "^1.0.3", - "@vue/babel-preset-jsx": "^1.1.2", - "babel-plugin-dynamic-import-node": "^2.3.3", - "core-js": "^3.8.3", - "core-js-compat": "^3.8.3", - "semver": "^7.3.4" - } - }, - "@vue/babel-preset-jsx": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@vue/babel-preset-jsx/-/babel-preset-jsx-1.2.4.tgz", - "integrity": "sha512-oRVnmN2a77bYDJzeGSt92AuHXbkIxbf/XXSE3klINnh9AXBmVS1DGa1f0d+dDYpLfsAKElMnqKTQfKn7obcL4w==", - "dev": true, - "requires": { - "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", - "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", - "@vue/babel-sugar-composition-api-inject-h": "^1.2.1", - "@vue/babel-sugar-composition-api-render-instance": "^1.2.4", - "@vue/babel-sugar-functional-vue": "^1.2.2", - "@vue/babel-sugar-inject-h": "^1.2.2", - "@vue/babel-sugar-v-model": "^1.2.3", - "@vue/babel-sugar-v-on": "^1.2.3" - } - }, - "@vue/babel-sugar-composition-api-inject-h": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-inject-h/-/babel-sugar-composition-api-inject-h-1.2.1.tgz", - "integrity": "sha512-4B3L5Z2G+7s+9Bwbf+zPIifkFNcKth7fQwekVbnOA3cr3Pq71q71goWr97sk4/yyzH8phfe5ODVzEjX7HU7ItQ==", - "dev": true, - "requires": { - "@babel/plugin-syntax-jsx": "^7.2.0" - } - }, - "@vue/babel-sugar-composition-api-render-instance": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-render-instance/-/babel-sugar-composition-api-render-instance-1.2.4.tgz", - "integrity": "sha512-joha4PZznQMsxQYXtR3MnTgCASC9u3zt9KfBxIeuI5g2gscpTsSKRDzWQt4aqNIpx6cv8On7/m6zmmovlNsG7Q==", - "dev": true, - "requires": { - "@babel/plugin-syntax-jsx": "^7.2.0" - } - }, - "@vue/babel-sugar-functional-vue": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-functional-vue/-/babel-sugar-functional-vue-1.2.2.tgz", - "integrity": "sha512-JvbgGn1bjCLByIAU1VOoepHQ1vFsroSA/QkzdiSs657V79q6OwEWLCQtQnEXD/rLTA8rRit4rMOhFpbjRFm82w==", - "dev": true, - "requires": { - "@babel/plugin-syntax-jsx": "^7.2.0" - } - }, - "@vue/babel-sugar-inject-h": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-inject-h/-/babel-sugar-inject-h-1.2.2.tgz", - "integrity": "sha512-y8vTo00oRkzQTgufeotjCLPAvlhnpSkcHFEp60+LJUwygGcd5Chrpn5480AQp/thrxVm8m2ifAk0LyFel9oCnw==", - "dev": true, - "requires": { - "@babel/plugin-syntax-jsx": "^7.2.0" - } - }, - "@vue/babel-sugar-v-model": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.2.3.tgz", - "integrity": "sha512-A2jxx87mySr/ulAsSSyYE8un6SIH0NWHiLaCWpodPCVOlQVODCaSpiR4+IMsmBr73haG+oeCuSvMOM+ttWUqRQ==", - "dev": true, - "requires": { - "@babel/plugin-syntax-jsx": "^7.2.0", - "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", - "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", - "camelcase": "^5.0.0", - "html-tags": "^2.0.0", - "svg-tags": "^1.0.0" - }, - "dependencies": { - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "html-tags": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", - "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", - "dev": true - } - } - }, - "@vue/babel-sugar-v-on": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.2.3.tgz", - "integrity": "sha512-kt12VJdz/37D3N3eglBywV8GStKNUhNrsxChXIV+o0MwVXORYuhDTHJRKPgLJRb/EY3vM2aRFQdxJBp9CLikjw==", - "dev": true, - "requires": { - "@babel/plugin-syntax-jsx": "^7.2.0", - "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", - "camelcase": "^5.0.0" - }, - "dependencies": { - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - } - } - }, - "@vue/cli-overlay": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@vue/cli-overlay/-/cli-overlay-5.0.4.tgz", - "integrity": "sha512-ZTLAAydILjvx0XHUGSNu/cQDpmvLTMYUutDf2vf6XGkSWYqncQ6RwkeMSQhvQNlgpa/ovwIgrlGxLoojFRwdVg==", - "dev": true - }, - "@vue/cli-plugin-babel": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-babel/-/cli-plugin-babel-5.0.4.tgz", - "integrity": "sha512-413ZwOWLtgw5vWJoMbrv36crW3qTas4Iru8sU7cRb0IqEZbS28R9X4PVtO8Pek2NYFbrs2XKRYOB7GblB6hVqg==", - "dev": true, - "requires": { - "@babel/core": "^7.12.16", - "@vue/babel-preset-app": "^5.0.4", - "@vue/cli-shared-utils": "^5.0.4", - "babel-loader": "^8.2.2", - "thread-loader": "^3.0.0", - "webpack": "^5.54.0" - } - }, - "@vue/cli-plugin-eslint": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-eslint/-/cli-plugin-eslint-5.0.4.tgz", - "integrity": "sha512-NLBEKFTFJhYHMzQ3z+sb6xlkcNaN/RcbZ3hiCY72aJe4YOO8jEAp0XkPzlHd4xYkMW7jrmOwwLOPw+3BJ4b77Q==", - "dev": true, - "requires": { - "@vue/cli-shared-utils": "^5.0.4", - "eslint-webpack-plugin": "^3.1.0", - "globby": "^11.0.2", - "webpack": "^5.54.0", - "yorkie": "^2.0.0" - } - }, - "@vue/cli-plugin-router": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-router/-/cli-plugin-router-5.0.4.tgz", - "integrity": "sha512-lylzCuH3Br0BcTz5IxxSffpyoF9dQ2k4jTdK8QlWrnRanWGw7P9C0kYMr9rohHaXpvAlu6bio392gbNIWpEepg==", - "dev": true, - "requires": { - "@vue/cli-shared-utils": "^5.0.4" - } - }, - "@vue/cli-plugin-typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-typescript/-/cli-plugin-typescript-5.0.4.tgz", - "integrity": "sha512-ITIt9hDc94gI4UCdsoAKYtFp2LAXF9fNYQqXminTnctd0UuTSXGvQcLmCnMYgKfKPVVcAWfG3vCMiB5bsd+Kyg==", - "dev": true, - "requires": { - "@babel/core": "^7.12.16", - "@types/webpack-env": "^1.15.2", - "@vue/cli-shared-utils": "^5.0.4", - "babel-loader": "^8.2.2", - "fork-ts-checker-webpack-plugin": "^6.4.0", - "globby": "^11.0.2", - "thread-loader": "^3.0.0", - "ts-loader": "^9.2.5", - "webpack": "^5.54.0", - "yorkie": "^2.0.0" - } - }, - "@vue/cli-plugin-vuex": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@vue/cli-plugin-vuex/-/cli-plugin-vuex-5.0.4.tgz", - "integrity": "sha512-dBwiD6mT9+V2HTHcwaWE8qFNgTk5I/NUvxYVeUN3Mmmpo4y/1RxXnr7BlKGnaQsTypb2RFk3KowqIJtg7s+E3Q==", - "dev": true, - "requires": {} - }, - "@vue/cli-service": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@vue/cli-service/-/cli-service-5.0.4.tgz", - "integrity": "sha512-xRiLNTFYmMCT9edZpyYXHijW5xot3gbZpcWDOXUOhKPHN4qs4XqWALnZlU97JYjZOr3XIr/ZvyciyEfrlUVqSA==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.12.16", - "@soda/friendly-errors-webpack-plugin": "^1.8.0", - "@soda/get-current-script": "^1.0.2", - "@types/minimist": "^1.2.0", - "@vue/cli-overlay": "^5.0.4", - "@vue/cli-plugin-router": "^5.0.4", - "@vue/cli-plugin-vuex": "^5.0.4", - "@vue/cli-shared-utils": "^5.0.4", - "@vue/component-compiler-utils": "^3.3.0", - "@vue/vue-loader-v15": "npm:vue-loader@^15.9.7", - "@vue/web-component-wrapper": "^1.3.0", - "acorn": "^8.0.5", - "acorn-walk": "^8.0.2", - "address": "^1.1.2", - "autoprefixer": "^10.2.4", - "browserslist": "^4.16.3", - "case-sensitive-paths-webpack-plugin": "^2.3.0", - "cli-highlight": "^2.1.10", - "clipboardy": "^2.3.0", - "cliui": "^7.0.4", - "copy-webpack-plugin": "^9.0.1", - "css-loader": "^6.5.0", - "css-minimizer-webpack-plugin": "^3.0.2", - "cssnano": "^5.0.0", - "debug": "^4.1.1", - "default-gateway": "^6.0.3", - "dotenv": "^10.0.0", - "dotenv-expand": "^5.1.0", - "fs-extra": "^9.1.0", - "globby": "^11.0.2", - "hash-sum": "^2.0.0", - "html-webpack-plugin": "^5.1.0", - "is-file-esm": "^1.0.0", - "launch-editor-middleware": "^2.2.1", - "lodash.defaultsdeep": "^4.6.1", - "lodash.mapvalues": "^4.6.0", - "mini-css-extract-plugin": "^2.5.3", - "minimist": "^1.2.5", - "module-alias": "^2.2.2", - "portfinder": "^1.0.26", - "postcss": "^8.2.6", - "postcss-loader": "^6.1.1", - "progress-webpack-plugin": "^1.0.12", - "ssri": "^8.0.1", - "terser-webpack-plugin": "^5.1.1", - "thread-loader": "^3.0.0", - "vue-loader": "^17.0.0", - "vue-style-loader": "^4.1.3", - "webpack": "^5.54.0", - "webpack-bundle-analyzer": "^4.4.0", - "webpack-chain": "^6.5.1", - "webpack-dev-server": "^4.7.3", - "webpack-merge": "^5.7.3", - "webpack-virtual-modules": "^0.4.2", - "whatwg-fetch": "^3.6.2" - } - }, - "@vue/cli-shared-utils": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@vue/cli-shared-utils/-/cli-shared-utils-5.0.4.tgz", - "integrity": "sha512-nfAsj8Nopu5sVHMBIaut/YL7NaJFVmTBSTJD7LM17jc5uytrM9JwiRtzCiv3JWRBG78Xdb/s2Xb/1YR4fkdmkQ==", - "dev": true, - "requires": { - "@achrinza/node-ipc": "9.2.2", - "chalk": "^4.1.2", - "execa": "^1.0.0", - "joi": "^17.4.0", - "launch-editor": "^2.2.1", - "lru-cache": "^6.0.0", - "node-fetch": "^2.6.7", - "open": "^8.0.2", - "ora": "^5.3.0", - "read-pkg": "^5.1.1", - "semver": "^7.3.4", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@vue/compiler-core": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.36.tgz", - "integrity": "sha512-bbyZM5hvBicv0PW3KUfVi+x3ylHnfKG7DOn5wM+f2OztTzTjLEyBb/5yrarIYpmnGitVGbjZqDbODyW4iK8hqw==", - "requires": { - "@babel/parser": "^7.16.4", - "@vue/shared": "3.2.36", - "estree-walker": "^2.0.2", - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "@vue/compiler-dom": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.36.tgz", - "integrity": "sha512-tcOTAOiW4s24QLnq+ON6J+GRONXJ+A/mqKCORi0LSlIh8XQlNnlm24y8xIL8la+ZDgkdbjarQ9ZqYSvEja6gVA==", - "requires": { - "@vue/compiler-core": "3.2.36", - "@vue/shared": "3.2.36" - } - }, - "@vue/compiler-sfc": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.36.tgz", - "integrity": "sha512-AvGb4bTj4W8uQ4BqaSxo7UwTEqX5utdRSMyHy58OragWlt8nEACQ9mIeQh3K4di4/SX+41+pJrLIY01lHAOFOA==", - "requires": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.36", - "@vue/compiler-dom": "3.2.36", - "@vue/compiler-ssr": "3.2.36", - "@vue/reactivity-transform": "3.2.36", - "@vue/shared": "3.2.36", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7", - "postcss": "^8.1.10", - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "@vue/compiler-ssr": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.36.tgz", - "integrity": "sha512-+KugInUFRvOxEdLkZwE+W43BqHyhBh0jpYXhmqw1xGq2dmE6J9eZ8UUSOKNhdHtQ/iNLWWeK/wPZkVLUf3YGaw==", - "requires": { - "@vue/compiler-dom": "3.2.36", - "@vue/shared": "3.2.36" - } - }, - "@vue/component-compiler-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz", - "integrity": "sha512-97sfH2mYNU+2PzGrmK2haqffDpVASuib9/w2/noxiFi31Z54hW+q3izKQXXQZSNhtiUpAI36uSuYepeBe4wpHQ==", - "dev": true, - "requires": { - "consolidate": "^0.15.1", - "hash-sum": "^1.0.2", - "lru-cache": "^4.1.2", - "merge-source-map": "^1.1.0", - "postcss": "^7.0.36", - "postcss-selector-parser": "^6.0.2", - "prettier": "^1.18.2 || ^2.0.0", - "source-map": "~0.6.1", - "vue-template-es2015-compiler": "^1.9.0" - }, - "dependencies": { - "hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", - "dev": true - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "requires": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - } - } - }, - "@vue/devtools-api": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.1.4.tgz", - "integrity": "sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ==" - }, - "@vue/eslint-config-prettier": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-7.0.0.tgz", - "integrity": "sha512-/CTc6ML3Wta1tCe1gUeO0EYnVXfo3nJXsIhZ8WJr3sov+cGASr6yuiibJTL6lmIBm7GobopToOuB3B6AWyV0Iw==", - "dev": true, - "requires": { - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-prettier": "^4.0.0" - } - }, - "@vue/reactivity": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.36.tgz", - "integrity": "sha512-c2qvopo0crh9A4GXi2/2kfGYMxsJW4tVILrqRPydVGZHhq0fnzy6qmclWOhBFckEhmyxmpHpdJtIRYGeKcuhnA==", - "requires": { - "@vue/shared": "3.2.36" - } - }, - "@vue/reactivity-transform": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.36.tgz", - "integrity": "sha512-Jk5o2BhpODC9XTA7o4EL8hSJ4JyrFWErLtClG3NH8wDS7ri9jBDWxI7/549T7JY9uilKsaNM+4pJASLj5dtRwA==", - "requires": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.36", - "@vue/shared": "3.2.36", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7" - } - }, - "@vue/runtime-core": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.36.tgz", - "integrity": "sha512-PTWBD+Lub+1U3/KhbCExrfxyS14hstLX+cBboxVHaz+kXoiDLNDEYAovPtxeTutbqtClIXtft+wcGdC+FUQ9qQ==", - "requires": { - "@vue/reactivity": "3.2.36", - "@vue/shared": "3.2.36" - } - }, - "@vue/runtime-dom": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.36.tgz", - "integrity": "sha512-gYPYblm7QXHVuBohqNRRT7Wez0f2Mx2D40rb4fleehrJU9CnkjG0phhcGEZFfGwCmHZRqBCRgbFWE98bPULqkg==", - "requires": { - "@vue/runtime-core": "3.2.36", - "@vue/shared": "3.2.36", - "csstype": "^2.6.8" - } - }, - "@vue/server-renderer": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.36.tgz", - "integrity": "sha512-uZE0+jfye6yYXWvAQYeHZv+f50sRryvy16uiqzk3jn8hEY8zTjI+rzlmZSGoE915k+W/Ol9XSw6vxOUD8dGkUg==", - "requires": { - "@vue/compiler-ssr": "3.2.36", - "@vue/shared": "3.2.36" - } - }, - "@vue/shared": { - "version": "3.2.36", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.36.tgz", - "integrity": "sha512-JtB41wXl7Au3+Nl3gD16Cfpj7k/6aCroZ6BbOiCMFCMvrOpkg/qQUXTso2XowaNqBbnkuGHurLAqkLBxNGc1hQ==" - }, - "@vue/vue-loader-v15": { - "version": "npm:vue-loader@15.9.8", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.8.tgz", - "integrity": "sha512-GwSkxPrihfLR69/dSV3+5CdMQ0D+jXg8Ma1S4nQXKJAznYFX14vHdc/NetQc34Dw+rBbIJyP7JOuVb9Fhprvog==", - "dev": true, - "requires": { - "@vue/component-compiler-utils": "^3.1.0", - "hash-sum": "^1.0.2", - "loader-utils": "^1.1.0", - "vue-hot-reload-api": "^2.3.0", - "vue-style-loader": "^4.1.0" - }, - "dependencies": { - "hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", - "dev": true - } - } - }, - "@vue/web-component-wrapper": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz", - "integrity": "sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==", - "dev": true - }, - "@vueuse/core": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-5.3.0.tgz", - "integrity": "sha512-bBL1/JMRHFWmbgQzUZHF4WOwlqfenR1B8+elriXsbnHlogQM5foSz9++WyDBR0YPIVgCJq7fvNLqd4T7+cjc5w==", - "requires": { - "@vueuse/shared": "5.3.0", - "vue-demi": "*" - }, - "dependencies": { - "vue-demi": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.4.tgz", - "integrity": "sha512-ztPDkFt0TSUdoq1ZI6oD730vgztBkiByhUW7L1cOTebiSBqSYfSQgnhYakYigBkyAybqCTH7h44yZuDJf2xILQ==", - "requires": {} - } - } - }, - "@vueuse/integrations": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-5.3.0.tgz", - "integrity": "sha512-qZg0b656O5alOOfl9p4BucRumhzHoKmKWUxYjkCwWh+3nPSP5R1+r1wFi1lg6ELPoTCww0LXTlPCZAmz9dSLjA==", - "requires": { - "@vueuse/shared": "5.3.0", - "axios": "^0.21.1", - "focus-trap": "^6.6.0", - "jwt-decode": "^3.1.2", - "nprogress": "^0.2.0", - "qrcode": "^1.4.4", - "universal-cookie": "^4.0.4", - "vue-demi": "*" - }, - "dependencies": { - "axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "optional": true, - "requires": { - "follow-redirects": "^1.14.0" - } - }, - "vue-demi": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.4.tgz", - "integrity": "sha512-ztPDkFt0TSUdoq1ZI6oD730vgztBkiByhUW7L1cOTebiSBqSYfSQgnhYakYigBkyAybqCTH7h44yZuDJf2xILQ==", - "requires": {} - } - } - }, - "@vueuse/shared": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-5.3.0.tgz", - "integrity": "sha512-qZfkPFH0qTScFpYiPOFpTcxWriRhlM3bgSzl3DFTgr/U0eZg3w2EFWaRZHdWeSvAUdNQyjOC4Toa8S0zJyEjHw==", - "requires": { - "vue-demi": "*" - }, - "dependencies": { - "vue-demi": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.4.tgz", - "integrity": "sha512-ztPDkFt0TSUdoq1ZI6oD730vgztBkiByhUW7L1cOTebiSBqSYfSQgnhYakYigBkyAybqCTH7h44yZuDJf2xILQ==", - "requires": {} - } - } - }, - "@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webcomponents/webcomponentsjs": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@webcomponents/webcomponentsjs/-/webcomponentsjs-2.6.0.tgz", - "integrity": "sha512-Moog+Smx3ORTbWwuPqoclr+uvfLnciVd6wdCaVscHPrxbmQ/IJKm3wbB7hpzJtXWjAq2l/6QMlO85aZiOdtv5Q==" - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", - "dev": true - }, - "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "requires": {} - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "acorn-node": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", - "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", - "dev": true, - "requires": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true - } - } - }, - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true - }, - "address": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", - "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==", - "dev": true - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "requires": { - "ajv": "^8.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - } - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true - }, - "ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "devOptional": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", - "dev": true - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true - }, - "arg": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", - "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==", - "dev": true - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", - "dev": true - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true - }, - "autoprefixer": { - "version": "10.4.4", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.4.tgz", - "integrity": "sha512-Tm8JxsB286VweiZ5F0anmbyGiNI3v3wGv3mz9W+cxEDYB/6jbnj6GM9H9mK3wIL8ftgl+C07Lcwb8PG5PCCPzA==", - "dev": true, - "requires": { - "browserslist": "^4.20.2", - "caniuse-lite": "^1.0.30001317", - "fraction.js": "^4.2.0", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - } - }, - "axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", - "requires": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" - } - }, - "babel-loader": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.4.tgz", - "integrity": "sha512-8dytA3gcvPPPv4Grjhnt8b5IIiTcq/zeXOPk4iTYI0SVXcsmuGg7JtBRDp8S9X+gJfhQ8ektjXZlDu1Bb33U8A==", - "dev": true, - "requires": { - "find-cache-dir": "^3.3.1", - "loader-utils": "^2.0.0", - "make-dir": "^3.1.0", - "schema-utils": "^2.6.5" - }, - "dependencies": { - "loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - } - } - }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dev": true, - "requires": { - "object.assign": "^4.1.0" - } - }, - "babel-plugin-polyfill-corejs2": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", - "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.3.1", - "semver": "^6.1.1" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "babel-plugin-polyfill-corejs3": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", - "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", - "dev": true, - "requires": { - "@babel/helper-define-polyfill-provider": "^0.3.1", - "core-js-compat": "^3.21.0" - } - }, - "babel-plugin-polyfill-regenerator": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", - "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", - "dev": true, - "requires": { - "@babel/helper-define-polyfill-provider": "^0.3.1" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true - }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", - "dev": true - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.7", - "raw-body": "2.4.3", - "type-is": "~1.6.18" - }, - "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "body-scroll-lock": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/body-scroll-lock/-/body-scroll-lock-3.1.5.tgz", - "integrity": "sha512-Yi1Xaml0EvNA0OYWxXiYNqY24AfWkbA6w5vxE7GWxtKfzIbZM+Qw+aSmkgsbWzbHiy/RCSkUZBplVxTA+E4jJg==" - }, - "bonjour": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", - "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", - "dev": true, - "requires": { - "array-flatten": "^2.1.0", - "deep-equal": "^1.0.1", - "dns-equal": "^1.0.0", - "dns-txt": "^2.0.2", - "multicast-dns": "^6.0.1", - "multicast-dns-service-types": "^1.1.0" - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "boxicons": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/boxicons/-/boxicons-2.1.2.tgz", - "integrity": "sha512-NAEj0xmE64Hv6q7yjvyEVsdA+XIESHLe/S/bkCd2A197LQNpZ5ftopxmD3DMatZ1lndGIzxxqqFnWrD1oB3IIg==", - "requires": { - "@webcomponents/webcomponentsjs": "^2.0.2", - "prop-types": "^15.6.0", - "react": "^16.0.0", - "react-dom": "^16.0.0", - "react-interactive": "^0.8.1", - "react-router-dom": "^4.2.2" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browserslist": { - "version": "4.20.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz", - "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001317", - "electron-to-chromium": "^1.4.84", - "escalade": "^3.1.1", - "node-releases": "^2.0.2", - "picocolors": "^1.0.0" - } - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "buffer-indexof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", - "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", - "dev": true - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "requires": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true - }, - "caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dev": true, - "requires": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "caniuse-lite": { - "version": "1.0.30001320", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001320.tgz", - "integrity": "sha512-MWPzG54AGdo3nWx7zHZTefseM5Y1ccM7hlQKHRqJkPozUaw3hNbBTMmLn16GG2FUzjR13Cr3NPfhIieX5PzXDA==", - "dev": true - }, - "case-sensitive-paths-webpack-plugin": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", - "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "charcodes": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/charcodes/-/charcodes-0.2.0.tgz", - "integrity": "sha512-Y4kiDb+AM4Ecy58YkuZrrSRJBDQdQ2L+NyS1vHHFtNtUjgutcZfx3yp1dAONI/oPaPmyGfCLx5CxL+zauIMyKQ==", - "dev": true - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true - }, - "ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", - "dev": true - }, - "classnames": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", - "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" - }, - "clean-css": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz", - "integrity": "sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg==", - "dev": true, - "requires": { - "source-map": "~0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-highlight": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", - "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "highlight.js": "^10.7.1", - "mz": "^2.4.0", - "parse5": "^5.1.1", - "parse5-htmlparser2-tree-adapter": "^6.0.0", - "yargs": "^16.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", - "dev": true - }, - "clipboardy": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz", - "integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==", - "dev": true, - "requires": { - "arch": "^2.1.1", - "execa": "^1.0.0", - "is-wsl": "^2.1.1" - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "colord": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz", - "integrity": "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==", - "dev": true - }, - "colorette": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", - "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "requires": { - "mime-db": ">= 1.43.0 < 2" - } - }, - "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "connect-history-api-fallback": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", - "dev": true - }, - "consolidate": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz", - "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==", - "dev": true, - "requires": { - "bluebird": "^3.1.1" - } - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "requires": { - "safe-buffer": "5.2.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true - }, - "convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "devOptional": true - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "copy-webpack-plugin": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-9.1.0.tgz", - "integrity": "sha512-rxnR7PaGigJzhqETHGmAcxKnLZSR5u1Y3/bcIv/1FnqXedcL/E2ewK7ZCNrArJKCiSv8yVXhTqetJh8inDvfsA==", - "dev": true, - "requires": { - "fast-glob": "^3.2.7", - "glob-parent": "^6.0.1", - "globby": "^11.0.3", - "normalize-path": "^3.0.0", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0" - }, - "dependencies": { - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "core-js": { - "version": "3.22.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.7.tgz", - "integrity": "sha512-Jt8SReuDKVNZnZEzyEQT5eK6T2RRCXkfTq7Lo09kpm+fHjgGewSbNjV+Wt4yZMhPDdzz2x1ulI5z/w4nxpBseg==" - }, - "core-js-compat": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.21.1.tgz", - "integrity": "sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g==", - "dev": true, - "requires": { - "browserslist": "^4.19.1", - "semver": "7.0.0" - }, - "dependencies": { - "semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true - } - } - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "css-declaration-sorter": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.2.1.tgz", - "integrity": "sha512-4qvWVSwnc5f1ZxCe80LccU5aenhZdhuCCyaOSMhr3dDAOTXtJNfAvthW+5x0UV4k1pWzE1EwNk4ztSDCk6WzKw==", - "dev": true, - "requires": {} - }, - "css-loader": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz", - "integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==", - "dev": true, - "requires": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.7", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.3.5" - } - }, - "css-minimizer-webpack-plugin": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz", - "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==", - "dev": true, - "requires": { - "cssnano": "^5.0.6", - "jest-worker": "^27.0.2", - "postcss": "^8.3.5", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1" - }, - "dependencies": { - "ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "css-select": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz", - "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^5.1.0", - "domhandler": "^4.3.0", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - } - }, - "css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dev": true, - "requires": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "css-what": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", - "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", - "dev": true - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "cssnano": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.5.tgz", - "integrity": "sha512-VZO1e+bRRVixMeia1zKagrv0lLN1B/r/u12STGNNUFxnp97LIFgZHQa0JxqlwEkvzUyA9Oz/WnCTAFkdEbONmg==", - "dev": true, - "requires": { - "cssnano-preset-default": "^5.2.5", - "lilconfig": "^2.0.3", - "yaml": "^1.10.2" - } - }, - "cssnano-preset-default": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.5.tgz", - "integrity": "sha512-WopL7PzN7sos3X8B54/QGl+CZUh1f0qN4ds+y2d5EPwRSSc3jsitVw81O+Uyop0pXyOfPfZxnc+LmA8w/Ki/WQ==", - "dev": true, - "requires": { - "css-declaration-sorter": "^6.0.3", - "cssnano-utils": "^3.1.0", - "postcss-calc": "^8.2.3", - "postcss-colormin": "^5.3.0", - "postcss-convert-values": "^5.1.0", - "postcss-discard-comments": "^5.1.1", - "postcss-discard-duplicates": "^5.1.0", - "postcss-discard-empty": "^5.1.1", - "postcss-discard-overridden": "^5.1.0", - "postcss-merge-longhand": "^5.1.3", - "postcss-merge-rules": "^5.1.1", - "postcss-minify-font-values": "^5.1.0", - "postcss-minify-gradients": "^5.1.1", - "postcss-minify-params": "^5.1.2", - "postcss-minify-selectors": "^5.2.0", - "postcss-normalize-charset": "^5.1.0", - "postcss-normalize-display-values": "^5.1.0", - "postcss-normalize-positions": "^5.1.0", - "postcss-normalize-repeat-style": "^5.1.0", - "postcss-normalize-string": "^5.1.0", - "postcss-normalize-timing-functions": "^5.1.0", - "postcss-normalize-unicode": "^5.1.0", - "postcss-normalize-url": "^5.1.0", - "postcss-normalize-whitespace": "^5.1.1", - "postcss-ordered-values": "^5.1.1", - "postcss-reduce-initial": "^5.1.0", - "postcss-reduce-transforms": "^5.1.0", - "postcss-svgo": "^5.1.0", - "postcss-unique-selectors": "^5.1.1" - } - }, - "cssnano-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", - "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", - "dev": true, - "requires": {} - }, - "csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "dev": true, - "requires": { - "css-tree": "^1.1.2" - } - }, - "csstype": { - "version": "2.6.20", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", - "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==" - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "optional": true - }, - "deep-equal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", - "dev": true, - "requires": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true - }, - "default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, - "requires": { - "execa": "^5.0.0" - }, - "dependencies": { - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - } - } - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, - "define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true - }, - "del": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", - "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", - "dev": true, - "requires": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "detect-hover": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-hover/-/detect-hover-1.0.3.tgz", - "integrity": "sha512-HtLoY+tClgYucJNiovNICGWFp9nOGVmHY44s7L62iPqORXM9vujeWFaVcqtA7XRvp/2Y+4RBUfHbDKFGN+xxZQ==" - }, - "detect-it": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/detect-it/-/detect-it-3.0.7.tgz", - "integrity": "sha512-RxpgcdbatUX6epJE09K16iJqF7x6iEcEdoL18FR2zpBO4JhnL7aMOAUoUEyexdtbWOSfTmoDWmeD6mwRBQyRXg==", - "requires": { - "detect-hover": "^1.0.3", - "detect-passive-events": "^1.0.5", - "detect-pointer": "^1.0.3", - "detect-touch-events": "^2.0.2" - } - }, - "detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true - }, - "detect-passive-events": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/detect-passive-events/-/detect-passive-events-1.0.5.tgz", - "integrity": "sha512-foW7Q35wwOCxVzW0xLf5XeB5Fhe7oyRgvkBYdiP9IWgLMzjqUqTvsJv9ymuEWGjY6AoDXD3OC294+Z9iuOw0QA==" - }, - "detect-pointer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-pointer/-/detect-pointer-1.0.3.tgz", - "integrity": "sha512-d0o/Puo3fiGSCXy6H039h9Kwz+mmYCGKZ/qtPFnpN3WfsumjC1C9b5KKvRu+aYnfdI8peqN/iAe7dPd85qIt2g==" - }, - "detect-touch-events": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/detect-touch-events/-/detect-touch-events-2.0.2.tgz", - "integrity": "sha512-g8GWBkJLiIDRJfRXEdrd1wMXpNyGId2DkbfuwFahSb4OCvn717hyRJtAcEDISfp3zkwEhZ4Y4woHPA6DeyB3Fw==" - }, - "detective": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", - "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", - "dev": true, - "requires": { - "acorn-node": "^1.6.1", - "defined": "^1.0.0", - "minimist": "^1.1.1" - } - }, - "didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true - }, - "dijkstrajs": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.2.tgz", - "integrity": "sha512-QV6PMaHTCNmKSeP6QoXhVTw9snc9VD8MulTT0Bd99Pacp4SS1cjcrYPgBPmibqKVtMJJfqC6XvOXgPMEEPH/fg==", - "optional": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true - }, - "dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", - "dev": true - }, - "dns-packet": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz", - "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==", - "dev": true, - "requires": { - "ip": "^1.1.0", - "safe-buffer": "^5.0.1" - } - }, - "dns-txt": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", - "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", - "dev": true, - "requires": { - "buffer-indexof": "^1.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dev": true, - "requires": { - "utila": "~0.4" - } - }, - "dom-serializer": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", - "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - } - }, - "domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", - "dev": true - }, - "domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "requires": { - "domelementtype": "^2.2.0" - } - }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", - "dev": true - }, - "dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", - "dev": true - }, - "duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "easy-stack": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.1.tgz", - "integrity": "sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w==", - "dev": true - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "ejs": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.7.tgz", - "integrity": "sha512-BIar7R6abbUxDA3bfXrO4DSgwo8I+fB5/1zgujl3HLLjwd6+9iOnrT+t3grn2qbk9vOgBubXOFwX2m9axoFaGw==", - "requires": { - "jake": "^10.8.5" - } - }, - "electron-to-chromium": { - "version": "1.4.94", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.94.tgz", - "integrity": "sha512-CoOKsuACoa0PAG3hQXxbh/XDiFcjGuSyGKUi09cjMHOt6RCi7/EXgXhaFF3I+aC89Omudqmkzd0YOQKxwtf/Bg==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "devOptional": true - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "encode-utf8": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz", - "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==", - "optional": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enhanced-resolve": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz", - "integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "dependencies": { - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - } - } - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true - }, - "equal-vue": { - "version": "0.79.3", - "resolved": "https://registry.npmjs.org/equal-vue/-/equal-vue-0.79.3.tgz", - "integrity": "sha512-+/ZXStdr8tteQWxvmNuLc2PwbmHmWjLvW+fwHOLTErjYueexC3472hlEXPusU9H0z/MF6p6SEHdNo9uUdObokw==", - "requires": { - "@vueuse/core": "^5.0.3", - "@vueuse/integrations": "^5.0.3", - "body-scroll-lock": "^3.1.5", - "tinycolor2": "^1.4.2", - "vue": "^3.0.5" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "error-stack-parser": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.7.tgz", - "integrity": "sha512-chLOW0ZGRf4s8raLrDxa5sdkvPec5YdvwbFnqJme4rk0rFajP8mPtrDL1+I+CwrQDCjswDA5sREX7jYQDQs9vA==", - "dev": true, - "requires": { - "stackframe": "^1.1.1" - } - }, - "es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true - }, - "esbuild": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.28.tgz", - "integrity": "sha512-YLNprkCcMVKQ5sekmCKEQ3Obu/L7s6+iij38xNKyBeSmSsTWur4Ky/9zB3XIGT8SCJITG/bZwAR2l7YOAXch4Q==", - "dev": true, - "requires": { - "esbuild-android-64": "0.14.28", - "esbuild-android-arm64": "0.14.28", - "esbuild-darwin-64": "0.14.28", - "esbuild-darwin-arm64": "0.14.28", - "esbuild-freebsd-64": "0.14.28", - "esbuild-freebsd-arm64": "0.14.28", - "esbuild-linux-32": "0.14.28", - "esbuild-linux-64": "0.14.28", - "esbuild-linux-arm": "0.14.28", - "esbuild-linux-arm64": "0.14.28", - "esbuild-linux-mips64le": "0.14.28", - "esbuild-linux-ppc64le": "0.14.28", - "esbuild-linux-riscv64": "0.14.28", - "esbuild-linux-s390x": "0.14.28", - "esbuild-netbsd-64": "0.14.28", - "esbuild-openbsd-64": "0.14.28", - "esbuild-sunos-64": "0.14.28", - "esbuild-windows-32": "0.14.28", - "esbuild-windows-64": "0.14.28", - "esbuild-windows-arm64": "0.14.28" - } - }, - "esbuild-android-64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.28.tgz", - "integrity": "sha512-A52C3zq+9tNwCqZ+4kVLBxnk/WnrYM8P2+QNvNE9B6d2OVPs214lp3g6UyO+dKDhUdefhfPCuwkP8j2A/+szNA==", - "dev": true, - "optional": true - }, - "esbuild-android-arm64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.28.tgz", - "integrity": "sha512-sm0fDEGElZhMC3HLZeECI2juE4aG7uPfMBMqNUhy9CeX399Pz8rC6e78OXMXInGjSdEAwQmCOHmfsP7uv3Q8rA==", - "dev": true, - "optional": true - }, - "esbuild-darwin-64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.28.tgz", - "integrity": "sha512-nzDd7mQ44FvsFHtOafZdBgn3Li5SMsnMnoz1J2MM37xJmR3wGNTFph88KypjHgWqwbxCI7MXS1U+sN4qDeeW6Q==", - "dev": true, - "optional": true - }, - "esbuild-darwin-arm64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.28.tgz", - "integrity": "sha512-XEq/bLR/glsUl+uGrBimQzOVs/CmwI833fXUhP9xrLI3IJ+rKyrZ5IA8u+1crOEf1LoTn8tV+hInmX6rGjbScw==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.28.tgz", - "integrity": "sha512-rTKLgUj/HEcPeE5XZ7IZwWpFx7IWMfprN7QRk/TUJE1s1Ipb58esboIesUpjirJz/BwrgHq+FDG9ChAI8dZAtQ==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-arm64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.28.tgz", - "integrity": "sha512-sBffxD1UMOsB7aWMoExmipycjcy3HJGwmqE4GQZUTZvdiH4GhjgUiVdtPyt7kSCdL40JqnWQJ4b1l8Y51oCF4Q==", - "dev": true, - "optional": true - }, - "esbuild-linux-32": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.28.tgz", - "integrity": "sha512-+Wxidh3fBEQ9kHcCsD4etlBTMb1n6QY2uXv3rFhVn88CY/JP782MhA57/ipLMY4kOLeSKEuFGN4rtjHuhmRMig==", - "dev": true, - "optional": true - }, - "esbuild-linux-64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.28.tgz", - "integrity": "sha512-7+xgsC4LvR6cnzaBdiljNnPDjbkwzahogN+S9uy9AoYw7ZjPnnXc6sjQAVCbqGb7MEgrWdpa6u/Tao79i4lWxg==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.28.tgz", - "integrity": "sha512-L5isjmlLbh9E0WVllXiVETbScgMbth/+XkXQii1WwgO1RvLIfaGrVFz8d2n6EH/ImtgYxPYGx+OcvIKQBc91Rg==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.28.tgz", - "integrity": "sha512-EjRHgwg+kgXABzyoPGPOPg4d5wZqRnZ/ZAxBDzLY+i6DS8OUfTSlZHWIOZzU4XF7125WxRBg9ULbrFJBl+57Eg==", - "dev": true, - "optional": true - }, - "esbuild-linux-mips64le": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.28.tgz", - "integrity": "sha512-krx9SSg7yfiUKk64EmjefOyiEF6nv2bRE4um/LiTaQ6Y/6FP4UF3/Ou/AxZVyR154uSRq63xejcAsmswXAYRsw==", - "dev": true, - "optional": true - }, - "esbuild-linux-ppc64le": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.28.tgz", - "integrity": "sha512-LD0Xxu9g+DNuhsEBV5QuVZ4uKVBMup0xPIruLweuAf9/mHXFnaCuNXUBF5t0DxKl7GQ5MSioKtnb92oMo+QXEw==", - "dev": true, - "optional": true - }, - "esbuild-linux-riscv64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.28.tgz", - "integrity": "sha512-L/DWfRh2P0vxq4Y+qieSNXKGdMg+e9Qe8jkbN2/8XSGYDTPzO2OcAxSujob4qIh7iSl+cknbXV+BvH0YFR0jbg==", - "dev": true, - "optional": true - }, - "esbuild-linux-s390x": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.28.tgz", - "integrity": "sha512-rrgxmsbmL8QQknWGnAL9bGJRQYLOi2AzXy5OTwfhxnj9eqjo5mSVbJXjgiq5LPUAMQZGdPH5yaNK0obAXS81Zw==", - "dev": true, - "optional": true - }, - "esbuild-netbsd-64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.28.tgz", - "integrity": "sha512-h8wntIyOR8/xMVVM6TvJxxWKh4AjmLK87IPKpuVi8Pq0kyk0RMA+eo4PFGk5j2XK0D7dj8PcSF5NSlP9kN/j0A==", - "dev": true, - "optional": true - }, - "esbuild-openbsd-64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.28.tgz", - "integrity": "sha512-HBv18rVapbuDx52/fhZ/c/w6TXyaQAvRxiDDn5Hz/pBcwOs3cdd2WxeIKlWmDoqm2JMx5EVlq4IWgoaRX9mVkw==", - "dev": true, - "optional": true - }, - "esbuild-sunos-64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.28.tgz", - "integrity": "sha512-zlIxePhZxKYheR2vBCgPVvTixgo/ozOfOMoP6RZj8dxzquU1NgeyhjkcRXucbLCtmoNJ+i4PtWwPZTLuDd3bGg==", - "dev": true, - "optional": true - }, - "esbuild-windows-32": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.28.tgz", - "integrity": "sha512-am9DIJxXlld1BOAY/VlvBQHMUCPL7S3gB/lnXIY3M4ys0gfuRqPf4EvMwZMzYUbFKBY+/Qb8SRgPRRGhwnJ8Kg==", - "dev": true, - "optional": true - }, - "esbuild-windows-64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.28.tgz", - "integrity": "sha512-78PhySDnmRZlsPNp/W/5Fim8iivlBQQxfhBFIqR7xwvfDmCFUSByyMKP7LCHgNtb04yNdop8nJJkJaQ8Xnwgiw==", - "dev": true, - "optional": true - }, - "esbuild-windows-arm64": { - "version": "0.14.28", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.28.tgz", - "integrity": "sha512-VhXGBTo6HELD8zyHXynV6+L2jWx0zkKnGx4TmEdSBK7UVFACtOyfUqpToG0EtnYyRZ0HESBhzPSVpP781ovmvA==", - "dev": true, - "optional": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "eslint": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.16.0.tgz", - "integrity": "sha512-MBndsoXY/PeVTDJeWsYj7kLZ5hQpJOfMYLsF6LicLHQWbRDG19lK5jOix4DPl8yY4SUFcE3txy86OzFLWT+yoA==", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.3.0", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.2", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "globals": { - "version": "13.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", - "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "eslint-config-prettier": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", - "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", - "dev": true, - "requires": {} - }, - "eslint-plugin-prettier": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", - "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, - "eslint-plugin-vue": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.0.1.tgz", - "integrity": "sha512-/w/9/vzz+4bSYtp5UqXgJ0CfycXTMtpp6lkz7/fMp0CcJxPWyRP6Pr88ihhrsNEcVt2ZweMupWRNYa+5Md41LQ==", - "dev": true, - "requires": { - "eslint-utils": "^3.0.0", - "natural-compare": "^1.4.0", - "nth-check": "^2.0.1", - "postcss-selector-parser": "^6.0.9", - "semver": "^7.3.5", - "vue-eslint-parser": "^9.0.1", - "xml-name-validator": "^4.0.0" - }, - "dependencies": { - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "vue-eslint-parser": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.0.2.tgz", - "integrity": "sha512-uCPQwTGjOtAYrwnU+76pYxalhjsh7iFBsHwBqDHiOPTxtICDaraO4Szw54WFTNZTAEsgHHzqFOu1mmnBOBRzDA==", - "dev": true, - "requires": { - "debug": "^4.3.4", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", - "esquery": "^1.4.0", - "lodash": "^4.17.21", - "semver": "^7.3.6" - } - } - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true - }, - "eslint-webpack-plugin": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.1.1.tgz", - "integrity": "sha512-xSucskTN9tOkfW7so4EaiFIkulWLXwCB/15H917lR6pTv0Zot6/fetFucmENRb7J5whVSFKIvwnrnsa78SG2yg==", - "dev": true, - "requires": { - "@types/eslint": "^7.28.2", - "jest-worker": "^27.3.1", - "micromatch": "^4.0.4", - "normalize-path": "^3.0.0", - "schema-utils": "^3.1.1" - }, - "dependencies": { - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "espree": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", - "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", - "dev": true, - "requires": { - "acorn": "^8.7.1", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - } - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true - }, - "event-pubsub": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz", - "integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ==", - "dev": true - }, - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "exifr": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/exifr/-/exifr-7.1.3.tgz", - "integrity": "sha512-g/aje2noHivrRSLbAUtBPWFbxKdKhgj/xr1vATDdUXPOFYJlQ62Ft0oy+72V6XLIpDJfHs6gXLbBLAolqOXYRw==" - }, - "express": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", - "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", - "dev": true, - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.19.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.4.2", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.9.7", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.17.2", - "serve-static": "1.14.2", - "setprototypeof": "1.2.0", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fast-xml-parser": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.0.8.tgz", - "integrity": "sha512-N4XqZaRMuHMvOFwFlqeBTlvrnXU+QN8wvCl2g9fHzMx2BnLoIYRDwy6XwI8FxogHMFI9OfGQBCddgckvSLTnvg==", - "requires": { - "strnum": "^1.0.5" - } - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "filelist": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.3.tgz", - "integrity": "sha512-LwjCsruLWQULGYKy7TX0OPtrL9kLpojOFKc5VCTxdFTV7w5zbsgqVKfnkKG7Qgjtq50gKfO56hJv88OfcGb70Q==", - "requires": { - "minimatch": "^5.0.1" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "devOptional": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", - "dev": true - }, - "focus-trap": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-6.7.3.tgz", - "integrity": "sha512-8xCEKndV4KrseGhFKKKmczVA14yx1/hnmFICPOjcFjToxCJYj/NHH43tPc3YE/PLnLRNZoFug0EcWkGQde/miQ==", - "optional": true, - "requires": { - "tabbable": "^5.2.1" - } - }, - "follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" - }, - "fork-ts-checker-webpack-plugin": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz", - "integrity": "sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@types/json-schema": "^7.0.5", - "chalk": "^4.1.0", - "chokidar": "^3.4.2", - "cosmiconfig": "^6.0.0", - "deepmerge": "^4.2.2", - "fs-extra": "^9.0.0", - "glob": "^7.1.6", - "memfs": "^3.1.2", - "minimatch": "^3.0.4", - "schema-utils": "2.7.0", - "semver": "^7.3.2", - "tapable": "^1.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true - }, - "fraction.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", - "dev": true - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true - }, - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "fs-monkey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", - "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "devOptional": true - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", - "dev": true - }, - "gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "dev": true, - "requires": { - "duplexer": "^0.1.2" - } - }, - "handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true - }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "hash-sum": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz", - "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==", - "dev": true - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", - "dev": true - }, - "history": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", - "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", - "requires": { - "@babel/runtime": "^7.1.2", - "loose-envify": "^1.2.0", - "resolve-pathname": "^3.0.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0", - "value-equal": "^1.0.1" - } - }, - "hoist-non-react-statics": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz", - "integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==" - }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "html-entities": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", - "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", - "dev": true - }, - "html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "dev": true, - "requires": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - } - }, - "html-tags": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", - "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==", - "dev": true - }, - "html-webpack-plugin": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", - "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", - "dev": true, - "requires": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" - }, - "dependencies": { - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - } - } - }, - "htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", - "dev": true - }, - "http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - } - }, - "http-parser-js": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz", - "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==", - "dev": true - }, - "http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-middleware": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.4.tgz", - "integrity": "sha512-m/4FxX17SUvz4lJ5WPXOHDUuCwIqXLfLHs1s0uZ3oYjhoXlx9csYxaOa0ElDEJ+h8Q4iJ1s+lTMbiCa4EXIJqg==", - "dev": true, - "requires": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "requires": {} - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true - }, - "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true - }, - "immutable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz", - "integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "requires": { - "loose-envify": "^1.0.0" - } - }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, - "ipaddr.js": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", - "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", - "dev": true - }, - "is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-ci": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", - "dev": true, - "requires": { - "ci-info": "^1.5.0" - } - }, - "is-core-module": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", - "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-file-esm": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-file-esm/-/is-file-esm-1.0.0.tgz", - "integrity": "sha512-rZlaNKb4Mr8WlRu2A9XdeoKgnO5aA53XdPHgCKVyCrQ/rWi89RET1+bq37Ru46obaQXeiX4vmFIm1vks41hoSA==", - "dev": true, - "requires": { - "read-pkg-up": "^7.0.1" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "devOptional": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-shallow-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shallow-equal/-/is-shallow-equal-1.0.1.tgz", - "integrity": "sha512-lq5RvK+85Hs5J3p4oA4256M1FEffzmI533ikeDHvJd42nouRRx5wBzt36JuviiGe5dIPyHON/d0/Up+PBo6XkQ==" - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, + "@vue/reactivity": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.36.tgz", + "integrity": "sha512-c2qvopo0crh9A4GXi2/2kfGYMxsJW4tVILrqRPydVGZHhq0fnzy6qmclWOhBFckEhmyxmpHpdJtIRYGeKcuhnA==", "requires": { - "is-docker": "^2.0.0" + "@vue/shared": "3.2.36" } }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "jake": { - "version": "10.8.5", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", - "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "@vue/reactivity-transform": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.36.tgz", + "integrity": "sha512-Jk5o2BhpODC9XTA7o4EL8hSJ4JyrFWErLtClG3NH8wDS7ri9jBDWxI7/549T7JY9uilKsaNM+4pJASLj5dtRwA==", "requires": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.1", - "minimatch": "^3.0.4" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.36", + "@vue/shared": "3.2.36", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7" } }, - "javascript-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz", - "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==", - "dev": true - }, - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, + "@vue/runtime-core": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.36.tgz", + "integrity": "sha512-PTWBD+Lub+1U3/KhbCExrfxyS14hstLX+cBboxVHaz+kXoiDLNDEYAovPtxeTutbqtClIXtft+wcGdC+FUQ9qQ==", "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "@vue/reactivity": "3.2.36", + "@vue/shared": "3.2.36" } }, - "joi": { - "version": "17.6.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.6.0.tgz", - "integrity": "sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw==", - "dev": true, + "@vue/runtime-dom": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.36.tgz", + "integrity": "sha512-gYPYblm7QXHVuBohqNRRT7Wez0f2Mx2D40rb4fleehrJU9CnkjG0phhcGEZFfGwCmHZRqBCRgbFWE98bPULqkg==", "requires": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", - "@sideway/formula": "^3.0.0", - "@sideway/pinpoint": "^2.0.0" + "@vue/runtime-core": "3.2.36", + "@vue/shared": "3.2.36", + "csstype": "^2.6.8" } }, - "js-message": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz", - "integrity": "sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==", - "dev": true + "@vue/server-renderer": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.36.tgz", + "integrity": "sha512-uZE0+jfye6yYXWvAQYeHZv+f50sRryvy16uiqzk3jn8hEY8zTjI+rzlmZSGoE915k+W/Ol9XSw6vxOUD8dGkUg==", + "requires": { + "@vue/compiler-ssr": "3.2.36", + "@vue/shared": "3.2.36" + } }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "@vue/shared": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.36.tgz", + "integrity": "sha512-JtB41wXl7Au3+Nl3gD16Cfpj7k/6aCroZ6BbOiCMFCMvrOpkg/qQUXTso2XowaNqBbnkuGHurLAqkLBxNGc1hQ==" }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", "dev": true, + "optional": true, + "peer": true, "requires": { - "argparse": "^2.0.1" + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" } }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true, + "optional": true, + "peer": true }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true + "@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true, + "optional": true, + "peer": true }, - "json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", - "dev": true + "@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true, + "optional": true, + "peer": true }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", "dev": true, + "optional": true, + "peer": true, "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" } }, - "jwt-decode": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", - "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==", - "optional": true - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "klona": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", - "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", - "dev": true + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true, + "optional": true, + "peer": true }, - "launch-editor": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.3.0.tgz", - "integrity": "sha512-3QrsCXejlWYHjBPFXTyGNhPj4rrQdB+5+r5r3wArpLH201aR+nWUgw/zKKkTmilCfY/sv6u8qo98pNvtg8LUTA==", + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", "dev": true, + "optional": true, + "peer": true, "requires": { - "picocolors": "^1.0.0", - "shell-quote": "^1.6.1" + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" } }, - "launch-editor-middleware": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/launch-editor-middleware/-/launch-editor-middleware-2.3.0.tgz", - "integrity": "sha512-GJR64trLdFFwCoL9DMn/d1SZX0OzTDPixu4mcfWTShQ4tIqCHCGvlg9fOEYQXyBlrSMQwylsJfUWncheShfV2w==", + "@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", "dev": true, + "optional": true, + "peer": true, "requires": { - "launch-editor": "^2.3.0" + "@xtuc/ieee754": "^1.2.0" } }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", "dev": true, + "optional": true, + "peer": true, "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" + "@xtuc/long": "4.2.2" } }, - "lilconfig": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz", - "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", - "dev": true + "@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true, + "optional": true, + "peer": true }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } }, - "loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", - "dev": true + "@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } }, - "loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", "dev": true, + "optional": true, + "peer": true, "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" } }, - "local-pkg": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.1.tgz", - "integrity": "sha512-lL87ytIGP2FU5PWwNDo0w3WhIo2gopIAxPg9RxDYF7m4rr5ahuZxP22xnJHIvaLTe4Z9P6uKKY2UHiwyB4pcrw==", - "dev": true + "@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "devOptional": true, + "@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "optional": true, + "peer": true, "requires": { - "p-locate": "^4.1.0" + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" } }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" - }, - "lodash.defaultsdeep": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz", - "integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==", - "dev": true - }, - "lodash.kebabcase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", - "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=", - "dev": true - }, - "lodash.mapvalues": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", - "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", - "dev": true + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "optional": true, + "peer": true }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "optional": true, + "peer": true }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", "dev": true }, - "lodash.throttle": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", - "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=" - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true + "acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "optional": true, + "peer": true, + "requires": {} }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } + "requires": {} }, - "log-update": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", - "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", + "acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "cli-cursor": "^2.0.0", - "wrap-ansi": "^3.0.1" + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" }, "dependencies": { - "ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", "dev": true - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", - "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" - } } } }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "requires": { - "tslib": "^2.0.3" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true, - "requires": { - "yallist": "^4.0.0" - } + "optional": true, + "peer": true, + "requires": {} }, - "magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "sourcemap-codec": "^1.4.8" + "color-convert": "^2.0.1" } }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" } }, - "mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "arg": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", + "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==", + "dev": true + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, - "memfs": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz", - "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==", + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "autoprefixer": { + "version": "10.4.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz", + "integrity": "sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==", "dev": true, "requires": { - "fs-monkey": "1.0.3" + "browserslist": "^4.20.3", + "caniuse-lite": "^1.0.30001335", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" } }, - "memoize-one": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", - "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "merge-source-map": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", - "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", - "dev": true, + "axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", "requires": { - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" } }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "browserslist": { + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", + "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", "dev": true, "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" + "caniuse-lite": "^1.0.30001332", + "electron-to-chromium": "^1.4.118", + "escalade": "^3.1.1", + "node-releases": "^2.0.3", + "picocolors": "^1.0.0" } }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "optional": true, + "peer": true + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + "camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true }, - "mime-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mime-match/-/mime-match-1.0.2.tgz", - "integrity": "sha1-P4fDHprxpf1IX7nbE0Qosju7e6g=", - "peer": true, + "caniuse-lite": { + "version": "1.0.30001344", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001344.tgz", + "integrity": "sha512-0ZFjnlCaXNOAYcV7i+TtdKBp0L/3XEU2MF/x6Du1lrh+SRX4IfzIVL4HNJg5pB2PmFb8rszIGyOvsZnqqRoc2g==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { - "wildcard": "^1.1.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "dependencies": { - "wildcard": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz", - "integrity": "sha1-pwIEUwhNjNLv5wup02liY94XEKU=", - "peer": true + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } } } }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "mini-css-extract-plugin": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.0.tgz", - "integrity": "sha512-ndG8nxCEnAemsg4FSgS+yNyHKgkTB4nPKqCOgh65j3/30qqC5RaSQQXMm++Y6sb6E1zRSxPkztj9fqxhS1Eo6w==", + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "requires": { - "schema-utils": "^4.0.0" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" }, "dependencies": { - "ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" + "is-glob": "^4.0.1" } } } }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "optional": true, + "peer": true }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "requires": { - "brace-expansion": "^1.1.7" + "color-name": "~1.1.4" } }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "optional": true, + "peer": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "core-js": { + "version": "3.22.8", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.8.tgz", + "integrity": "sha512-UoGQ/cfzGYIuiq6Z7vWL1HfkE9U9IZ4Ub+0XSiJTCzvbZzgPA69oDF2f+lgJ6dFFLEdjW5O6svvoKzXX23xFkA==" }, - "minipass": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", - "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { - "yallist": "^4.0.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "csstype": { + "version": "2.6.20", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", + "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { - "minimist": "^1.2.6" + "ms": "2.1.2" } }, - "module-alias": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.2.2.tgz", - "integrity": "sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q==", + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "mrmime": { + "defined": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz", - "integrity": "sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ==", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==", "dev": true }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, - "multicast-dns": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", - "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "detective": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", + "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", "dev": true, "requires": { - "dns-packet": "^1.3.1", - "thunky": "^1.0.2" + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" } }, - "multicast-dns-service-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", - "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", "dev": true }, - "mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "requires": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" + "path-type": "^4.0.0" } }, - "namespace-emitter": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/namespace-emitter/-/namespace-emitter-2.0.1.tgz", - "integrity": "sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==", - "peer": true - }, - "nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==" - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", "dev": true }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "requires": { + "jake": "^10.8.5" + } }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "electron-to-chromium": { + "version": "1.4.143", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.143.tgz", + "integrity": "sha512-2hIgvu0+pDfXIqmVmV5X6iwMjQ2KxDsWKwM+oI1fABEOy/Dqmll0QJRmIQ3rm+XaoUa/qKrmy5h7LSTFQ6Ldzg==", "dev": true }, - "no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "enhanced-resolve": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz", + "integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==", "dev": true, + "optional": true, + "peer": true, "requires": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" } }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", "dev": true, - "requires": { - "whatwg-url": "^5.0.0" - } + "optional": true, + "peer": true }, - "node-forge": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.0.tgz", - "integrity": "sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA==", - "dev": true + "esbuild": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.42.tgz", + "integrity": "sha512-V0uPZotCEHokJdNqyozH6qsaQXqmZEOiZWrXnds/zaH/0SyrIayRXWRB98CENO73MIZ9T3HBIOsmds5twWtmgw==", + "dev": true, + "requires": { + "esbuild-android-64": "0.14.42", + "esbuild-android-arm64": "0.14.42", + "esbuild-darwin-64": "0.14.42", + "esbuild-darwin-arm64": "0.14.42", + "esbuild-freebsd-64": "0.14.42", + "esbuild-freebsd-arm64": "0.14.42", + "esbuild-linux-32": "0.14.42", + "esbuild-linux-64": "0.14.42", + "esbuild-linux-arm": "0.14.42", + "esbuild-linux-arm64": "0.14.42", + "esbuild-linux-mips64le": "0.14.42", + "esbuild-linux-ppc64le": "0.14.42", + "esbuild-linux-riscv64": "0.14.42", + "esbuild-linux-s390x": "0.14.42", + "esbuild-netbsd-64": "0.14.42", + "esbuild-openbsd-64": "0.14.42", + "esbuild-sunos-64": "0.14.42", + "esbuild-windows-32": "0.14.42", + "esbuild-windows-64": "0.14.42", + "esbuild-windows-arm64": "0.14.42" + } }, - "node-releases": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", - "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", - "dev": true + "esbuild-android-64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.42.tgz", + "integrity": "sha512-P4Y36VUtRhK/zivqGVMqhptSrFILAGlYp0Z8r9UQqHJ3iWztRCNWnlBzD9HRx0DbueXikzOiwyOri+ojAFfW6A==", + "dev": true, + "optional": true }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "esbuild-android-arm64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.42.tgz", + "integrity": "sha512-0cOqCubq+RWScPqvtQdjXG3Czb3AWI2CaKw3HeXry2eoA2rrPr85HF7IpdU26UWdBXgPYtlTN1LUiuXbboROhg==", "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.42.tgz", + "integrity": "sha512-ipiBdCA3ZjYgRfRLdQwP82rTiv/YVMtW36hTvAN5ZKAIfxBOyPXY7Cejp3bMXWgzKD8B6O+zoMzh01GZsCuEIA==", + "dev": true, + "optional": true }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "esbuild-darwin-arm64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.42.tgz", + "integrity": "sha512-bU2tHRqTPOaoH/4m0zYHbFWpiYDmaA0gt90/3BMEFaM0PqVK/a6MA2V/ypV5PO0v8QxN6gH5hBPY4YJ2lopXgA==", + "dev": true, + "optional": true }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true + "esbuild-freebsd-64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.42.tgz", + "integrity": "sha512-75h1+22Ivy07+QvxHyhVqOdekupiTZVLN1PMwCDonAqyXd8TVNJfIRFrdL8QmSJrOJJ5h8H1I9ETyl2L8LQDaw==", + "dev": true, + "optional": true }, - "normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true + "esbuild-freebsd-arm64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.42.tgz", + "integrity": "sha512-W6Jebeu5TTDQMJUJVarEzRU9LlKpNkPBbjqSu+GUPTHDCly5zZEQq9uHkmHHl7OKm+mQ2zFySN83nmfCeZCyNA==", + "dev": true, + "optional": true }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "esbuild-linux-32": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.42.tgz", + "integrity": "sha512-Ooy/Bj+mJ1z4jlWcK5Dl6SlPlCgQB9zg1UrTCeY8XagvuWZ4qGPyYEWGkT94HUsRi2hKsXvcs6ThTOjBaJSMfg==", "dev": true, - "requires": { - "path-key": "^2.0.0" - }, - "dependencies": { - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - } - } + "optional": true }, - "nprogress": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", - "integrity": "sha1-y480xTIT2JVyP8urkH6UIq28r7E=", + "esbuild-linux-64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.42.tgz", + "integrity": "sha512-2L0HbzQfbTuemUWfVqNIjOfaTRt9zsvjnme6lnr7/MO9toz/MJ5tZhjqrG6uDWDxhsaHI2/nsDgrv8uEEN2eoA==", + "dev": true, "optional": true }, - "nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", + "esbuild-linux-arm": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.42.tgz", + "integrity": "sha512-STq69yzCMhdRaWnh29UYrLSr/qaWMm/KqwaRF1pMEK7kDiagaXhSL1zQGXbYv94GuGY/zAwzK98+6idCMUOOCg==", "dev": true, - "requires": { - "boolbase": "^1.0.0" - } + "optional": true }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "esbuild-linux-arm64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.42.tgz", + "integrity": "sha512-c3Ug3e9JpVr8jAcfbhirtpBauLxzYPpycjWulD71CF6ZSY26tvzmXMJYooQ2YKqDY4e/fPu5K8bm7MiXMnyxuA==", + "dev": true, + "optional": true }, - "object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true + "esbuild-linux-mips64le": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.42.tgz", + "integrity": "sha512-QuvpHGbYlkyXWf2cGm51LBCHx6eUakjaSrRpUqhPwjh/uvNUYvLmz2LgPTTPwCqaKt0iwL+OGVL0tXA5aDbAbg==", + "dev": true, + "optional": true }, - "object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "esbuild-linux-ppc64le": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.42.tgz", + "integrity": "sha512-8ohIVIWDbDT+i7lCx44YCyIRrOW1MYlks9fxTo0ME2LS/fxxdoJBwHWzaDYhjvf8kNpA+MInZvyOEAGoVDrMHg==", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } + "optional": true }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true + "esbuild-linux-riscv64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.42.tgz", + "integrity": "sha512-DzDqK3TuoXktPyG1Lwx7vhaF49Onv3eR61KwQyxYo4y5UKTpL3NmuarHSIaSVlTFDDpcIajCDwz5/uwKLLgKiQ==", + "dev": true, + "optional": true }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "esbuild-linux-s390x": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.42.tgz", + "integrity": "sha512-YFRhPCxl8nb//Wn6SiS5pmtplBi4z9yC2gLrYoYI/tvwuB1jldir9r7JwAGy1Ck4D7sE7wBN9GFtUUX/DLdcEQ==", "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } + "optional": true }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true + "esbuild-netbsd-64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.42.tgz", + "integrity": "sha512-QYSD2k+oT9dqB/4eEM9c+7KyNYsIPgzYOSrmfNGDIyJrbT1d+CFVKvnKahDKNJLfOYj8N4MgyFaU9/Ytc6w5Vw==", + "dev": true, + "optional": true }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "esbuild-openbsd-64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.42.tgz", + "integrity": "sha512-M2meNVIKWsm2HMY7+TU9AxM7ZVwI9havdsw6m/6EzdXysyCFFSoaTQ/Jg03izjCsK17FsVRHqRe26Llj6x0MNA==", "dev": true, - "requires": { - "ee-first": "1.1.1" - } + "optional": true }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true + "esbuild-sunos-64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.42.tgz", + "integrity": "sha512-uXV8TAZEw36DkgW8Ak3MpSJs1ofBb3Smkc/6pZ29sCAN1KzCAQzsje4sUwugf+FVicrHvlamCOlFZIXgct+iqQ==", + "dev": true, + "optional": true }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "esbuild-windows-32": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.42.tgz", + "integrity": "sha512-4iw/8qWmRICWi9ZOnJJf9sYt6wmtp3hsN4TdI5NqgjfOkBVMxNdM9Vt3626G1Rda9ya2Q0hjQRD9W1o+m6Lz6g==", "dev": true, - "requires": { - "wrappy": "1" - } + "optional": true }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "esbuild-windows-64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.42.tgz", + "integrity": "sha512-j3cdK+Y3+a5H0wHKmLGTJcq0+/2mMBHPWkItR3vytp/aUGD/ua/t2BLdfBIzbNN9nLCRL9sywCRpOpFMx3CxzA==", "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } + "optional": true }, - "open": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "esbuild-windows-arm64": { + "version": "0.14.42", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.42.tgz", + "integrity": "sha512-+lRAARnF+hf8J0mN27ujO+VbhPbDqJ8rCcJKye4y7YZLV6C4n3pTRThAb388k/zqF5uM0lS5O201u0OqoWSicw==", "dev": true, - "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - } + "optional": true }, - "opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true }, - "ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "eslint": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.16.0.tgz", + "integrity": "sha512-MBndsoXY/PeVTDJeWsYj7kLZ5hQpJOfMYLsF6LicLHQWbRDG19lK5jOix4DPl8yY4SUFcE3txy86OzFLWT+yoA==", "dev": true, "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" + "@eslint/eslintrc": "^1.3.0", + "@humanwhocodes/config-array": "^0.9.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.2", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", "dev": true, "requires": { - "color-name": "~1.1.4" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" } }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", "dev": true }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } } } }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "devOptional": true, - "requires": { - "p-try": "^2.0.0" - } + "eslint-config-prettier": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", + "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", + "dev": true, + "requires": {} }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "devOptional": true, + "eslint-plugin-prettier": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", + "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", + "dev": true, "requires": { - "p-limit": "^2.2.0" + "prettier-linter-helpers": "^1.0.0" } }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "eslint-plugin-vue": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-8.0.1.tgz", + "integrity": "sha512-h7SJFNECfkx89CeH3VCGGhLcm4VLOsOZ+DUSGk0h/aCqm9Outm/sIkoOvNpCebsb0U+uBzb93v2yZ6k7Vzy6LQ==", "dev": true, "requires": { - "aggregate-error": "^3.0.0" + "eslint-utils": "^3.0.0", + "natural-compare": "^1.4.0", + "semver": "^7.3.5", + "vue-eslint-parser": "^8.0.0" } }, - "p-retry": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz", - "integrity": "sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==", + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "requires": { - "@types/retry": "^0.12.0", - "retry": "^0.13.1" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "devOptional": true - }, - "param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "dev": true, "requires": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" + "eslint-visitor-keys": "^2.0.0" } }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + }, + "espree": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", + "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", "dev": true, "requires": { - "callsites": "^3.0.0" + "acorn": "^8.7.1", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true + } } }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } } }, - "parse5": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", - "dev": true - }, - "parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "requires": { - "parse5": "^6.0.1" + "estraverse": "^5.2.0" }, "dependencies": { - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true } } }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true }, - "pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "devOptional": true + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "optional": true, + "peer": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", "dev": true }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dev": true, "requires": { - "isarray": "0.0.1" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } } }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, - "pinia": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.14.tgz", - "integrity": "sha512-0nPuZR4TetT/WcLN+feMSjWJku3SQU7dBbXC6uw+R6FLQJCsg+/0pzXyD82T1FmAYe0lsx+jnEDQ1BLgkRKlxA==", + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, "requires": { - "@vue/devtools-api": "^6.1.4", - "vue-demi": "*" - }, - "dependencies": { - "vue-demi": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.5.tgz", - "integrity": "sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==", - "requires": {} - } + "reusify": "^1.0.4" } }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "requires": { - "find-up": "^4.0.0" + "flat-cache": "^3.0.4" } }, - "pngjs": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", - "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", - "optional": true - }, - "portfinder": { - "version": "1.0.28", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", - "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", - "dev": true, + "filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", "requires": { - "async": "^2.6.2", - "debug": "^3.1.1", - "mkdirp": "^0.5.5" + "minimatch": "^5.0.1" }, "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", "requires": { - "ms": "^2.1.1" + "brace-expansion": "^2.0.1" } } } }, - "postcss": { - "version": "8.4.13", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.13.tgz", - "integrity": "sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==", - "requires": { - "nanoid": "^3.3.3", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - }, - "postcss-calc": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", - "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "requires": { - "postcss-selector-parser": "^6.0.9", - "postcss-value-parser": "^4.2.0" + "to-regex-range": "^5.0.1" } }, - "postcss-colormin": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.0.tgz", - "integrity": "sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg==", + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, "requires": { - "browserslist": "^4.16.6", - "caniuse-api": "^3.0.0", - "colord": "^2.9.1", - "postcss-value-parser": "^4.2.0" + "flatted": "^3.1.0", + "rimraf": "^3.0.2" } }, - "postcss-convert-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.0.tgz", - "integrity": "sha512-GkyPbZEYJiWtQB0KZ0X6qusqFHUepguBCNFi9t5JJc7I2OTXG7C0twbTLvCfaKOLl3rSXmpAwV7W5txd91V84g==", - "dev": true, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true + }, + "follow-redirects": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "requires": { - "postcss-value-parser": "^4.2.0" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" } }, - "postcss-discard-comments": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.1.tgz", - "integrity": "sha512-5JscyFmvkUxz/5/+TB3QTTT9Gi9jHkcn8dcmmuN68JQcv3aQg4y88yEHHhwFB52l/NkaJ43O0dbksGMAo49nfQ==", - "dev": true, - "requires": {} - }, - "postcss-discard-duplicates": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", - "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", - "dev": true, - "requires": {} + "fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "dev": true }, - "postcss-discard-empty": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", - "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", - "dev": true, - "requires": {} + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true }, - "postcss-discard-overridden": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", - "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, - "requires": {} + "optional": true }, - "postcss-js": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", - "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", - "dev": true, - "requires": { - "camelcase-css": "^2.0.1" - } + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, - "postcss-load-config": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", - "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", - "dev": true, - "requires": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" - } + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "dev": true }, - "postcss-loader": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", - "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "requires": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.5" - }, - "dependencies": { - "cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - } - } + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, - "postcss-merge-longhand": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.3.tgz", - "integrity": "sha512-lX8GPGvZ0iGP/IboM7HXH5JwkXvXod1Rr8H8ixwiA372hArk0zP4ZcCy4z4Prg/bfNlbbTf0KCOjCF9kKnpP/w==", + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "requires": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^5.1.0" + "is-glob": "^4.0.3" } }, - "postcss-merge-rules": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.1.tgz", - "integrity": "sha512-8wv8q2cXjEuCcgpIB1Xx1pIy8/rhMPIQqYKNzEdyx37m6gpq83mQQdCxgIkFgliyEnKvdwJf/C61vN4tQDq4Ww==", + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true, - "requires": { - "browserslist": "^4.16.6", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^3.1.0", - "postcss-selector-parser": "^6.0.5" - } + "optional": true, + "peer": true }, - "postcss-minify-font-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", - "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "globals": { + "version": "13.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", + "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", "dev": true, "requires": { - "postcss-value-parser": "^4.2.0" + "type-fest": "^0.20.2" } }, - "postcss-minify-gradients": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", - "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "requires": { - "colord": "^2.9.1", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" } }, - "postcss-minify-params": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.2.tgz", - "integrity": "sha512-aEP+p71S/urY48HWaRHasyx4WHQJyOYaKpQ6eXl8k0kxg66Wt/30VR6/woh8THgcpRbonJD5IeD+CzNhPi1L8g==", + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true, - "requires": { - "browserslist": "^4.16.6", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - } + "optional": true, + "peer": true }, - "postcss-minify-selectors": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.0.tgz", - "integrity": "sha512-vYxvHkW+iULstA+ctVNx0VoRAR4THQQRkG77o0oa4/mBS0OzGvvzLIvHDv/nNEM0crzN2WIyFU5X7wZhaUK3RA==", + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { - "postcss-selector-parser": "^6.0.5" + "function-bind": "^1.1.1" } }, - "postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "requires": {} - }, - "postcss-modules-local-by-default": { + "has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", - "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true + }, + "immutable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz", + "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "requires": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" } }, - "postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, "requires": { - "postcss-selector-parser": "^6.0.4" + "once": "^1.3.0", + "wrappy": "1" } }, - "postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "requires": { - "icss-utils": "^5.0.0" + "binary-extensions": "^2.0.0" } }, - "postcss-nested": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", - "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", + "is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", "dev": true, "requires": { - "postcss-selector-parser": "^6.0.6" + "has": "^1.0.3" } }, - "postcss-normalize-charset": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", - "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", - "dev": true, - "requires": {} + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true }, - "postcss-normalize-display-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", - "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "requires": { - "postcss-value-parser": "^4.2.0" + "is-extglob": "^2.1.1" } }, - "postcss-normalize-positions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.0.tgz", - "integrity": "sha512-8gmItgA4H5xiUxgN/3TVvXRoJxkAWLW6f/KKhdsH03atg0cB8ilXnrB5PpSshwVu/dD2ZsRFQcR1OEmSBDAgcQ==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true }, - "postcss-normalize-repeat-style": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.0.tgz", - "integrity": "sha512-IR3uBjc+7mcWGL6CtniKNQ4Rr5fTxwkaDHwMBDGGs1x9IVRkYIT/M4NelZWkAOBdV6v3Z9S46zqaKGlyzHSchw==", - "dev": true, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", "requires": { - "postcss-value-parser": "^4.2.0" + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "dependencies": { + "async": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" + } } }, - "postcss-normalize-string": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", - "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, + "optional": true, + "peer": true, "requires": { - "postcss-value-parser": "^4.2.0" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" } }, - "postcss-normalize-timing-functions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", - "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "requires": { - "postcss-value-parser": "^4.2.0" + "argparse": "^2.0.1" } }, - "postcss-normalize-unicode": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.0.tgz", - "integrity": "sha512-J6M3MizAAZ2dOdSjy2caayJLQT8E8K9XjLce8AUQMwOrCvjCHv24aLC/Lps1R1ylOfol5VIDMaM/Lo9NGlk1SQ==", + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true, - "requires": { - "browserslist": "^4.16.6", - "postcss-value-parser": "^4.2.0" - } + "optional": true, + "peer": true }, - "postcss-normalize-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", - "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "requires": { - "normalize-url": "^6.0.1", - "postcss-value-parser": "^4.2.0" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" } }, - "postcss-normalize-whitespace": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", - "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "lilconfig": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz", + "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", + "dev": true + }, + "loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } + "optional": true, + "peer": true }, - "postcss-ordered-values": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.1.tgz", - "integrity": "sha512-7lxgXF0NaoMIgyihL/2boNAEZKiW0+HkMhdKMTD93CjW8TdCy2hSdj8lsAo+uwm7EDG16Da2Jdmtqpedl0cMfw==", + "local-pkg": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.1.tgz", + "integrity": "sha512-lL87ytIGP2FU5PWwNDo0w3WhIo2gopIAxPg9RxDYF7m4rr5ahuZxP22xnJHIvaLTe4Z9P6uKKY2UHiwyB4pcrw==", + "dev": true + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" + "yallist": "^4.0.0" } }, - "postcss-reduce-initial": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.0.tgz", - "integrity": "sha512-5OgTUviz0aeH6MtBjHfbr57tml13PuedK/Ecg8szzd4XRMbYxH4572JFG067z+FqBIf6Zp/d+0581glkvvWMFw==", - "dev": true, + "magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", "requires": { - "browserslist": "^4.16.6", - "caniuse-api": "^3.0.0" + "sourcemap-codec": "^1.4.8" } }, - "postcss-reduce-transforms": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", - "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } + "optional": true, + "peer": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true }, - "postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" + "braces": "^3.0.2", + "picomatch": "^2.3.1" } }, - "postcss-svgo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", - "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", - "dev": true, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "requires": { - "postcss-value-parser": "^4.2.0", - "svgo": "^2.7.0" + "mime-db": "1.52.0" } }, - "postcss-unique-selectors": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", - "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", - "dev": true, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "requires": { - "postcss-selector-parser": "^6.0.5" + "brace-expansion": "^1.1.7" } }, - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, - "preact": { - "version": "10.7.1", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.7.1.tgz", - "integrity": "sha512-MufnRFz39aIhs9AMFisonjzTud1PK1bY+jcJLo6m2T9Uh8AqjD77w11eAAawmjUogoGOnipECq7e/1RClIKsxg==" - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "prettier": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz", - "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==", + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } + "optional": true, + "peer": true }, - "pretty-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", - "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", - "dev": true, - "requires": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" - } + "node-releases": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", + "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==", + "dev": true }, - "prismjs": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.28.0.tgz", - "integrity": "sha512-8aaXdYvl1F7iC7Xm1spqSaY/OJBpYW3v+KJ+F17iYxvdc8sfjW194COK5wVhMZX45tGteiBQgdvD/nhxcRwylw==" + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", "dev": true }, - "progress-webpack-plugin": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/progress-webpack-plugin/-/progress-webpack-plugin-1.0.12.tgz", - "integrity": "sha512-b0dMK6D7pFicDzSdh+sU0p/gp3n5QAGwjPbgacmYB/eVQpayzf9lKTQLYMnTAbk69fKoXSoVNl/+IkobJblL1A==", - "dev": true, - "requires": { - "chalk": "^2.1.0", - "figures": "^2.0.0", - "log-update": "^2.1.0" - } + "object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true }, - "prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" + "wrappy": "1" } }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", "dev": true, "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "dependencies": { - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true - } + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" } }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "callsites": "^3.0.0" } }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true }, - "qrcode": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.0.tgz", - "integrity": "sha512-9MgRpgVc+/+47dFvQeD6U2s0Z92EsKzcHogtum4QB+UNd025WOJSHvn/hjk9xmzj7Stj95CyUAs31mrjxliEsQ==", - "optional": true, - "requires": { - "dijkstrajs": "^1.0.1", - "encode-utf8": "^1.0.3", - "pngjs": "^5.0.0", - "yargs": "^15.3.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "optional": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "optional": true - }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "optional": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "optional": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "optional": true - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "optional": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "optional": true - }, - "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "optional": true, - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - } - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "optional": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, - "raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", - "dev": true, + "pinia": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.14.tgz", + "integrity": "sha512-0nPuZR4TetT/WcLN+feMSjWJku3SQU7dBbXC6uw+R6FLQJCsg+/0pzXyD82T1FmAYe0lsx+jnEDQ1BLgkRKlxA==", "requires": { - "bytes": "3.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "@vue/devtools-api": "^6.1.4", + "vue-demi": "*" }, "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true + "vue-demi": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.1.tgz", + "integrity": "sha512-xmkJ56koG3ptpLnpgmIzk9/4nFf4CqduSJbUM0OdPoU87NwRuZ6x49OLhjSa/fC15fV+5CbEnrxU4oyE022svg==", + "requires": {} } } }, - "react": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", - "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2" - } - }, - "react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - } - }, - "react-interactive": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/react-interactive/-/react-interactive-0.8.3.tgz", - "integrity": "sha512-mmRvA9aKP7zu9kVfP1AX1egX8tFlnE3DDXq92z0JTZezfOpmeQBzr77O1+mTV54OOmn+M2t6c5kFD5VnuFoM7A==", - "requires": { - "detect-it": "^3.0.3", - "object-assign": "^4.1.1", - "prop-types": "^15.6.0" - } - }, - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "react-router": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz", - "integrity": "sha512-yrvL8AogDh2X42Dt9iknk4wF4V8bWREPirFfS9gLU1huk6qK41sg7Z/1S81jjTrGHxa3B8R3J6xIkDAA6CVarg==", - "requires": { - "history": "^4.7.2", - "hoist-non-react-statics": "^2.5.0", - "invariant": "^2.2.4", - "loose-envify": "^1.3.1", - "path-to-regexp": "^1.7.0", - "prop-types": "^15.6.1", - "warning": "^4.0.1" - } - }, - "react-router-dom": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-4.3.1.tgz", - "integrity": "sha512-c/MlywfxDdCp7EnB7YfPMOfMD3tOtIjrQlj/CKfNMBxdmpJP8xcz5P/UAFn3JbnQCNUxsHyVVqllF9LhgVyFCA==", + "postcss": { + "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", "requires": { - "history": "^4.7.2", - "invariant": "^2.2.4", - "loose-envify": "^1.3.1", - "prop-types": "^15.6.1", - "react-router": "^4.3.1", - "warning": "^4.0.1" + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" } }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "postcss-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", + "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", "dev": true, "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" + "camelcase-css": "^2.0.1" } }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", "dev": true, "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "dependencies": { - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" } }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "postcss-nested": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", + "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", "dev": true, "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "postcss-selector-parser": "^6.0.6" } }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", "dev": true, "requires": { - "picomatch": "^2.2.1" + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" } }, - "regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, - "regenerate-unicode-properties": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", - "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", - "dev": true, - "requires": { - "regenerate": "^1.4.2" - } + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true }, - "regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "prettier": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz", + "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==", + "dev": true }, - "regenerator-transform": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", - "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, "requires": { - "@babel/runtime": "^7.8.4" + "fast-diff": "^1.1.2" } }, - "regexp.prototype.flags": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz", - "integrity": "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } + "prismjs": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.28.0.tgz", + "integrity": "sha512-8aaXdYvl1F7iC7Xm1spqSaY/OJBpYW3v+KJ+F17iYxvdc8sfjW194COK5wVhMZX45tGteiBQgdvD/nhxcRwylw==" }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, - "regexpu-core": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz", - "integrity": "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==", - "dev": true, - "requires": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.0.1", - "regjsgen": "^0.6.0", - "regjsparser": "^0.8.2", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.0.0" - } - }, - "regjsgen": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", - "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==", + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", "dev": true }, - "regjsparser": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", - "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, + "optional": true, + "peer": true, "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } + "safe-buffer": "^5.1.0" } }, - "relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", - "dev": true - }, - "renderkid": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", - "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "requires": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" + "picomatch": "^2.2.1" } }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "devOptional": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "optional": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, "resolve": { @@ -21966,27 +6333,6 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, - "resolve-pathname": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", - "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true - }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -22003,9 +6349,9 @@ } }, "rollup": { - "version": "2.70.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.70.1.tgz", - "integrity": "sha512-CRYsI5EuzLbXdxC6RnYhOuRdtz4bhejPMSWjsFLfVM/7w/85n2szZv6yExqUXsBdz5KT8eoubeyDUDjhLHEslA==", + "version": "2.75.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.75.5.tgz", + "integrity": "sha512-JzNlJZDison3o2mOxVmb44Oz7t74EfSd1SQrplQk0wSaXV7uLQXtVdHbxlcT3w+8tZ1TL4r/eLfc7nAbz38BBA==", "dev": true, "requires": { "fsevents": "~2.3.2" @@ -22021,16 +6367,12 @@ } }, "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "optional": true, + "peer": true }, "sass": { "version": "1.52.1", @@ -22043,41 +6385,19 @@ "source-map-js": ">=0.6.2 <2.0.0" } }, - "scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, "schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", "dev": true, + "optional": true, + "peer": true, "requires": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } }, - "select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", - "dev": true - }, - "selfsigned": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.1.tgz", - "integrity": "sha512-LmME957M1zOsUhG+67rAjKfiWFox3SBxE/yymatMZsAx+oMrJ0YQ8AToOnyCm7xbeg2ep37IHLxdu0o2MavQOQ==", - "dev": true, - "requires": { - "node-forge": "^1" - } - }, "semver": { "version": "7.3.7", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", @@ -22087,155 +6407,17 @@ "lru-cache": "^6.0.0" } }, - "send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", - "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "1.8.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - } - } - }, "serialize-javascript": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, + "optional": true, + "peer": true, "requires": { "randombytes": "^2.1.0" } }, - "serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - } - } - }, - "serve-static": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", - "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.2" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "optional": true - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "shallow-equal": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz", - "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==" - }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -22251,249 +6433,63 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, - "shell-quote": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", - "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", - "dev": true - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "sirv": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.19.tgz", - "integrity": "sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==", - "dev": true, - "requires": { - "@polka/url": "^1.0.0-next.20", - "mrmime": "^1.0.0", - "totalist": "^1.0.0" - } - }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, - "sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, - "requires": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", - "dev": true - }, - "spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - } - }, - "spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, - "requires": { - "minipass": "^3.1.1" - } - }, - "stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "dev": true - }, - "stackframe": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.1.tgz", - "integrity": "sha512-h88QkzREN/hy8eRdyNhhsO7RSJ5oyTqxxmmn0dzBIMUclZsjpfmrsg81vp8mjjAs2vAZ72nyWxRUwSwmh0e4xg==", - "dev": true + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, + "optional": true, + "peer": true, "requires": { - "safe-buffer": "~5.2.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "devOptional": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "devOptional": true, + "dev": true, "requires": { "ansi-regex": "^5.0.1" } }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", - "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", - "dev": true - }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, - "strnum": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", - "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" - }, - "stylehacks": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.0.tgz", - "integrity": "sha512-SzLmvHQTrIWfSgljkQCw2++C9+Ne91d/6Sp92I8c5uHTcy/PgeHamwITIbBW9wnFTY/3ZfSXR9HIL6Ikqmcu6Q==", - "dev": true, - "requires": { - "browserslist": "^4.16.6", - "postcss-selector-parser": "^6.0.4" - } - }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "optional": true, + "peer": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } }, "supports-preserve-symlinks-flag": { @@ -22502,41 +6498,6 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, - "svg-tags": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=", - "dev": true - }, - "svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", - "dev": true, - "requires": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - } - } - }, - "tabbable": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.2.1.tgz", - "integrity": "sha512-40pEZ2mhjaZzK0BnI+QGNjJO8UYx9pP5v7BGe17SORTO0OEuuaAwQTkAp8whcZvqon44wKFOikD+Al11K3JICQ==", - "optional": true - }, "tailwindcss": { "version": "3.0.24", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.24.tgz", @@ -22564,46 +6525,28 @@ "postcss-value-parser": "^4.2.0", "quick-lru": "^5.1.1", "resolve": "^1.22.0" - }, - "dependencies": { - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } } }, "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "optional": true, + "peer": true }, "terser": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.1.tgz", - "integrity": "sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==", + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.0.tgz", + "integrity": "sha512-JC6qfIEkPBd9j1SMO3Pfn+A6w2kQV54tv+ABQLgZr7dA3k/DL/OBoYSWxzVpZev3J+bUHXfr55L8Mox7AaNo6g==", "dev": true, + "optional": true, + "peer": true, "requires": { + "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.7.2", "source-map-support": "~0.5.20" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } } }, "terser-webpack-plugin": { @@ -22611,31 +6554,14 @@ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz", "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==", "dev": true, + "optional": true, + "peer": true, "requires": { "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.0", "source-map": "^0.6.1", "terser": "^5.7.2" - }, - "dependencies": { - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } } }, "text-table": { @@ -22644,88 +6570,6 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "requires": { - "any-promise": "^1.0.0" - } - }, - "thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", - "dev": true, - "requires": { - "thenify": ">= 3.1.0 < 4" - } - }, - "thread-loader": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/thread-loader/-/thread-loader-3.0.4.tgz", - "integrity": "sha512-ByaL2TPb+m6yArpqQUZvP+5S1mZtXsEP7nWKKlAUTm7fCml8kB5s1uI3+eHRP2bk5mVYfRSBI7FFf+tWEyLZwA==", - "dev": true, - "requires": { - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.1.0", - "loader-utils": "^2.0.0", - "neo-async": "^2.6.2", - "schema-utils": "^3.0.0" - }, - "dependencies": { - "loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true - }, - "tiny-invariant": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", - "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==" - }, - "tiny-warning": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", - "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" - }, - "tinycolor2": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz", - "integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==" - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -22735,96 +6579,10 @@ "is-number": "^7.0.0" } }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true - }, - "totalist": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", - "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==", - "dev": true - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true - }, - "ts-loader": { - "version": "9.2.8", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.8.tgz", - "integrity": "sha512-gxSak7IHUuRtwKf3FIPSW1VpZcqF9+MBrHOvBp9cjHh+525SjtCIJKVGjRKIAfxBwDGDGCFF00rTfzB1quxdSw==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "ts-results": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/ts-results/-/ts-results-3.3.0.tgz", - "integrity": "sha512-FWqxGX2NHp5oCyaMd96o2y2uMQmSu8Dey6kvyuFdRJ2AzfmWo3kWa4UsPlCGlfQ/qu03m09ZZtppMoY8EMHuiA==" - }, "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, "tsutils": { @@ -22834,14 +6592,6 @@ "dev": true, "requires": { "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } } }, "type-check": { @@ -22854,77 +6604,17 @@ } }, "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, "typescript": { "version": "4.7.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.2.tgz", "integrity": "sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A==", "devOptional": true }, - "unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", - "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", - "dev": true - }, - "unicode-property-aliases-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", - "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", - "dev": true - }, - "universal-cookie": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-4.0.4.tgz", - "integrity": "sha512-lbRVHoOMtItjWbM7TwDLdl8wug7izB0tq3/YVKhT/ahB4VDvWMyvnADfnJI8y6fSvsjh51Ix7lTGC6Tn4rMPhw==", - "optional": true, - "requires": { - "@types/cookie": "^0.3.3", - "cookie": "^0.4.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, "unplugin": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-0.6.3.tgz", @@ -22964,18 +6654,18 @@ } }, "magic-string": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.1.tgz", - "integrity": "sha512-ndThHmvgtieXe8J/VGPjG+Apu7v7ItcD5mhEIvOscWjPF/ccOiLxHaSuCAS2G+3x4GKsAbT8u7zdyamupui8Tg==", + "version": "0.26.2", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.2.tgz", + "integrity": "sha512-NzzlXpclt5zAbmo6h6jNc8zl2gNRGHvmsZW4IvZhTC4W7k4OlLP+S5YLussa/r3ixNT66KOQfNORlXHSOy/X4A==", "dev": true, "requires": { "sourcemap-codec": "^1.4.8" } }, "minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -22998,51 +6688,12 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", - "dev": true - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - }, "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "value-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", - "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true - }, "vite": { "version": "2.9.9", "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.9.tgz", @@ -23076,108 +6727,56 @@ "@vue/shared": "3.2.36" } }, - "vue-axios": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/vue-axios/-/vue-axios-3.4.1.tgz", - "integrity": "sha512-8YZYUOQrBEJktxoQtrM4rr2LfVcDaWfJqv8MqtLlgLlkuBvCYKFSZSo6AXQ4YcCzdgccDqstmuaEh68lcH9xWA==", - "requires": {} - }, "vue-class-component": { "version": "8.0.0-rc.1", "resolved": "https://registry.npmjs.org/vue-class-component/-/vue-class-component-8.0.0-rc.1.tgz", "integrity": "sha512-w1nMzsT/UdbDAXKqhwTmSoyuJzUXKrxLE77PCFVuC6syr8acdFDAq116xgvZh9UCuV0h+rlCtxXolr3Hi3HyPQ==", "requires": {} }, - "vue-color-kit": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/vue-color-kit/-/vue-color-kit-1.0.5.tgz", - "integrity": "sha512-PUQzqdpI7672YYuoHdTLENHldieVMis0u9g2n7NAxiLGdiaqCD/QaYtbDOvtASpN5oSIfKxQgPV+i45MOlkKnw==", - "requires": {} - }, - "vue-final-modal": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/vue-final-modal/-/vue-final-modal-3.4.4.tgz", - "integrity": "sha512-4nOLU+cMcUqAT0kg+64+Hi96kkQPOph2LOJa7Fl58BXlTyhfRxaMuz3M91wi2ooMIL4poWA8428P5GIAXSpuZg==" - }, - "vue-hot-reload-api": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", - "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==", - "dev": true - }, - "vue-loader": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-17.0.0.tgz", - "integrity": "sha512-OWSXjrzIvbF2LtOUmxT3HYgwwubbfFelN8PAP9R9dwpIkj48TVioHhWWSx7W7fk+iF5cgg3CBJRxwTdtLU4Ecg==", + "vue-eslint-parser": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz", + "integrity": "sha512-dzHGG3+sYwSf6zFBa0Gi9ZDshD7+ad14DGOdTLjruRVgZXe2J+DcZ9iUhyR48z5g1PqRa20yt3Njna/veLJL/g==", "dev": true, "requires": { - "chalk": "^4.1.0", - "hash-sum": "^2.0.0", - "loader-utils": "^2.0.0" + "debug": "^4.3.2", + "eslint-scope": "^7.0.0", + "eslint-visitor-keys": "^3.1.0", + "espree": "^9.0.0", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.5" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", "dev": true, "requires": { - "color-name": "~1.1.4" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" } }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", "dev": true }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true - }, - "loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } } } }, + "vue-final-modal": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/vue-final-modal/-/vue-final-modal-3.4.4.tgz", + "integrity": "sha512-4nOLU+cMcUqAT0kg+64+Hi96kkQPOph2LOJa7Fl58BXlTyhfRxaMuz3M91wi2ooMIL4poWA8428P5GIAXSpuZg==" + }, "vue-meta": { "version": "3.0.0-alpha.10", "resolved": "https://registry.npmjs.org/vue-meta/-/vue-meta-3.0.0-alpha.10.tgz", @@ -23198,44 +6797,13 @@ "@vue/devtools-api": "^6.0.0" } }, - "vue-style-loader": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz", - "integrity": "sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==", + "vue-tsc": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-0.35.2.tgz", + "integrity": "sha512-aqY16VlODHzqtKGUkqdumNpH+s5ABCkufRyvMKQlL/mua+N2DfSVnHufzSNNUMr7vmOO0YsNg27jsspBMq4iGA==", "dev": true, "requires": { - "hash-sum": "^1.0.2", - "loader-utils": "^1.0.2" - }, - "dependencies": { - "hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", - "dev": true - } - } - }, - "vue-template-es2015-compiler": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", - "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", - "dev": true - }, - "vue3-cookies": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/vue3-cookies/-/vue3-cookies-1.0.6.tgz", - "integrity": "sha512-a1UvVD0qIgxyOqjlSOwnLnqAnz8ASltugEv8yX+96i/WGZAN9fEDci7xO4HIWZE1uToUnRq9JnFhvfDCSo45OA==", - "requires": { - "vue": "^3.0.0" - } - }, - "warning": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", - "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", - "requires": { - "loose-envify": "^1.0.0" + "@volar/vue-typescript": "0.35.2" } }, "watchpack": { @@ -23243,40 +6811,20 @@ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", "dev": true, + "optional": true, + "peer": true, "requires": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" } }, - "wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "requires": { - "minimalistic-assert": "^1.0.0" - } - }, - "wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "dev": true, - "requires": { - "defaults": "^1.0.3" - } - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true - }, "webpack": { - "version": "5.70.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz", - "integrity": "sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==", + "version": "5.72.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.1.tgz", + "integrity": "sha512-dXG5zXCLspQR4krZVR6QgajnZOjW2K/djHvdcRaDQvsjV9z9vaW6+ja5dZOYbqBBjF6kGXka/2ZyxNdc+8Jung==", "dev": true, + "optional": true, + "peer": true, "requires": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^0.0.51", @@ -23287,13 +6835,13 @@ "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.9.2", + "enhanced-resolve": "^5.9.3", "es-module-lexer": "^0.9.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.9", - "json-parse-better-errors": "^1.0.2", + "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", @@ -23302,282 +6850,6 @@ "terser-webpack-plugin": "^5.1.3", "watchpack": "^2.3.1", "webpack-sources": "^3.2.3" - }, - "dependencies": { - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - } - } - }, - "webpack-bundle-analyzer": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz", - "integrity": "sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ==", - "dev": true, - "requires": { - "acorn": "^8.0.4", - "acorn-walk": "^8.0.0", - "chalk": "^4.1.0", - "commander": "^7.2.0", - "gzip-size": "^6.0.0", - "lodash": "^4.17.20", - "opener": "^1.5.2", - "sirv": "^1.0.7", - "ws": "^7.3.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "webpack-chain": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-6.5.1.tgz", - "integrity": "sha512-7doO/SRtLu8q5WM0s7vPKPWX580qhi0/yBHkOxNkv50f6qB76Zy9o2wRTrrPULqYTvQlVHuvbA8v+G5ayuUDsA==", - "dev": true, - "requires": { - "deepmerge": "^1.5.2", - "javascript-stringify": "^2.0.1" - }, - "dependencies": { - "deepmerge": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz", - "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==", - "dev": true - } - } - }, - "webpack-dev-middleware": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz", - "integrity": "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==", - "dev": true, - "requires": { - "colorette": "^2.0.10", - "memfs": "^3.4.1", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - } - } - } - }, - "webpack-dev-server": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz", - "integrity": "sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A==", - "dev": true, - "requires": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.2.2", - "ansi-html-community": "^0.0.8", - "bonjour": "^3.5.0", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^1.6.0", - "default-gateway": "^6.0.3", - "del": "^6.0.0", - "express": "^4.17.1", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.0", - "ipaddr.js": "^2.0.1", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "portfinder": "^1.0.28", - "schema-utils": "^4.0.0", - "selfsigned": "^2.0.0", - "serve-index": "^1.9.1", - "sockjs": "^0.3.21", - "spdy": "^4.0.2", - "strip-ansi": "^7.0.0", - "webpack-dev-middleware": "^5.3.1", - "ws": "^8.4.2" - }, - "dependencies": { - "ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - } - }, - "strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "dev": true, - "requires": {} - } - } - }, - "webpack-merge": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", - "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" } }, "webpack-sources": { @@ -23592,39 +6864,6 @@ "integrity": "sha512-5NUqC2JquIL2pBAAo/VfBP6KuGkHIZQXW/lNKupLPfhViwh8wNsu0BObtl09yuKZszeEUfbXz8xhrHvSG16Nqw==", "dev": true }, - "websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "requires": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - } - }, - "websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true - }, - "whatwg-fetch": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", - "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==", - "dev": true - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dev": true, - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -23634,92 +6873,24 @@ "isexe": "^2.0.0" } }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "optional": true - }, - "wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true - }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } - } - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, - "ws": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", - "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", - "dev": true, - "requires": {} - }, - "xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "dev": true - }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -23731,119 +6902,6 @@ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true - }, - "yorkie": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yorkie/-/yorkie-2.0.0.tgz", - "integrity": "sha512-jcKpkthap6x63MB4TxwCyuIGkV0oYP/YRyuQU5UO0Yz/E/ZAu+653/uov+phdmO54n6BcvFRyyt0RRrWdN2mpw==", - "dev": true, - "requires": { - "execa": "^0.8.0", - "is-ci": "^1.0.10", - "normalize-path": "^1.0.0", - "strip-indent": "^2.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "execa": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", - "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "normalize-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz", - "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=", - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - } - } } } } diff --git a/frontend/package.json b/frontend/package.json index 3d88427e..c70c0220 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,57 +1,47 @@ { - "name": "site", - "version": "1.0.1", + "name": "nitro_repo-frontend", + "version": "1.1.0-SNAPSHOT", "private": true, "scripts": { "dev": "vite", - "build": "vite build", - "full-build": "npm install && vite build", - "serve": "vite preview" + "build": "vue-tsc --noEmit && vite build", + "preview": "vite preview", + "lint": "eslint src/**/*.{ts,vue}" }, "dependencies": { "@kyvg/vue3-notification": "^2.3.4", - "@nitro_repo/nitro_repo-api-wrapper": "file:../nitro_repo-api-wrapper", - "@uppy/drag-drop": "^2.1.1", - "@uppy/vue": "^0.4.8", + "@rushstack/eslint-patch": "^1.1.3", + "@types/webpack-env": "^1.17.0", "axios": "^0.27.2", - "boxicons": "^2.1.2", - "core-js": "^3.22.7", - "equal-vue": "^0.79.3", - "fast-xml-parser": "^4.0.8", + "core-js": "^3.22.8", "pinia": "^2.0.14", "prismjs": "^1.28.0", "vite-plugin-ejs": "^1.4.4", "vue": "^3.2.36", - "vue-axios": "^3.4.1", "vue-class-component": "^8.0.0-0", - "vue-color-kit": "^1.0.5", - "vue-final-modal": "^3.4.3", + "vue-final-modal": "^3.4.4", "vue-meta": "3.0.0-alpha.10", "vue-prism-editor": "^2.0.0-alpha.2", - "vue-router": "^4.0.15", - "vue3-cookies": "^1.0.6", - "ts-results": "3.3.0" + "vue-router": "^4.0.15" }, "devDependencies": { - "@typescript-eslint/eslint-plugin": "^5.27.0", - "@typescript-eslint/parser": "^5.27.0", + "@types/prismjs": "^1.26.0", + "@typescript-eslint/eslint-plugin": "5.27.0", + "@typescript-eslint/parser": "5.27.0", "@vitejs/plugin-vue": "^2.3.3", - "@vue/cli-plugin-babel": "~5.0.4", - "@vue/cli-plugin-eslint": "~5.0.4", - "@vue/cli-plugin-router": "~5.0.4", - "@vue/cli-plugin-typescript": "~5.0.4", - "@vue/cli-plugin-vuex": "~5.0.4", - "@vue/cli-service": "~5.0.4", - "@vue/compiler-sfc": "^3.2.36", - "@vue/eslint-config-prettier": "^7.0.0", - "eslint": "^8.16.0", - "eslint-plugin-prettier": "^4.0.0", - "eslint-plugin-vue": "^9.0.1", + "@vue/eslint-config-prettier": "7.0.0", + "@vue/eslint-config-typescript": "10.0.0", + "autoprefixer": "^10.4.7", + "eslint": "8.16.0", + "eslint-plugin-prettier": "4.0.0", + "eslint-plugin-vue": "8.0.1", + "postcss": "^8.4.14", "prettier": "2.6.2", "sass": "^1.52.1", "tailwindcss": "^3.0.24", "typescript": "~4.7.2", "unplugin-vue-components": "^0.19.6", - "vite": "^2.9.9" + "vite": "^2.9.9", + "vue-tsc": "^0.35.2" } -} \ No newline at end of file +} diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 526b7672..aa498f9c 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -1,5 +1,4 @@ - diff --git a/frontend/src/api/repository/BadgeGen.ts b/frontend/src/api/repository/BadgeGen.ts index b6c34fb6..dc12e3fa 100644 --- a/frontend/src/api/repository/BadgeGen.ts +++ b/frontend/src/api/repository/BadgeGen.ts @@ -24,6 +24,7 @@ export function createBadgeSnippets( }, ]; } + export function createProjectSnippet( storage: string, repository: string, diff --git a/frontend/src/components/ArtifactSearch.vue b/frontend/src/components/ArtifactSearch.vue new file mode 100644 index 00000000..fde4cf38 --- /dev/null +++ b/frontend/src/components/ArtifactSearch.vue @@ -0,0 +1,48 @@ + + diff --git a/frontend/src/components/CreateRepo.vue b/frontend/src/components/CreateRepo.vue deleted file mode 100644 index f693c4b5..00000000 --- a/frontend/src/components/CreateRepo.vue +++ /dev/null @@ -1,127 +0,0 @@ - - - - diff --git a/frontend/src/components/CreateStorage.vue b/frontend/src/components/CreateStorage.vue deleted file mode 100644 index ce028ccd..00000000 --- a/frontend/src/components/CreateStorage.vue +++ /dev/null @@ -1,108 +0,0 @@ - - - - diff --git a/frontend/src/components/CreateUser.vue b/frontend/src/components/CreateUser.vue deleted file mode 100644 index b28197c5..00000000 --- a/frontend/src/components/CreateUser.vue +++ /dev/null @@ -1,171 +0,0 @@ - - - diff --git a/frontend/src/components/Me.vue b/frontend/src/components/Me.vue deleted file mode 100644 index d0bc1b07..00000000 --- a/frontend/src/components/Me.vue +++ /dev/null @@ -1,68 +0,0 @@ - - - - diff --git a/frontend/src/components/Repositories.vue b/frontend/src/components/Repositories.vue deleted file mode 100644 index ba36f00e..00000000 --- a/frontend/src/components/Repositories.vue +++ /dev/null @@ -1,72 +0,0 @@ - - - diff --git a/frontend/src/components/Storages.vue b/frontend/src/components/Storages.vue deleted file mode 100644 index 28acfa3e..00000000 --- a/frontend/src/components/Storages.vue +++ /dev/null @@ -1,64 +0,0 @@ - - - diff --git a/frontend/src/components/UpdateStorage.vue b/frontend/src/components/UpdateStorage.vue deleted file mode 100644 index 0128e144..00000000 --- a/frontend/src/components/UpdateStorage.vue +++ /dev/null @@ -1,97 +0,0 @@ - - diff --git a/frontend/src/components/UpdateUser.vue b/frontend/src/components/UpdateUser.vue deleted file mode 100644 index 3154d504..00000000 --- a/frontend/src/components/UpdateUser.vue +++ /dev/null @@ -1,47 +0,0 @@ - - - diff --git a/frontend/src/components/Users.vue b/frontend/src/components/Users.vue deleted file mode 100644 index 45a1b599..00000000 --- a/frontend/src/components/Users.vue +++ /dev/null @@ -1,67 +0,0 @@ - - - - diff --git a/frontend/src/components/browse/BrowseBox.vue b/frontend/src/components/browse/BrowseBox.vue deleted file mode 100644 index bc67613b..00000000 --- a/frontend/src/components/browse/BrowseBox.vue +++ /dev/null @@ -1,98 +0,0 @@ - - - diff --git a/frontend/src/components/common/code/CodeCard.vue b/frontend/src/components/common/code/CodeCard.vue index c2a76b41..8f906bf9 100644 --- a/frontend/src/components/common/code/CodeCard.vue +++ b/frontend/src/components/common/code/CodeCard.vue @@ -31,7 +31,8 @@ export default defineComponent({ highlighter: (code: string) => prism.highlight( code, - prism.languages[props.snippetInfo.lang] ?? prism.languages.js + prism.languages[props.snippetInfo.lang] ?? prism.languages.js, + props.snippetInfo.lang ), ...props.snippetInfo, })); diff --git a/frontend/src/components/common/code/CodeMenu.vue b/frontend/src/components/common/code/CodeMenu.vue index b024a219..ef7d5dc0 100644 --- a/frontend/src/components/common/code/CodeMenu.vue +++ b/frontend/src/components/common/code/CodeMenu.vue @@ -23,7 +23,7 @@ diff --git a/frontend/src/components/nav/Login.vue b/frontend/src/components/nav/Login.vue index b22b06c1..8b84f861 100644 --- a/frontend/src/components/nav/Login.vue +++ b/frontend/src/components/nav/Login.vue @@ -1,6 +1,13 @@ @@ -12,8 +19,8 @@ diff --git a/frontend/src/components/project/ViewProject.vue b/frontend/src/components/project/ViewProject.vue deleted file mode 100644 index 5c8a7bd0..00000000 --- a/frontend/src/components/project/ViewProject.vue +++ /dev/null @@ -1,43 +0,0 @@ - - - diff --git a/frontend/src/components/project/badge/ProjectBadge.vue b/frontend/src/components/project/badge/ProjectBadge.vue deleted file mode 100644 index 50ad46b7..00000000 --- a/frontend/src/components/project/badge/ProjectBadge.vue +++ /dev/null @@ -1,106 +0,0 @@ - - - - diff --git a/frontend/src/components/project/types/maven/MavenProjectInfo.vue b/frontend/src/components/project/types/maven/MavenProjectInfo.vue deleted file mode 100644 index 2b88b61c..00000000 --- a/frontend/src/components/project/types/maven/MavenProjectInfo.vue +++ /dev/null @@ -1,24 +0,0 @@ - - - diff --git a/frontend/src/components/project/types/maven/copy/MavenProjectCopy.vue b/frontend/src/components/project/types/maven/copy/MavenProjectCopy.vue deleted file mode 100644 index b89aa73d..00000000 --- a/frontend/src/components/project/types/maven/copy/MavenProjectCopy.vue +++ /dev/null @@ -1,76 +0,0 @@ - - - - diff --git a/frontend/src/components/repo/ViewRepo.vue b/frontend/src/components/repo/ViewRepo.vue deleted file mode 100644 index 62edeb47..00000000 --- a/frontend/src/components/repo/ViewRepo.vue +++ /dev/null @@ -1,81 +0,0 @@ - - - diff --git a/frontend/src/components/repo/badge/RepositoryBadge.vue b/frontend/src/components/repo/badge/RepositoryBadge.vue deleted file mode 100644 index 62c1414d..00000000 --- a/frontend/src/components/repo/badge/RepositoryBadge.vue +++ /dev/null @@ -1,53 +0,0 @@ - - - diff --git a/frontend/src/components/repo/types/maven/MavenRepoInfo.vue b/frontend/src/components/repo/types/maven/MavenRepoInfo.vue deleted file mode 100644 index 257233a3..00000000 --- a/frontend/src/components/repo/types/maven/MavenRepoInfo.vue +++ /dev/null @@ -1,45 +0,0 @@ - - - - diff --git a/frontend/src/components/repo/update/DeployRepo.vue b/frontend/src/components/repo/update/DeployRepo.vue deleted file mode 100644 index fa17ab01..00000000 --- a/frontend/src/components/repo/update/DeployRepo.vue +++ /dev/null @@ -1,84 +0,0 @@ - - diff --git a/frontend/src/components/repo/update/FrontendRepo.vue b/frontend/src/components/repo/update/FrontendRepo.vue deleted file mode 100644 index ea4df0ef..00000000 --- a/frontend/src/components/repo/update/FrontendRepo.vue +++ /dev/null @@ -1,170 +0,0 @@ - - diff --git a/frontend/src/components/repo/update/GeneralRepo.vue b/frontend/src/components/repo/update/GeneralRepo.vue deleted file mode 100644 index 4eae84f5..00000000 --- a/frontend/src/components/repo/update/GeneralRepo.vue +++ /dev/null @@ -1,216 +0,0 @@ - - diff --git a/frontend/src/components/repo/update/SecurityRepo.vue b/frontend/src/components/repo/update/SecurityRepo.vue deleted file mode 100644 index 737acefa..00000000 --- a/frontend/src/components/repo/update/SecurityRepo.vue +++ /dev/null @@ -1,62 +0,0 @@ - - - diff --git a/frontend/src/components/repo/update/UpdateRepo.vue b/frontend/src/components/repo/update/UpdateRepo.vue deleted file mode 100644 index fbeefe96..00000000 --- a/frontend/src/components/repo/update/UpdateRepo.vue +++ /dev/null @@ -1,109 +0,0 @@ - - diff --git a/frontend/src/components/upload/MavenUpload.js b/frontend/src/components/upload/MavenUpload.js deleted file mode 100644 index 01d801cb..00000000 --- a/frontend/src/components/upload/MavenUpload.js +++ /dev/null @@ -1,25 +0,0 @@ -import BasePlugin from '@uppy/core/lib/BasePlugin.js' - -class MavenUploader extends BasePlugin { - constructor(uppy, opts) { - super(uppy, opts) - this.id = opts.id || 'MavenUploader' - this.title = "MavenUploader" - this.type = 'maven' - this.prepareUpload = this.prepareUpload.bind(this) // ← this! - - } - prepareUpload (fileIDs) { - console.log(this) // `this` refers to the `MyPlugin` instance. - return Promise.resolve() - } - install() { - this.uppy.addPreProcessor(this.prepareUpload) - - } - - uninstall() { - this.uppy.removePreProcessor(this.prepareUpload) - - } -} \ No newline at end of file diff --git a/frontend/src/components/upload/MavenUpload.vue b/frontend/src/components/upload/MavenUpload.vue deleted file mode 100644 index cc56ff75..00000000 --- a/frontend/src/components/upload/MavenUpload.vue +++ /dev/null @@ -1,193 +0,0 @@ - - - - diff --git a/frontend/src/components/upload/PomCreator.ts b/frontend/src/components/upload/PomCreator.ts deleted file mode 100644 index 22cdba81..00000000 --- a/frontend/src/components/upload/PomCreator.ts +++ /dev/null @@ -1,13 +0,0 @@ -export interface Pom { - project: Project -} -export const xmlOptions = { - ignoreAttributes: false, -}; -export interface Project { - modelVersion: string; - groupId: string; - artifactId: string; - version: string; -} - diff --git a/frontend/src/components/upload/PomCreator.vue b/frontend/src/components/upload/PomCreator.vue deleted file mode 100644 index 8d5a240a..00000000 --- a/frontend/src/components/upload/PomCreator.vue +++ /dev/null @@ -1,146 +0,0 @@ - - - - diff --git a/frontend/src/components/user/LoginComp.vue b/frontend/src/components/user/LoginComp.vue index 65c04abe..55de0851 100644 --- a/frontend/src/components/user/LoginComp.vue +++ b/frontend/src/components/user/LoginComp.vue @@ -1,33 +1,30 @@ diff --git a/frontend/src/views/Repository.vue b/frontend/src/views/Repository.vue index 2d72bb20..3916ec58 100644 --- a/frontend/src/views/Repository.vue +++ b/frontend/src/views/Repository.vue @@ -1,26 +1,7 @@ - + diff --git a/frontend/src/views/Upload.vue b/frontend/src/views/Upload.vue index bd441fc9..394516a2 100644 --- a/frontend/src/views/Upload.vue +++ b/frontend/src/views/Upload.vue @@ -5,37 +5,22 @@ From 48d2020c01b2bfb2f59e797df27561b2e762b657 Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Wed, 13 Jul 2022 13:27:04 -0400 Subject: [PATCH 17/76] Starting to make backend queries again --- backend/Cargo.toml | 3 ++ backend/src/api.rs | 9 +++++ backend/src/authentication/middleware.rs | 2 +- backend/src/bin/nitro_repo_full.rs | 7 ++++ backend/src/lib.rs | 1 + backend/src/repository/web/multi/admin.rs | 8 ++-- backend/src/storage/models.rs | 13 +++++-- backend/src/storage/multi/mod.rs | 2 +- backend/src/storage/multi/web/admin.rs | 18 ++++++++- backend/src/system/web/mod.rs | 4 +- frontend/src/components/CreateRepo.vue | 38 ++++++++++++++---- frontend/src/components/CreateStorage.vue | 39 +++++++++++++++---- frontend/src/components/CreateUser.vue | 1 - frontend/src/components/Repositories.vue | 4 -- frontend/src/components/Storages.vue | 4 -- frontend/src/components/UpdateStorage.vue | 18 +++++---- frontend/src/components/Users.vue | 6 +-- .../src/components/common/code/CodeCard.vue | 1 - frontend/src/components/nav/Navbar.vue | 2 +- frontend/src/router/index.ts | 27 ++++++++++++- frontend/src/store/user.ts | 6 +++ 21 files changed, 161 insertions(+), 52 deletions(-) create mode 100644 backend/src/api.rs diff --git a/backend/Cargo.toml b/backend/Cargo.toml index dbd44fcd..8d9dab3f 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -72,6 +72,9 @@ unicode-width = "0.1.9" semver = "1.0.9" # Docs schemars = "0.8.10" +utoipa = { version = "1.1.0", features = ["actix_extras"] } +utoipa-swagger-ui = { version = "1.1.0", features = ["actix-web"] } + [build-dependencies] vergen = "7.0.0" diff --git a/backend/src/api.rs b/backend/src/api.rs new file mode 100644 index 00000000..68f5e93c --- /dev/null +++ b/backend/src/api.rs @@ -0,0 +1,9 @@ +use crate::storage::models::StorageSaver; +use crate::storage::multi::web::admin; +use utoipa::OpenApi; +#[derive(OpenApi)] +#[openapi( + handlers(admin::get_storage, admin::get_storages), + components(StorageSaver) +)] +pub struct ApiDoc; diff --git a/backend/src/authentication/middleware.rs b/backend/src/authentication/middleware.rs index c4ef2317..610568d7 100644 --- a/backend/src/authentication/middleware.rs +++ b/backend/src/authentication/middleware.rs @@ -203,7 +203,7 @@ where // If a new cookie needs to be added. Do it if let Some(session) = session { let mut cookie = Cookie::new("session", &session.token); - cookie.set_secure(false); + cookie.set_secure(true); cookie.set_same_site(SameSite::None); cookie.set_path("/"); cookie.set_expires(session.expiration); diff --git a/backend/src/bin/nitro_repo_full.rs b/backend/src/bin/nitro_repo_full.rs index 66d40ddb..1f148db9 100644 --- a/backend/src/bin/nitro_repo_full.rs +++ b/backend/src/bin/nitro_repo_full.rs @@ -12,7 +12,10 @@ use log::info; use semver::Version; use tokio::fs::read_to_string; use tokio::sync::RwLock; +use utoipa::OpenApi; +use utoipa_swagger_ui::SwaggerUi; +use api::api::ApiDoc; use api::authentication::middleware::HandleSession; use api::authentication::session::SessionManager; use api::cli::handle_cli; @@ -73,9 +76,13 @@ async fn main() -> std::io::Result<()> { let site_state = Data::new(nitro_repo); let database_data = Data::new(connection); let session_data = Data::new(session_manager); + let openapi = ApiDoc::openapi(); let server = HttpServer::new(move || { App::new() + .service( + SwaggerUi::new("/swagger-ui/{_:.*}").url("/api-doc/openapi.json", openapi.clone()), + ) .app_data(storages_data.clone()) .app_data(site_state.clone()) .app_data(database_data.clone()) diff --git a/backend/src/lib.rs b/backend/src/lib.rs index 8ef7f552..583384cb 100644 --- a/backend/src/lib.rs +++ b/backend/src/lib.rs @@ -5,6 +5,7 @@ use tokio::sync::RwLock; use crate::settings::models::{GeneralSettings, Settings}; +pub mod api; pub mod authentication; pub mod cli; pub mod constants; diff --git a/backend/src/repository/web/multi/admin.rs b/backend/src/repository/web/multi/admin.rs index dcdd40d7..842c6ae2 100644 --- a/backend/src/repository/web/multi/admin.rs +++ b/backend/src/repository/web/multi/admin.rs @@ -56,20 +56,18 @@ pub async fn create_repository( storage_handler: web::Data, database: web::Data, auth: Authentication, - storage_name: web::Path, - query_params: web::Path<(String, RepositoryType)>, + query_params: web::Path<(String, String, RepositoryType)>, ) -> actix_web::Result { let user: UserModel = auth.get_user(&database).await??; user.can_i_edit_repos()?; + let (storage_name, repository_name, repository_type) = query_params.into_inner(); let storage = storage_handler - .get_storage_by_name(&storage_name.into_inner()) + .get_storage_by_name(&storage_name) .await .map_err(InternalError::from)? .ok_or_else(|| APIError::from(("Storage not found", StatusCode::NOT_FOUND)))?; - let (repository_name, repository_type) = query_params.into_inner(); - if let Err(error) = storage .create_repository(repository_name, repository_type) .await diff --git a/backend/src/storage/models.rs b/backend/src/storage/models.rs index 316c05b9..91573932 100644 --- a/backend/src/storage/models.rs +++ b/backend/src/storage/models.rs @@ -5,6 +5,7 @@ use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use serde_json::Value; use tokio::sync::RwLockReadGuard; +use utoipa::Component; use crate::repository::settings::{RepositoryConfig, RepositoryType}; use crate::storage::error::StorageError; @@ -16,7 +17,7 @@ pub static STORAGE_FILE: &str = "storages.json"; pub static STORAGE_FILE_BAK: &str = "storages.json.bak"; /// Types of Storages -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Component)] pub enum StorageType { LocalStorage, } @@ -59,19 +60,25 @@ impl Display for StorageStatus { } } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Component)] pub struct StorageSaver { + /// The Type of the Storage + #[component(example = StorageType::LocalStorage)] pub storage_type: StorageType, + /// The Storage Config #[serde(flatten)] pub generic_config: StorageConfig, /// Storage Handler Config pub handler_config: Value, } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Component)] pub struct StorageConfig { + /// The public name of the storage pub public_name: String, + /// The internal name of the storage pub name: String, + /// This is created internally by the storage. No need to set this. #[serde(default = "crate::utils::get_current_time")] pub created: i64, } diff --git a/backend/src/storage/multi/mod.rs b/backend/src/storage/multi/mod.rs index bc5c2906..a5c77227 100644 --- a/backend/src/storage/multi/mod.rs +++ b/backend/src/storage/multi/mod.rs @@ -76,7 +76,7 @@ impl MultiStorageController { name: &str, ) -> Result>, StorageError> { let storages = self.storages.read().await; - if storages.contains_key(name) { + if !storages.contains_key(name) { return Ok(None); } let storage = RwLockReadGuard::map(storages, |storages| { diff --git a/backend/src/storage/multi/web/admin.rs b/backend/src/storage/multi/web/admin.rs index 3d37bf91..379e3df7 100644 --- a/backend/src/storage/multi/web/admin.rs +++ b/backend/src/storage/multi/web/admin.rs @@ -12,7 +12,11 @@ use crate::storage::multi::MultiStorageController; use crate::system::permissions::options::CanIDo; use crate::system::user::UserModel; -/// API handler for getting storages +#[utoipa::path( +get, +path = "/api/storages", +responses((status = 200, description = "A list of storages", body = [StorageSaver])), +)] #[get("/storages")] pub async fn get_storages( storage_handler: web::Data, @@ -70,7 +74,17 @@ pub async fn delete_storage( } } -/// Gets the storage based on the name +#[utoipa::path( +get, +path = "/api/storages/{id}", +responses( +(status = 200, description = "Storage found succesfully", body = StorageSaver), +(status = 404, description = "Storage was not found") +), +params( +("id" = string, path, description = "Storage name"), +) +)] #[get("/storage/{name}")] pub async fn get_storage( storage_handler: web::Data, diff --git a/backend/src/system/web/mod.rs b/backend/src/system/web/mod.rs index 7c28bc15..1a7d0a04 100644 --- a/backend/src/system/web/mod.rs +++ b/backend/src/system/web/mod.rs @@ -12,4 +12,6 @@ pub fn user_routes(cfg: &mut ServiceConfig) { cfg.service(user::me); } -pub fn init_user_manager_routes(_cfg: &mut ServiceConfig) {} +pub fn init_user_manager_routes(cfg: &mut ServiceConfig) { + cfg.service(admin::list_users); +} diff --git a/frontend/src/components/CreateRepo.vue b/frontend/src/components/CreateRepo.vue index 8d086456..79c20a3f 100644 --- a/frontend/src/components/CreateRepo.vue +++ b/frontend/src/components/CreateRepo.vue @@ -40,8 +40,11 @@ diff --git a/frontend/src/components/repo/badge/RepositoryBadge.vue b/frontend/src/components/repo/badge/RepositoryBadge.vue index f538d788..105f2539 100644 --- a/frontend/src/components/repo/badge/RepositoryBadge.vue +++ b/frontend/src/components/repo/badge/RepositoryBadge.vue @@ -32,14 +32,13 @@ import { defineComponent } from "vue"; import { apiURL } from "@/http-common"; import { createBadgeSnippets } from "@/api/repository/BadgeGen"; import CodeMenu from "@/components/common/code/CodeMenu.vue"; -import { Repository } from "@/types/repositoryTypes"; export default defineComponent({ components: { CodeMenu }, props: { repository: { required: true, - type: Object as () => Repository, + type: Object as () => { name: string; storage: string }, }, }, setup(props) { diff --git a/frontend/src/components/repo/update/ArtifactSettings.vue b/frontend/src/components/repo/update/ArtifactSettings.vue index aa2f3984..2c417ed9 100644 --- a/frontend/src/components/repo/update/ArtifactSettings.vue +++ b/frontend/src/components/repo/update/ArtifactSettings.vue @@ -1,6 +1,12 @@ diff --git a/frontend/src/components/repo/update/DeployRepo.vue b/frontend/src/components/repo/update/DeployRepo.vue deleted file mode 100644 index a3b6fe1a..00000000 --- a/frontend/src/components/repo/update/DeployRepo.vue +++ /dev/null @@ -1,54 +0,0 @@ - - diff --git a/frontend/src/components/repo/update/FrontendRepo.vue b/frontend/src/components/repo/update/FrontendRepo.vue index 48ad3f00..d8e954b0 100644 --- a/frontend/src/components/repo/update/FrontendRepo.vue +++ b/frontend/src/components/repo/update/FrontendRepo.vue @@ -5,10 +5,10 @@
-
+
-
+
- @@ -54,10 +51,7 @@
- @@ -66,10 +60,7 @@
- @@ -84,7 +75,7 @@ diff --git a/frontend/src/components/repo/update/UpdateRepo.vue b/frontend/src/components/repo/update/UpdateRepo.vue index 5d92e1b3..1a04a256 100644 --- a/frontend/src/components/repo/update/UpdateRepo.vue +++ b/frontend/src/components/repo/update/UpdateRepo.vue @@ -2,8 +2,6 @@ General Frontend - Security - Deploy Settings diff --git a/frontend/src/components/repo/ViewRepo.vue b/frontend/src/components/repo/ViewRepo.vue index 12291e16..f43838e5 100644 --- a/frontend/src/components/repo/ViewRepo.vue +++ b/frontend/src/components/repo/ViewRepo.vue @@ -1,13 +1,41 @@ @@ -16,37 +44,40 @@ import MavenRepoInfo from "@/components/repo/types/maven/MavenRepoInfo.vue"; import { defineComponent, ref } from "vue"; import { useMeta } from "vue-meta"; -import { useRouter } from "vue-router"; import RepositoryBadge from "./badge/RepositoryBadge.vue"; -import { Repository } from "@/types/repositoryTypes"; +import httpCommon from "@/http-common"; +import DynamicIcon from "@/components/repo/DynamicIcon.vue"; export default defineComponent({ - components: { MavenRepoInfo, RepositoryBadge }, + components: { DynamicIcon, MavenRepoInfo, RepositoryBadge }, props: { storage: { - required: false, type: String, }, repositoryName: { - required: false, type: String, }, - repositoryType: { - required: false, - type: Object as () => Repository, - }, }, - setup(props) { - const router = useRouter(); - - const repository = ref(props.repositoryType); - const { meta } = useMeta({ - title: "Nitro Repo", + async setup(props) { + const repository = ref< + | { repository_type: string; page_content: string; name: string } + | undefined + >(undefined); + useMeta({ + title: `${props.repositoryName} - Nitro Repo`, }); - // TODO pull repository data + await httpCommon.apiClient + .get(`api/repositories/${props.storage}/${props.repositoryName}`) + .then((response) => { + if (response.status == 200) { + repository.value = response.data; + } else { + //TODO handle 404 + console.error("Error fetching repository "); + } + }); return { repository, - router, }; }, }); diff --git a/frontend/src/components/repo/types/maven/MavenRepoInfo.vue b/frontend/src/components/repo/types/maven/MavenRepoInfo.vue index 82f26539..c43f18d5 100644 --- a/frontend/src/components/repo/types/maven/MavenRepoInfo.vue +++ b/frontend/src/components/repo/types/maven/MavenRepoInfo.vue @@ -15,14 +15,13 @@ import { defineComponent, ref } from "vue"; import { apiURL } from "@/http-common"; import createRepositoryInfo from "@/api/maven/CodeGen"; -import { Repository } from "@/types/repositoryTypes"; export default defineComponent({ components: {}, props: { repository: { required: true, - type: Object as () => Repository, + type: Object as () => { name: string; storage: string }, }, }, setup(props) { diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index 24e450b9..e3d31122 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -79,13 +79,13 @@ const routes: Array = [ component: Browse, }, { - path: "/repository/:storage/:repo", + path: "/repository/:storage/:repository", name: "ViewRepository", component: Repository, }, { - path: "/project/:storage/:repo/:id/:version?", + path: "/project/:storage/:repository/:project/:version?", name: "Project", component: Project, }, diff --git a/frontend/src/styles/app.css b/frontend/src/styles/app.css index d9a1b62e..f5650516 100644 --- a/frontend/src/styles/app.css +++ b/frontend/src/styles/app.css @@ -1,7 +1,10 @@ @tailwind base; @tailwind components; @tailwind utilities; - +@font-face { + font-family: "Fira Code"; + src: url("@/prismjs/fonts/static/FiraCode-Regular.ttf") format("truetype"); +} html, body { --color-primary: 206, 25%, 26%; diff --git a/frontend/src/views/Project.vue b/frontend/src/views/Project.vue index 3916ec58..04568944 100644 --- a/frontend/src/views/Project.vue +++ b/frontend/src/views/Project.vue @@ -1,7 +1,32 @@ - + diff --git a/frontend/src/views/Repository.vue b/frontend/src/views/Repository.vue index 3916ec58..b4a11f75 100644 --- a/frontend/src/views/Repository.vue +++ b/frontend/src/views/Repository.vue @@ -1,7 +1,25 @@ - + From b46502abd9133a967be33328a852741073a7ca40 Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Wed, 20 Jul 2022 09:27:11 -0400 Subject: [PATCH 34/76] Another Install Method and started a docker file --- Dockerfile | 14 +++ backend/Cargo.toml | 3 +- backend/src/bin/simple_installer.rs | 114 ++++++++++++++++++ backend/src/install/mod.rs | 7 ++ backend/src/install/utils.rs | 44 +++++++ backend/src/repository/nitro/mod.rs | 5 +- .../src/repository/nitro/nitro_repository.rs | 4 +- backend/src/settings/models.rs | 29 ++++- backend/src/utils.rs | 18 ++- 9 files changed, 229 insertions(+), 9 deletions(-) create mode 100644 Dockerfile create mode 100644 backend/src/bin/simple_installer.rs create mode 100644 backend/src/install/utils.rs diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..3ec71f9f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +FROM rust:latest + +LABEL author="Wyatt Herkamp" maintaner="wherkamp@kingtux.me" + +RUN apt-get update -y \ apt-get install git +RUN cargo install fnm + +RUN git pull https://github.com/wyatt-herkamp/nitro_repo.git +RUN git checkout dev + +RUN cd /backend && cargo build --release && cd .. +RUN cd /frontend && fnm use && npm install && npm run build + + diff --git a/backend/Cargo.toml b/backend/Cargo.toml index b49f9609..144825f4 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -13,7 +13,8 @@ path = "src/lib.rs" [[bin]] name = "nitro_repo_full" required-features = ["multi_storage"] - +[[bin]] +name = "simple_installer" [dependencies] # Web diff --git a/backend/src/bin/simple_installer.rs b/backend/src/bin/simple_installer.rs new file mode 100644 index 00000000..0b98d23e --- /dev/null +++ b/backend/src/bin/simple_installer.rs @@ -0,0 +1,114 @@ +use api::settings::models::{Database, GeneralSettings, MysqlSettings, SqliteSettings}; +use api::system::permissions::UserPermissions; +use api::system::user::database::ActiveModel; +use api::system::user::UserEntity; +use api::system::{hash, user}; +use api::utils::get_current_time; +use clap::{Parser, Subcommand}; +use sea_orm::ActiveValue::Set; +use sea_orm::{ConnectOptions, DatabaseConnection, EntityTrait}; +use semver::Op; +use std::env; +use std::fs::OpenOptions; +use std::path::Path; + +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct InstallCommand { + #[clap(subcommand)] + database_type: DatabaseTypes, + #[clap(long)] + admin_username: String, + #[clap(long)] + admin_password: String, +} + +#[derive(Subcommand, Debug)] +enum DatabaseTypes { + Mysql(MysqlInstall), + Sqlite(SqliteInstall), +} +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct SqliteInstall { + #[clap(long)] + database_file: String, +} + +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct MysqlInstall { + #[clap(long)] + pub db_user: String, + #[clap(long)] + pub db_password: String, + #[clap(long)] + pub db_host: String, + #[clap(long)] + pub database: String, +} +#[tokio::main] +async fn main() { + let install_command = InstallCommand::parse(); + let config = match install_command.database_type { + DatabaseTypes::Mysql(mysql) => { + let mysql_settings = MysqlSettings { + user: mysql.db_user, + password: mysql.db_password, + host: mysql.db_host, + database: mysql.database, + }; + api::settings::models::Database::Mysql(mysql_settings) + } + DatabaseTypes::Sqlite(sqlite) => { + let buf = Path::new(&sqlite.database_file).to_path_buf(); + let sqlite_settings = SqliteSettings { database_file: buf }; + api::settings::models::Database::Sqlite(sqlite_settings) + } + }; + if let Database::Sqlite(sql) = &config { + println!("{}", sql.to_string()); + OpenOptions::new() + .create(true) + .write(true) + .open(&sql.database_file) + .expect("Failed to open file"); + } + let options: ConnectOptions = config.clone().into(); + let mut database_conn = sea_orm::Database::connect(options) + .await + .expect("Failed to connect to database"); + api::utils::run_database_setup(&mut database_conn) + .await + .expect("Failed to run database setup"); + let user: user::database::ActiveModel = ActiveModel { + id: Default::default(), + name: Set(install_command.admin_username.clone()), + username: Set(install_command.admin_username), + + email: Set("admin@nitro_repo.dev".to_string()), + password: Set(hash(install_command.admin_password).unwrap()), + permissions: Set(UserPermissions { + disabled: false, + admin: true, + user_manager: true, + repository_manager: true, + deployer: None, + viewer: None, + }), + created: Set(get_current_time()), + }; + + UserEntity::insert(user) + .exec(&database_conn) + .await + .expect("Failed to insert user"); + let general = GeneralSettings { + database: config, + application: Default::default(), + internal: Default::default(), + session: Default::default(), + }; + api::install::utils::install_data(env::current_dir().unwrap(), general) + .expect("Failed to install data"); +} diff --git a/backend/src/install/mod.rs b/backend/src/install/mod.rs index c33f1028..83d1f953 100644 --- a/backend/src/install/mod.rs +++ b/backend/src/install/mod.rs @@ -1,3 +1,6 @@ +pub mod utils; + +use anyhow::Error; use std::env::current_dir; use std::fmt::{Display, Formatter}; use std::fs::{create_dir_all, OpenOptions}; @@ -517,6 +520,10 @@ pub async fn load_installer(working_dir: PathBuf) -> anyhow::Result<()> { let app = run_app(terminal, App::default()).await?; + install_data(working_dir, app) +} + +fn install_data(working_dir: PathBuf, app: App) -> Result<(), Error> { let general = GeneralSettings { database: app.database_stage.into(), application: Application::from(app.other_stage), diff --git a/backend/src/install/utils.rs b/backend/src/install/utils.rs new file mode 100644 index 00000000..811d2af4 --- /dev/null +++ b/backend/src/install/utils.rs @@ -0,0 +1,44 @@ +use crate::settings::models::{Application, EmailSetting, SecuritySettings, SiteSetting}; +use crate::GeneralSettings; +use log::info; +use std::fs::{create_dir_all, OpenOptions}; +use std::io::{Error, Write}; +use std::path::PathBuf; + +pub fn install_data(working_dir: PathBuf, general: GeneralSettings) -> anyhow::Result<()> { + let configs = working_dir.join("cfg"); + create_dir_all(&configs)?; + + let other = toml::to_string_pretty(&general)?; + let mut file = OpenOptions::new() + .write(true) + .append(true) + .create(true) + .open(working_dir.join("nitro_repo.toml"))?; + file.write_all(other.as_bytes())?; + + let security = toml::to_string_pretty(&SecuritySettings::default())?; + let mut file = OpenOptions::new() + .write(true) + .append(true) + .create(true) + .open(configs.join("security.toml"))?; + file.write_all(security.as_bytes())?; + + let email = toml::to_string_pretty(&EmailSetting::default())?; + let mut file = OpenOptions::new() + .write(true) + .append(true) + .create(true) + .open(configs.join("email.toml"))?; + file.write_all(email.as_bytes())?; + let site = toml::to_string_pretty(&SiteSetting::default())?; + let mut file = OpenOptions::new() + .write(true) + .append(true) + .create(true) + .open(configs.join("site.toml"))?; + file.write_all(site.as_bytes())?; + info!("Installation Complete"); + Ok(()) +} diff --git a/backend/src/repository/nitro/mod.rs b/backend/src/repository/nitro/mod.rs index c72ea8f3..b120a4e3 100644 --- a/backend/src/repository/nitro/mod.rs +++ b/backend/src/repository/nitro/mod.rs @@ -36,10 +36,7 @@ pub struct NitroFileResponse { #[derive(Serialize, Deserialize, Clone, Debug)] pub enum NitroFileResponseType { - Project(Option), - Version(VersionBrowseResponse), - Repository(RepositoryConfig), - Storage, + Project(Project), Other, } diff --git a/backend/src/repository/nitro/nitro_repository.rs b/backend/src/repository/nitro/nitro_repository.rs index 40cfe761..19cea280 100644 --- a/backend/src/repository/nitro/nitro_repository.rs +++ b/backend/src/repository/nitro/nitro_repository.rs @@ -135,7 +135,7 @@ pub trait NitroRepositoryHandler { version: version_data, frontend_response: String::new(), }; - NitroFileResponseType::Project(Some(project)) + NitroFileResponseType::Project(project) } else if let Some(version) = get_version_data(self.storage(), self.repository(), requested_dir).await? { @@ -150,7 +150,7 @@ pub trait NitroRepositoryHandler { version: Some(version), frontend_response: String::new(), }; - NitroFileResponseType::Project(Some(project)) + NitroFileResponseType::Project(project) } else { NitroFileResponseType::Other }; diff --git a/backend/src/settings/models.rs b/backend/src/settings/models.rs index 35b0a180..a64dd713 100644 --- a/backend/src/settings/models.rs +++ b/backend/src/settings/models.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; use std::fmt::{Display, Formatter}; +use std::fs::create_dir_all; use std::path::PathBuf; use sea_orm::ConnectOptions; @@ -52,12 +53,14 @@ impl Default for Internal { #[serde(tag = "type", content = "settings")] pub enum Database { Mysql(MysqlSettings), + Sqlite(SqliteSettings), } #[allow(clippy::from_over_into)] impl Into for Database { fn into(self) -> ConnectOptions { match self { Database::Mysql(mysql) => ConnectOptions::new(mysql.to_string()), + Database::Sqlite(database) => ConnectOptions::new(database.to_string()), } } } @@ -81,7 +84,15 @@ pub struct MysqlSettings { pub host: String, pub database: String, } - +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct SqliteSettings { + pub database_file: PathBuf, +} +impl Display for SqliteSettings { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "sqlite:{}", self.database_file.display()) + } +} #[derive(Debug, Deserialize, Serialize, Clone)] pub struct Application { pub log: String, @@ -94,6 +105,22 @@ pub struct Application { pub ssl_cert_key: Option, } +impl Default for Application { + fn default() -> Self { + let buf = PathBuf::from("storage"); + create_dir_all(&buf).unwrap(); + Self { + log: "./".to_string(), + address: "0.0.0.0:6742".to_string(), + app_url: "http://127.0.0.1:6742".to_string(), + max_upload: 1024, + mode: Mode::Release, + storage_location: buf.canonicalize().unwrap(), + ssl_private_key: None, + ssl_cert_key: None, + } + } +} #[derive(Debug, Deserialize, Serialize, Clone)] pub struct GeneralSettings { pub database: Database, diff --git a/backend/src/utils.rs b/backend/src/utils.rs index bef8d148..cea47a47 100644 --- a/backend/src/utils.rs +++ b/backend/src/utils.rs @@ -4,15 +4,31 @@ use std::io::Read; use std::ops::Add; use std::path::Path; +use crate::authentication; use actix_web::http::header::HeaderMap; use chrono::{DateTime, Duration, Local}; +use crossterm::ExecutableCommand; use nitro_log::config::Config; use nitro_log::{LoggerBuilders, NitroLogger}; use rust_embed::RustEmbed; +use sea_orm::{DatabaseConnection, DbErr, Schema}; use crate::error::internal_error::InternalError; use crate::settings::models::Mode; - +use crate::system::user::UserEntity; +use sea_orm::ConnectionTrait; +pub async fn run_database_setup(database: &mut DatabaseConnection) -> Result<(), DbErr> { + let schema = Schema::new(database.get_database_backend()); + let users = schema.create_table_from_entity(UserEntity); + database + .execute(database.get_database_backend().build(&users)) + .await?; + let tokens = schema.create_table_from_entity(authentication::auth_token::AuthTokenEntity); + database + .execute(database.get_database_backend().build(&tokens)) + .await?; + Ok(()) +} pub fn load_logger>(logger: T) { let file = match logger.as_ref() { Mode::Debug => "log-debug.json", From d25a4a15b408e627bb1be1ee8744852dc27adb1d Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Wed, 20 Jul 2022 10:18:16 -0400 Subject: [PATCH 35/76] Strip some code --- backend/Cargo.toml | 10 - backend/src/api.rs | 16 - backend/src/authentication/auth_token/mod.rs | 3 +- backend/src/authentication/middleware.rs | 11 +- .../src/authentication/session/basic/mod.rs | 7 +- backend/src/authentication/session/mod.rs | 4 +- backend/src/bin/nitro_repo_full.rs | 16 +- backend/src/bin/simple_installer.rs | 2 +- backend/src/cli/mod.rs | 19 +- backend/src/install/mod.rs | 545 +----------------- backend/src/install/utils.rs | 44 -- backend/src/lib.rs | 1 - backend/src/repository/nitro/mod.rs | 1 - backend/src/repository/response.rs | 1 - backend/src/repository/settings/badge.rs | 5 +- backend/src/repository/settings/frontend.rs | 5 +- .../src/repository/web/multi/public/mod.rs | 2 +- .../repository/web/multi/public/project.rs | 2 - .../web/multi/public/repositories.rs | 9 +- backend/src/storage/models.rs | 8 +- backend/src/storage/multi/web/admin.rs | 16 - backend/src/storage/multi/web/public.rs | 9 +- backend/src/system/mod.rs | 2 +- backend/src/utils.rs | 1 - 24 files changed, 37 insertions(+), 702 deletions(-) delete mode 100644 backend/src/api.rs delete mode 100644 backend/src/install/utils.rs diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 144825f4..25343646 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -38,11 +38,9 @@ toml = "0.5.9" # utils rand = "0.8.5" -rand_core = { version = "0.6.3", features = ["std"] } rust-embed = { version = "6.4.0", features = ["interpolate-folder-path"] } argon2 = "0.4.1" chrono = "0.4.19" -time = "0.3.11" regex = "1.6.0" futures-util = "0.3.21" base64 = "0.13.0" @@ -57,7 +55,6 @@ log = { version = "0.4.17", features = ["kv_unstable", "kv_unstable_std", "kv_un # Rust Internal strum = { version = "0.24.1", features = ["derive"] } strum_macros = "0.24.2" -derive_more = "0.99.17" async-trait = "0.1.56" thiserror = "1.0.31" anyhow = "1.0.58" @@ -66,15 +63,8 @@ badge-maker = "0.3.1" # Webhook webhook = "2.0.0" # Installer -tui = "0.18.0" -crossterm = "0.24.0" clap = { version = "3.2.12", features = ["derive"] } -unicode-width = "0.1.9" semver = "1.0.12" -# Docs -schemars = "0.8.10" -utoipa = { version = "1.1.0", features = ["actix_extras"] } -utoipa-swagger-ui = { version = "1.1.0", features = ["actix-web"] } # Cache redis = "0.21.5" comrak = "0.14" diff --git a/backend/src/api.rs b/backend/src/api.rs deleted file mode 100644 index 92f733b3..00000000 --- a/backend/src/api.rs +++ /dev/null @@ -1,16 +0,0 @@ -use crate::repository::web::multi::public::repositories::{self, PublicRepositoryResponse}; -use crate::storage::models::StorageSaver; -use crate::storage::multi::web::admin; -use crate::storage::multi::web::public::{self, PublicStorageResponse}; -use utoipa::OpenApi; -#[derive(OpenApi)] -#[openapi( - handlers( - admin::get_storage, - admin::get_storages, - public::get_storages_multi, - repositories::get_repositories - ), - components(StorageSaver, PublicStorageResponse, PublicRepositoryResponse) -)] -pub struct ApiDoc; diff --git a/backend/src/authentication/auth_token/mod.rs b/backend/src/authentication/auth_token/mod.rs index e6e89e94..2b283371 100644 --- a/backend/src/authentication/auth_token/mod.rs +++ b/backend/src/authentication/auth_token/mod.rs @@ -11,7 +11,6 @@ use rand::Rng; use sea_orm::FromQueryResult; use sea_orm::{ColumnTrait, DatabaseConnection, EntityTrait, QueryFilter}; use serde::{Deserialize, Serialize}; -use time::OffsetDateTime; #[derive(Debug, Clone, Serialize, Deserialize, FromQueryResult)] pub struct TokenResponse { @@ -82,5 +81,5 @@ pub fn generate_token() -> String { } pub fn token_expiration(add: i64) -> i64 { - OffsetDateTime::now_utc().unix_timestamp() + add + get_current_time() + add } diff --git a/backend/src/authentication/middleware.rs b/backend/src/authentication/middleware.rs index 6b30beee..d14fa49a 100644 --- a/backend/src/authentication/middleware.rs +++ b/backend/src/authentication/middleware.rs @@ -3,7 +3,8 @@ use std::future::{ready, Ready}; use std::rc::Rc; use std::time::SystemTime; -use actix_web::cookie::{Cookie, SameSite}; +use actix_web::cookie::time::OffsetDateTime; +use actix_web::cookie::{Cookie, Expiration, SameSite}; use actix_web::http::header::{HeaderValue, AUTHORIZATION, ORIGIN, SET_COOKIE}; use actix_web::http::Method; use actix_web::{ @@ -18,6 +19,7 @@ use crate::authentication::session::SessionManagerType; use crate::authentication::{ auth_token, session::Session, session::SessionManager, verify_login, Authentication, }; +use crate::utils::get_current_time; pub struct HandleSession(pub bool); @@ -97,7 +99,7 @@ where (Authentication::NoIdentification, Option::None) } } else if let Some(mut session) = session { - if session.expiration <= SystemTime::UNIX_EPOCH { + if session.expiration <= get_current_time() as u64 { session = session_manager .re_create_session(&session.token) .await @@ -215,7 +217,10 @@ where cookie.set_secure(true); cookie.set_same_site(SameSite::None); cookie.set_path("/"); - cookie.set_expires(session.expiration); + cookie.set_expires(Expiration::DateTime( + OffsetDateTime::from_unix_timestamp(session.expiration as i64) + .expect("Time has Broken. its is the end times"), + )); let cookie_encoded = cookie.encoded().to_string(); trace!("Sending Cookie Response {}", &cookie_encoded); let val = HeaderValue::from_str(&cookie_encoded).unwrap(); diff --git a/backend/src/authentication/session/basic/mod.rs b/backend/src/authentication/session/basic/mod.rs index 8e2c25ed..6ffd3d37 100644 --- a/backend/src/authentication/session/basic/mod.rs +++ b/backend/src/authentication/session/basic/mod.rs @@ -2,13 +2,14 @@ use std::collections::HashMap; use std::ops::Add; use async_trait::async_trait; +use chrono::Duration; use log::trace; use rand::distributions::Alphanumeric; use rand::Rng; -use time::{Duration, OffsetDateTime}; use tokio::sync::RwLock; use crate::authentication::session::{Session, SessionManagerType}; +use crate::utils::get_current_time; pub struct BasicSessionManager { pub sessions: RwLock>, @@ -93,6 +94,6 @@ fn generate_token() -> String { format!("nrs_{}", token) } -pub fn token_expiration() -> OffsetDateTime { - OffsetDateTime::now_utc().add(Duration::days(1)) +pub fn token_expiration() -> u64 { + (Duration::days(1).num_milliseconds() + get_current_time()) as u64 } diff --git a/backend/src/authentication/session/mod.rs b/backend/src/authentication/session/mod.rs index 6664e011..b4a57b27 100644 --- a/backend/src/authentication/session/mod.rs +++ b/backend/src/authentication/session/mod.rs @@ -5,7 +5,7 @@ use crate::authentication::session::basic::BasicSessionManager; use crate::authentication::session::redis_manager::RedisSessionManager; use crate::settings::models::SessionSettings; use async_trait::async_trait; -use time::OffsetDateTime; +use chrono::NaiveDateTime; pub enum SessionManager { BasicSessionManager(BasicSessionManager), @@ -16,7 +16,7 @@ pub enum SessionManager { pub struct Session { pub token: String, pub user: Option, - pub expiration: OffsetDateTime, + pub expiration: u64, } #[async_trait] diff --git a/backend/src/bin/nitro_repo_full.rs b/backend/src/bin/nitro_repo_full.rs index e0d04f6d..c8b06075 100644 --- a/backend/src/bin/nitro_repo_full.rs +++ b/backend/src/bin/nitro_repo_full.rs @@ -8,14 +8,6 @@ use actix_web::main; use actix_web::middleware::DefaultHeaders; use actix_web::web::{Data, PayloadConfig}; use actix_web::{web, App, HttpServer}; -use log::info; -use semver::Version; -use tokio::fs::read_to_string; -use tokio::sync::RwLock; -use utoipa::OpenApi; -use utoipa_swagger_ui::SwaggerUi; - -use api::api::ApiDoc; use api::authentication::middleware::HandleSession; use api::authentication::session::SessionManager; use api::cli::handle_cli; @@ -24,6 +16,10 @@ use api::settings::models::GeneralSettings; use api::storage::multi::MultiStorageController; use api::utils::load_logger; use api::{frontend, repository, storage, system, NitroRepo}; +use log::info; +use semver::Version; +use tokio::fs::read_to_string; +use tokio::sync::RwLock; #[main] async fn main() -> std::io::Result<()> { @@ -77,13 +73,9 @@ async fn main() -> std::io::Result<()> { let site_state = Data::new(nitro_repo); let database_data = Data::new(connection); let session_data = Data::new(session_manager); - let openapi = ApiDoc::openapi(); let server = HttpServer::new(move || { App::new() - .service( - SwaggerUi::new("/swagger-ui/{_:.*}").url("/api-doc/openapi.json", openapi.clone()), - ) .app_data(storages_data.clone()) .app_data(site_state.clone()) .app_data(database_data.clone()) diff --git a/backend/src/bin/simple_installer.rs b/backend/src/bin/simple_installer.rs index 0b98d23e..7eb09e9c 100644 --- a/backend/src/bin/simple_installer.rs +++ b/backend/src/bin/simple_installer.rs @@ -109,6 +109,6 @@ async fn main() { internal: Default::default(), session: Default::default(), }; - api::install::utils::install_data(env::current_dir().unwrap(), general) + api::install::install_data(env::current_dir().unwrap(), general) .expect("Failed to install data"); } diff --git a/backend/src/cli/mod.rs b/backend/src/cli/mod.rs index c2e99329..99812645 100644 --- a/backend/src/cli/mod.rs +++ b/backend/src/cli/mod.rs @@ -4,16 +4,11 @@ use clap::Parser; use log::error; use style_term::{DefaultColor, StyleString}; -use crate::install::load_installer; -use crate::settings::models::Mode; use crate::updater; -use crate::utils::load_logger; #[derive(Parser, Debug)] #[clap(author, version, about, long_about = None)] struct NitroRepoCLI { - #[clap(short, long)] - install: bool, #[clap(short, long)] update: Option, } @@ -22,19 +17,7 @@ pub async fn handle_cli() -> std::io::Result { let path = current_dir()?; let parse: NitroRepoCLI = NitroRepoCLI::parse(); - if parse.install { - load_logger(Mode::Install); - if let Err(error) = load_installer(path).await { - error!("Unable to complete Install {error}"); - println!( - "{}", - "Unable to Complete Installation" - .style() - .text_color(DefaultColor::Red) - ); - } - return Ok(true); - } else if let Some(update) = parse.update { + if let Some(update) = parse.update { if let Err(error) = updater::update(update).await { error!("Unable to complete update {error}"); println!( diff --git a/backend/src/install/mod.rs b/backend/src/install/mod.rs index 83d1f953..68f65ccb 100644 --- a/backend/src/install/mod.rs +++ b/backend/src/install/mod.rs @@ -1,535 +1,11 @@ -pub mod utils; - -use anyhow::Error; -use std::env::current_dir; -use std::fmt::{Display, Formatter}; +use crate::settings::models::{EmailSetting, SecuritySettings, SiteSetting}; +use crate::GeneralSettings; +use log::info; use std::fs::{create_dir_all, OpenOptions}; -use std::io; -use std::io::{Stdout, Write}; +use std::io::Write; use std::path::PathBuf; -use crossterm::{ - event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, - execute, - terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, - ExecutableCommand, -}; -use log::{error, info, trace}; -use sea_orm::ActiveValue::Set; -use sea_orm::ConnectionTrait; -use sea_orm::{DatabaseConnection, EntityTrait, Schema}; -use serde::{Deserialize, Serialize}; -use thiserror::Error; -use tui::{ - backend::{Backend, CrosstermBackend}, - layout::{Constraint, Direction, Layout}, - style::{Color, Modifier, Style}, - text::{Span, Spans, Text}, - widgets::{Block, Borders, List, ListItem, Paragraph}, - Frame, Terminal, -}; -use unicode_width::UnicodeWidthStr; - -use crate::settings::models::{ - Application, Database, EmailSetting, Mode, MysqlSettings, SecuritySettings, SiteSetting, -}; -use crate::system::permissions::UserPermissions; -use crate::system::user::UserEntity; -use crate::system::{hash, user}; -use crate::utils::get_current_time; -use crate::{authentication, GeneralSettings}; - -#[derive(Error, Debug)] -pub enum InstallError { - #[error("Unable to Install Nitro Repo. {0}")] - InstallError(String), - #[error("IO Error. Installer. {0}")] - IOError(std::io::Error), -} - -impl From<&str> for InstallError { - fn from(error: &str) -> Self { - InstallError::InstallError(error.to_string()) - } -} - -impl From for InstallError { - fn from(error: std::io::Error) -> Self { - InstallError::IOError(error) - } -} - -impl std::convert::From for InstallError { - fn from(error: sea_orm::DbErr) -> Self { - InstallError::InstallError(error.to_string()) - } -} - -//mysql://newuser:"password"@127.0.0.1/nitro_repo -#[derive(Serialize, Deserialize, Clone, Debug)] -struct DatabaseStage { - pub user: Option, - pub password: Option, - pub host: Option, - pub database: Option, -} - -impl From for Database { - fn from(db: DatabaseStage) -> Self { - let mysql_settings = MysqlSettings { - user: db.user.unwrap(), - password: db.password.unwrap(), - host: db.host.unwrap(), - database: db.database.unwrap(), - }; - crate::settings::models::Database::Mysql(mysql_settings) - } -} - -impl Display for DatabaseStage { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - let my_db = self.clone(); - write!( - f, - "mysql://{}:{}@{}/{}", - my_db.user.unwrap(), - my_db.password.unwrap(), - my_db.host.unwrap(), - my_db.database.unwrap() - ) - } -} - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct UserStage { - pub name: Option, - pub username: Option, - pub email: Option, - pub password: Option, - pub password_two: Option, -} - -impl From for user::database::ActiveModel { - fn from(value: UserStage) -> Self { - user::database::ActiveModel { - id: Default::default(), - name: Set(value.name.unwrap_or_default()), - username: Set(value.username.unwrap_or_default()), - email: Set(value.email.unwrap_or_default()), - password: Set(hash(value.password.unwrap_or_default()).unwrap()), - permissions: Set(UserPermissions { - disabled: false, - admin: true, - user_manager: true, - repository_manager: true, - deployer: None, - viewer: None, - }), - created: Set(get_current_time()), - } - } -} - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct OtherStage { - log_location: Option, - address: Option, - app_url: Option, - max_upload: Option, -} - -impl From for Application { - fn from(other: OtherStage) -> Self { - let storages = current_dir().unwrap().join("storages"); - Self { - log: other.log_location.unwrap(), - address: other.address.unwrap(), - app_url: other.app_url.unwrap(), - max_upload: other.max_upload.unwrap().parse().unwrap(), - mode: Mode::Release, - storage_location: storages, - ssl_private_key: None, - ssl_cert_key: None, - } - } -} - -/// App holds the state of the application -struct App { - /// Current value of the input box - input: String, - /// Current input mode - stage: u8, - /// History of recorded messages - database_stage: DatabaseStage, - user_stage: UserStage, - other_stage: OtherStage, - connection: Option, -} - -impl Default for App { - fn default() -> App { - App { - input: String::new(), - stage: 0, - connection: None, - database_stage: DatabaseStage { - user: None, - password: None, - host: None, - database: None, - }, - user_stage: UserStage { - name: None, - username: None, - email: None, - password: None, - password_two: None, - }, - other_stage: OtherStage { - log_location: None, - address: None, - app_url: None, - max_upload: None, - }, - } - } -} -#[allow(unused_mut)] -async fn run_app( - mut terminal: Terminal>, - mut app: App, -) -> Result { - loop { - if app.stage >= 3 { - close(terminal); - return Ok(app); - } - terminal.draw(|f| ui(f, &app))?; - - if let Event::Key(key) = event::read()? { - match key.code { - KeyCode::Enter => { - let value = if app.input.is_empty() { - get_next_default(&app) - } else { - Some(app.input.clone()) - }; - app.input.clear(); - match app.stage { - 0 => { - if app.database_stage.user.is_none() { - app.database_stage.user = value; - } else if app.database_stage.password.is_none() { - app.database_stage.password = value; - } else if app.database_stage.host.is_none() { - app.database_stage.host = value; - } else if app.database_stage.database.is_none() { - app.database_stage.database = value; - } else { - let string = app.database_stage.to_string(); - trace!("Database String: {}", &string); - let mut database_conn = sea_orm::Database::connect(string).await?; - let schema = Schema::new(database_conn.get_database_backend()); - let users = schema.create_table_from_entity(UserEntity); - database_conn - .execute(database_conn.get_database_backend().build(&users)) - .await?; - let tokens = schema.create_table_from_entity( - authentication::auth_token::AuthTokenEntity, - ); - database_conn - .execute(database_conn.get_database_backend().build(&tokens)) - .await?; - - app.connection = Some(database_conn); - app.stage = 1; - } - } - 1 => { - if app.user_stage.name.is_none() { - app.user_stage.name = value; - } else if app.user_stage.username.is_none() { - app.user_stage.username = value; - } else if app.user_stage.email.is_none() { - app.user_stage.email = value; - } else if app.user_stage.password.is_none() { - app.user_stage.password = value; - } else { - let connection = app.connection.as_ref().unwrap(); - let stage = app.user_stage.clone(); - - //TODO dont kill program on failure to create user - let user: user::database::ActiveModel = stage.into(); - UserEntity::insert(user).exec(connection).await?; - app.stage = 2; - } - } - 2 => { - if app.other_stage.address.is_none() { - app.other_stage.address = value; - } else if app.other_stage.app_url.is_none() { - app.other_stage.app_url = value; - } else if app.other_stage.log_location.is_none() { - app.other_stage.log_location = value; - } else if app.other_stage.max_upload.is_none() { - app.other_stage.max_upload = value; - } else { - app.stage = 3; - } - } - _ => {} - } - } - KeyCode::Char(c) => { - app.input.push(c); - } - KeyCode::Backspace => { - app.input.pop(); - } - KeyCode::Esc => { - break; - } - _ => {} - } - } - } - close(terminal); - - Err("Unknown Error. Final Catch!".into()) -} - -fn get_next_default(app: &App) -> Option { - match app.stage { - 0 => { - if app.database_stage.user.is_none() || app.database_stage.password.is_none() { - None - } else if app.database_stage.host.is_none() { - Some("127.0.0.1".to_string()) - } else if app.database_stage.database.is_none() { - Some("nitro_repo".to_string()) - } else { - None - } - } - 2 => { - if app.other_stage.address.is_none() { - Some("0.0.0.0:6742".to_string()) - } else if app.other_stage.app_url.is_none() { - Some("http://127.0.0.1:6742".to_string()) - } else if app.other_stage.log_location.is_none() { - Some("./".to_string()) - } else if app.other_stage.max_upload.is_none() { - Some("1024".to_string()) - } else { - None - } - } - _ => None, - } -} - -fn get_next_step(app: &App) -> String { - match app.stage { - 0 => { - if app.database_stage.user.is_none() { - "Database Username".to_string() - } else if app.database_stage.password.is_none() { - "Database Password".to_string() - } else if app.database_stage.host.is_none() { - "Database Host".to_string() - } else if app.database_stage.database.is_none() { - "Database Database".to_string() - } else { - "Confirm".to_string() - } - } - 1 => { - if app.user_stage.name.is_none() { - "User Name".to_string() - } else if app.user_stage.username.is_none() { - "User Username".to_string() - } else if app.user_stage.email.is_none() { - "User Email".to_string() - } else if app.user_stage.password.is_none() { - "User Password".to_string() - } else { - "Confirm".to_string() - } - } - 2 => { - if app.other_stage.address.is_none() { - "Bind Address".to_string() - } else if app.other_stage.app_url.is_none() { - "App URL".to_string() - } else if app.other_stage.log_location.is_none() { - "Log Location".to_string() - } else if app.other_stage.max_upload.is_none() { - "Max Upload".to_string() - } else { - "Confirm".to_string() - } - } - _ => "".to_string(), - } -} - -fn create_line(key: &str, value: &str, messages: &mut Vec) { - let content = vec![Spans::from(Span::raw(format!("{key}: {value}")))]; - messages.push(ListItem::new(content)) -} - -fn ui(f: &mut Frame, app: &App) { - let chunks = Layout::default() - .direction(Direction::Vertical) - .margin(2) - .constraints( - [ - Constraint::Min(5), - Constraint::Length(1), - Constraint::Length(3), - ] - .as_ref(), - ) - .split(f.size()); - let mut messages: Vec = Vec::new(); - - create_line( - "Database Username", - app.database_stage.user.as_ref().unwrap_or(&"".to_string()), - &mut messages, - ); - create_line( - "Database Password", - app.database_stage - .password - .as_ref() - .unwrap_or(&"".to_string()), - &mut messages, - ); - create_line( - "Database Host", - app.database_stage.host.as_ref().unwrap_or(&"".to_string()), - &mut messages, - ); - create_line( - "Database Database", - app.database_stage - .database - .as_ref() - .unwrap_or(&"".to_string()), - &mut messages, - ); - let content = vec![Spans::from(Span::raw("______________User_______________"))]; - messages.push(ListItem::new(content)); - create_line( - "User Name", - app.user_stage.name.as_ref().unwrap_or(&"".to_string()), - &mut messages, - ); - create_line( - "User Username", - app.user_stage.username.as_ref().unwrap_or(&"".to_string()), - &mut messages, - ); - create_line( - "User Email", - app.user_stage.email.as_ref().unwrap_or(&"".to_string()), - &mut messages, - ); - create_line( - "User Password", - app.user_stage.password.as_ref().unwrap_or(&"".to_string()), - &mut messages, - ); - let content = vec![Spans::from(Span::raw("______________Other_______________"))]; - messages.push(ListItem::new(content)); - create_line( - "Bind Address", - app.other_stage.address.as_ref().unwrap_or(&"".to_string()), - &mut messages, - ); - create_line( - "App URL", - app.other_stage.app_url.as_ref().unwrap_or(&"".to_string()), - &mut messages, - ); - create_line( - "Log Location", - app.other_stage - .log_location - .as_ref() - .unwrap_or(&"".to_string()), - &mut messages, - ); - - create_line( - "Max Upload", - app.other_stage - .max_upload - .as_ref() - .unwrap_or(&"".to_string()), - &mut messages, - ); - - let messages = List::new(messages).block(Block::default().borders(Borders::ALL).title("Data")); - f.render_widget(messages, chunks[0]); - - let string = get_next_step(app); - - let msg = if string.eq("Confirm") { - vec![ - Span::raw("Please Enter to Confirm "), - Span::styled(". ESC", Style::default().add_modifier(Modifier::BOLD)), - Span::raw(format!(" To Restart. {}", app.stage)), - ] - } else { - vec![ - Span::raw("Please Enter "), - Span::styled( - format!("{}[{}]", string, get_next_default(app).unwrap_or_default()), - Style::default().add_modifier(Modifier::BOLD), - ), - Span::styled(". Enter", Style::default().add_modifier(Modifier::BOLD)), - Span::raw(format!(" to record the data. {}", app.stage)), - ] - }; - let mut text = Text::from(Spans::from(msg)); - text.patch_style(Style::default()); - let help_message = Paragraph::new(text); - f.render_widget(help_message, chunks[1]); - - let input = Paragraph::new(app.input.as_ref()) - .style(Style::default().fg(Color::Yellow)) - .block(Block::default().borders(Borders::ALL).title("Input")); - f.render_widget(input, chunks[2]); - f.set_cursor( - // Put cursor past the end of the input text - chunks[2].x + app.input.width() as u16 + 1, - // Move one line down, from the border to the input line - chunks[2].y + 1, - ) -} - -pub async fn load_installer(working_dir: PathBuf) -> anyhow::Result<()> { - enable_raw_mode()?; - let mut stdout = io::stdout(); - execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?; - let backend = CrosstermBackend::new(stdout); - let terminal = Terminal::new(backend)?; - - let app = run_app(terminal, App::default()).await?; - - install_data(working_dir, app) -} - -fn install_data(working_dir: PathBuf, app: App) -> Result<(), Error> { - let general = GeneralSettings { - database: app.database_stage.into(), - application: Application::from(app.other_stage), - internal: Default::default(), - session: Default::default(), - }; +pub fn install_data(working_dir: PathBuf, general: GeneralSettings) -> anyhow::Result<()> { let configs = working_dir.join("cfg"); create_dir_all(&configs)?; @@ -566,14 +42,3 @@ fn install_data(working_dir: PathBuf, app: App) -> Result<(), Error> { info!("Installation Complete"); Ok(()) } - -fn close(mut terminal: Terminal>) { - disable_raw_mode().unwrap(); - execute!( - terminal.backend_mut(), - LeaveAlternateScreen, - DisableMouseCapture - ) - .unwrap(); - terminal.show_cursor().unwrap(); -} diff --git a/backend/src/install/utils.rs b/backend/src/install/utils.rs deleted file mode 100644 index 811d2af4..00000000 --- a/backend/src/install/utils.rs +++ /dev/null @@ -1,44 +0,0 @@ -use crate::settings::models::{Application, EmailSetting, SecuritySettings, SiteSetting}; -use crate::GeneralSettings; -use log::info; -use std::fs::{create_dir_all, OpenOptions}; -use std::io::{Error, Write}; -use std::path::PathBuf; - -pub fn install_data(working_dir: PathBuf, general: GeneralSettings) -> anyhow::Result<()> { - let configs = working_dir.join("cfg"); - create_dir_all(&configs)?; - - let other = toml::to_string_pretty(&general)?; - let mut file = OpenOptions::new() - .write(true) - .append(true) - .create(true) - .open(working_dir.join("nitro_repo.toml"))?; - file.write_all(other.as_bytes())?; - - let security = toml::to_string_pretty(&SecuritySettings::default())?; - let mut file = OpenOptions::new() - .write(true) - .append(true) - .create(true) - .open(configs.join("security.toml"))?; - file.write_all(security.as_bytes())?; - - let email = toml::to_string_pretty(&EmailSetting::default())?; - let mut file = OpenOptions::new() - .write(true) - .append(true) - .create(true) - .open(configs.join("email.toml"))?; - file.write_all(email.as_bytes())?; - let site = toml::to_string_pretty(&SiteSetting::default())?; - let mut file = OpenOptions::new() - .write(true) - .append(true) - .create(true) - .open(configs.join("site.toml"))?; - file.write_all(site.as_bytes())?; - info!("Installation Complete"); - Ok(()) -} diff --git a/backend/src/lib.rs b/backend/src/lib.rs index 2e51899c..d1990c84 100644 --- a/backend/src/lib.rs +++ b/backend/src/lib.rs @@ -5,7 +5,6 @@ use tokio::sync::RwLock; use crate::settings::models::{GeneralSettings, Settings}; -pub mod api; pub mod authentication; pub mod cli; pub mod constants; diff --git a/backend/src/repository/nitro/mod.rs b/backend/src/repository/nitro/mod.rs index b120a4e3..bc091261 100644 --- a/backend/src/repository/nitro/mod.rs +++ b/backend/src/repository/nitro/mod.rs @@ -1,7 +1,6 @@ use serde::{Deserialize, Serialize}; use crate::repository::response::Project; -use crate::repository::settings::RepositoryConfig; use crate::storage::file::StorageFile; use crate::utils::get_current_time; diff --git a/backend/src/repository/response.rs b/backend/src/repository/response.rs index 83413644..6f88d9e6 100644 --- a/backend/src/repository/response.rs +++ b/backend/src/repository/response.rs @@ -9,7 +9,6 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; use crate::error::internal_error::InternalError; -use crate::repository::frontend::FrontendResponse; use crate::repository::nitro::{NitroVersion, ProjectData, VersionData}; use crate::repository::settings::RepositoryConfig; use crate::storage::file::StorageFileResponse; diff --git a/backend/src/repository/settings/badge.rs b/backend/src/repository/settings/badge.rs index 0e1a1155..ed5c1172 100644 --- a/backend/src/repository/settings/badge.rs +++ b/backend/src/repository/settings/badge.rs @@ -1,10 +1,9 @@ use badge_maker::Style; -use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::repository::settings::RepositoryConfigType; -#[derive(Debug, Clone, Serialize, JsonSchema, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct BadgeSettings { #[serde(default = "BadgeStyle::default")] pub style: BadgeStyle, @@ -38,7 +37,7 @@ fn default_label_color() -> String { "#555".to_string() } -#[derive(Debug, Clone, Serialize, JsonSchema, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub enum BadgeStyle { Flat, FlatSquare, diff --git a/backend/src/repository/settings/frontend.rs b/backend/src/repository/settings/frontend.rs index 5cab156f..655aec61 100644 --- a/backend/src/repository/settings/frontend.rs +++ b/backend/src/repository/settings/frontend.rs @@ -1,9 +1,8 @@ -use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::repository::settings::RepositoryConfigType; -#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub enum PageProvider { // Do not create a page for this projects in this repository None, @@ -20,7 +19,7 @@ impl Default for PageProvider { } /// Frontend Settings -#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Frontend { pub page_provider: PageProvider, /// The Description of the Repository diff --git a/backend/src/repository/web/multi/public/mod.rs b/backend/src/repository/web/multi/public/mod.rs index dc042524..68060846 100644 --- a/backend/src/repository/web/multi/public/mod.rs +++ b/backend/src/repository/web/multi/public/mod.rs @@ -1,4 +1,4 @@ -use actix_web::{web, Route}; +use actix_web::web; pub mod project; pub mod repositories; diff --git a/backend/src/repository/web/multi/public/project.rs b/backend/src/repository/web/multi/public/project.rs index 98c33a7b..0419548c 100644 --- a/backend/src/repository/web/multi/public/project.rs +++ b/backend/src/repository/web/multi/public/project.rs @@ -5,8 +5,6 @@ use sea_orm::DatabaseConnection; use serde::{Deserialize, Serialize}; use std::ops::Deref; -use utoipa::Component; - use crate::authentication::Authentication; use crate::error::internal_error::InternalError; diff --git a/backend/src/repository/web/multi/public/repositories.rs b/backend/src/repository/web/multi/public/repositories.rs index 4e3460f2..a7fc861c 100644 --- a/backend/src/repository/web/multi/public/repositories.rs +++ b/backend/src/repository/web/multi/public/repositories.rs @@ -5,8 +5,6 @@ use sea_orm::DatabaseConnection; use serde::{Deserialize, Serialize}; use std::ops::Deref; -use utoipa::Component; - use crate::authentication::Authentication; use crate::error::internal_error::InternalError; @@ -17,17 +15,12 @@ use crate::storage::multi::MultiStorageController; use crate::storage::DynamicStorage; use crate::system::permissions::options::{CanIDo, MissingPermission}; use crate::system::user::UserModel; -#[derive(Debug, Clone, Serialize, Deserialize, Component)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct PublicRepositoryResponse { pub name: String, pub repository_type: RepositoryType, } -#[utoipa::path( -get, -path = "/api/repositories/{storage_name}", -responses((status = 200, description = "A list of storages", body = [PublicRepositoryResponse])), -)] #[get("repositories/{storage_name}")] pub async fn get_repositories( storage_handler: web::Data, diff --git a/backend/src/storage/models.rs b/backend/src/storage/models.rs index 91573932..10f117b0 100644 --- a/backend/src/storage/models.rs +++ b/backend/src/storage/models.rs @@ -5,7 +5,6 @@ use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use serde_json::Value; use tokio::sync::RwLockReadGuard; -use utoipa::Component; use crate::repository::settings::{RepositoryConfig, RepositoryType}; use crate::storage::error::StorageError; @@ -17,7 +16,7 @@ pub static STORAGE_FILE: &str = "storages.json"; pub static STORAGE_FILE_BAK: &str = "storages.json.bak"; /// Types of Storages -#[derive(Debug, Clone, Serialize, Deserialize, Component)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub enum StorageType { LocalStorage, } @@ -60,10 +59,9 @@ impl Display for StorageStatus { } } -#[derive(Debug, Clone, Serialize, Deserialize, Component)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct StorageSaver { /// The Type of the Storage - #[component(example = StorageType::LocalStorage)] pub storage_type: StorageType, /// The Storage Config #[serde(flatten)] @@ -72,7 +70,7 @@ pub struct StorageSaver { pub handler_config: Value, } -#[derive(Debug, Clone, Serialize, Deserialize, Component)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct StorageConfig { /// The public name of the storage pub public_name: String, diff --git a/backend/src/storage/multi/web/admin.rs b/backend/src/storage/multi/web/admin.rs index 233c7e19..73c7e924 100644 --- a/backend/src/storage/multi/web/admin.rs +++ b/backend/src/storage/multi/web/admin.rs @@ -12,11 +12,6 @@ use crate::storage::multi::MultiStorageController; use crate::system::permissions::options::CanIDo; use crate::system::user::UserModel; -#[utoipa::path( -get, -path = "/api/admin/storages", -responses((status = 200, description = "A list of storages", body = [StorageSaver])), -)] #[get("/storages")] pub async fn get_storages( storage_handler: web::Data, @@ -74,17 +69,6 @@ pub async fn delete_storage( } } -#[utoipa::path( -get, -path = "/api/storages/{id}", -responses( -(status = 200, description = "Storage found succesfully", body = StorageSaver), -(status = 404, description = "Storage was not found") -), -params( -("id" = string, path, description = "Storage name"), -) -)] #[get("/storage/{name}")] pub async fn get_storage( storage_handler: web::Data, diff --git a/backend/src/storage/multi/web/public.rs b/backend/src/storage/multi/web/public.rs index 3acf9a28..30b451c8 100644 --- a/backend/src/storage/multi/web/public.rs +++ b/backend/src/storage/multi/web/public.rs @@ -1,23 +1,16 @@ use actix_web::{get, web, HttpResponse}; use sea_orm::DatabaseConnection; use serde::{Deserialize, Serialize}; -use utoipa::Component; use crate::authentication::Authentication; use crate::storage::multi::MultiStorageController; -#[derive(Debug, Clone, Serialize, Deserialize, Component)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct PublicStorageResponse { /// The List of Storages that are available to the current user pub storages: Vec, /// If the system is a multi or single storage system. If False storages will contain only one element named System pub multi_storage: bool, } -#[utoipa::path( -get, -path = "/api/storages", -responses((status = 200, description = "A list of storages", body = PublicStorageResponse)), - -)] #[get("/storages")] pub async fn get_storages_multi( storage_handler: web::Data, diff --git a/backend/src/system/mod.rs b/backend/src/system/mod.rs index df4a3aa9..3155d68e 100644 --- a/backend/src/system/mod.rs +++ b/backend/src/system/mod.rs @@ -1,6 +1,6 @@ use argon2::password_hash::SaltString; use argon2::{Argon2, PasswordHasher}; -use rand_core::OsRng; +use rand::rngs::OsRng; use crate::error::internal_error::InternalError; diff --git a/backend/src/utils.rs b/backend/src/utils.rs index cea47a47..e293a18f 100644 --- a/backend/src/utils.rs +++ b/backend/src/utils.rs @@ -7,7 +7,6 @@ use std::path::Path; use crate::authentication; use actix_web::http::header::HeaderMap; use chrono::{DateTime, Duration, Local}; -use crossterm::ExecutableCommand; use nitro_log::config::Config; use nitro_log::{LoggerBuilders, NitroLogger}; use rust_embed::RustEmbed; From a74b76e83a443c39ceed901a415deb5010122a9d Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Wed, 20 Jul 2022 10:39:36 -0400 Subject: [PATCH 36/76] Fix session --- backend/src/authentication/middleware.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/backend/src/authentication/middleware.rs b/backend/src/authentication/middleware.rs index d14fa49a..65f28efa 100644 --- a/backend/src/authentication/middleware.rs +++ b/backend/src/authentication/middleware.rs @@ -217,10 +217,7 @@ where cookie.set_secure(true); cookie.set_same_site(SameSite::None); cookie.set_path("/"); - cookie.set_expires(Expiration::DateTime( - OffsetDateTime::from_unix_timestamp(session.expiration as i64) - .expect("Time has Broken. its is the end times"), - )); + cookie.set_expires(Expiration::Session); let cookie_encoded = cookie.encoded().to_string(); trace!("Sending Cookie Response {}", &cookie_encoded); let val = HeaderValue::from_str(&cookie_encoded).unwrap(); From 2fafbe094be7d06a782eda449d9062cfc9ad383e Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Wed, 20 Jul 2022 12:02:37 -0400 Subject: [PATCH 37/76] Added the concept of a ProxyMavenRepository --- backend/src/repository/ci/mod.rs | 8 +- backend/src/repository/docker/mod.rs | 9 +- backend/src/repository/handler.rs | 69 +++++--- backend/src/repository/maven/hosted.rs | 132 +++++++++++++++ backend/src/repository/maven/mod.rs | 150 ++++++------------ backend/src/repository/maven/models.rs | 18 ++- backend/src/repository/maven/proxy.rs | 30 ++++ backend/src/repository/nitro/dynamic.rs | 4 +- backend/src/repository/npm/mod.rs | 8 +- backend/src/repository/raw/mod.rs | 9 +- backend/src/repository/web/multi/admin.rs | 39 ++++- .../repository/web/multi/public/project.rs | 2 +- 12 files changed, 327 insertions(+), 151 deletions(-) create mode 100644 backend/src/repository/maven/hosted.rs create mode 100644 backend/src/repository/maven/proxy.rs diff --git a/backend/src/repository/ci/mod.rs b/backend/src/repository/ci/mod.rs index 094cbc4d..0763d93e 100644 --- a/backend/src/repository/ci/mod.rs +++ b/backend/src/repository/ci/mod.rs @@ -1,3 +1,4 @@ +use crate::error::internal_error::InternalError; use crate::repository::handler::RepositoryHandler; use crate::repository::settings::RepositoryConfig; use crate::storage::models::Storage; @@ -9,8 +10,11 @@ pub struct CIHandler<'a, StorageType: Storage> { storage: RwLockReadGuard<'a, StorageType>, } impl<'a, StorageType: Storage> CIHandler<'a, StorageType> { - pub fn create(config: RepositoryConfig, storage: RwLockReadGuard<'a, StorageType>) -> Self { - CIHandler { config, storage } + pub async fn create( + config: RepositoryConfig, + storage: RwLockReadGuard<'a, StorageType>, + ) -> Result, InternalError> { + Ok(CIHandler { config, storage }) } } diff --git a/backend/src/repository/docker/mod.rs b/backend/src/repository/docker/mod.rs index 08afb093..9dde81f5 100644 --- a/backend/src/repository/docker/mod.rs +++ b/backend/src/repository/docker/mod.rs @@ -1,15 +1,20 @@ +use crate::error::internal_error::InternalError; use crate::repository::handler::RepositoryHandler; use crate::repository::settings::RepositoryConfig; use crate::storage::models::Storage; use async_trait::async_trait; use tokio::sync::RwLockReadGuard; + pub struct DockerHandler<'a, StorageType: Storage> { config: RepositoryConfig, storage: RwLockReadGuard<'a, StorageType>, } impl<'a, StorageType: Storage> DockerHandler<'a, StorageType> { - pub fn create(config: RepositoryConfig, storage: RwLockReadGuard<'a, StorageType>) -> Self { - DockerHandler { config, storage } + pub async fn create( + config: RepositoryConfig, + storage: RwLockReadGuard<'a, StorageType>, + ) -> Result, InternalError> { + Ok(DockerHandler { config, storage }) } } diff --git a/backend/src/repository/handler.rs b/backend/src/repository/handler.rs index 7a9c6e89..1a3858af 100644 --- a/backend/src/repository/handler.rs +++ b/backend/src/repository/handler.rs @@ -95,34 +95,25 @@ pub trait RepositoryHandler<'a, S: Storage>: Send + Sync { .into()) } } -/// Creates a DynamicRepositoryHandler to handle all types of Repositories -/// # Arguments -/// Array + macro_rules! repository_handler { - ($($repository_type:ident,$repository_tt:tt),*) => { - pub enum DynamicRepositoryHandler<'a, StorageType: Storage> { + ($name:ident, $($repository_type:ident,$repository_tt:tt),*) => { + pub enum $name<'a, StorageType: Storage> { $( $repository_type($repository_tt<'a, StorageType>), )* } - #[inline] - pub async fn get_repository_handler( - storage: RwLockReadGuard<'_, StorageType>, - repository_config: RepositoryConfig, - ) -> Result>, InternalError> { - match repository_config.repository_type { - $( - RepositoryType::$repository_type => { - let handler = $repository_tt::create(repository_config, storage); - Ok(Some(DynamicRepositoryHandler::$repository_type(handler))) - }, - )* + // Implement From<$repository_tt> for $name + $( + impl<'a, StorageType: Storage> From<$repository_tt<'a, StorageType>> for $name<'a, StorageType> { + fn from(repository: $repository_tt<'a, StorageType>) -> Self { + $name::$repository_type(repository) } } - + )* #[async_trait] impl<'a, StorageType: Storage> RepositoryHandler<'a, StorageType> - for DynamicRepositoryHandler<'a, StorageType> + for $name<'a, StorageType> { async fn handle_get( &self, @@ -133,7 +124,7 @@ macro_rules! repository_handler { ) -> Result { match self { $( - DynamicRepositoryHandler::$repository_type(handler) => handler.handle_get( + $name::$repository_type(handler) => handler.handle_get( path, header, conn, @@ -152,7 +143,7 @@ macro_rules! repository_handler { ) -> Result { match self { $( - DynamicRepositoryHandler::$repository_type(handler) => handler.handle_post( + $name::$repository_type(handler) => handler.handle_post( path, header, conn, @@ -172,7 +163,7 @@ macro_rules! repository_handler { ) -> Result { match self { $( - DynamicRepositoryHandler::$repository_type(handler) => handler.handle_put( + $name::$repository_type(handler) => handler.handle_put( path, header, conn, @@ -192,7 +183,7 @@ macro_rules! repository_handler { ) -> Result { match self { $( - DynamicRepositoryHandler::$repository_type(handler) => handler.handle_patch( + $name::$repository_type(handler) => handler.handle_patch( path, header, conn, @@ -211,7 +202,7 @@ macro_rules! repository_handler { ) -> Result { match self { $( - DynamicRepositoryHandler::$repository_type(handler) => handler.handle_head( + $name::$repository_type(handler) => handler.handle_head( path, header, conn, @@ -221,11 +212,39 @@ macro_rules! repository_handler { } } } + } + + } +pub(crate) use repository_handler; +/// Creates a DynamicRepositoryHandler to handle all types of Repositories +/// # Arguments +/// Array +macro_rules! dynamic_repository_handler { + ($($repository_type:ident,$repository_tt:tt),*) => { + repository_handler!( + DynamicRepositoryHandler, + $($repository_type,$repository_tt),* + ); + #[inline] + pub async fn get_repository_handler( + storage: RwLockReadGuard<'_, StorageType>, + repository_config: RepositoryConfig, + ) -> Result>, InternalError> { + match repository_config.repository_type { + $( + RepositoryType::$repository_type => { + let handler = $repository_tt::create(repository_config, storage).await?; + Ok(Some(DynamicRepositoryHandler::$repository_type(handler))) + }, + )* + } + } + }; } -repository_handler!( +dynamic_repository_handler!( NPM, NPMHandler, Maven, diff --git a/backend/src/repository/maven/hosted.rs b/backend/src/repository/maven/hosted.rs new file mode 100644 index 00000000..e03ebf07 --- /dev/null +++ b/backend/src/repository/maven/hosted.rs @@ -0,0 +1,132 @@ +use crate::authentication::Authentication; +use crate::error::api_error::APIError; +use crate::error::internal_error::InternalError; +use crate::repository::handler::RepositoryHandler; +use crate::repository::maven::models::{Pom, ProxySettings}; +use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; +use crate::repository::response::RepoResponse; +use crate::repository::settings::{Policy, RepositoryConfig, Visibility}; +use crate::storage::file::StorageFileResponse; +use crate::storage::models::Storage; +use crate::system::permissions::options::CanIDo; +use crate::system::user::UserModel; +use actix_web::http::header::HeaderMap; +use actix_web::http::StatusCode; +use actix_web::web::Bytes; +use async_trait::async_trait; +use log::error; +use sea_orm::DatabaseConnection; +use tokio::sync::RwLockReadGuard; +pub struct HostedMavenRepository<'a, S: Storage> { + pub config: RepositoryConfig, + pub storage: RwLockReadGuard<'a, S>, +} +#[async_trait] +impl<'a, S: Storage> RepositoryHandler<'a, S> for HostedMavenRepository<'a, S> { + async fn handle_get( + &self, + path: &str, + _: &HeaderMap, + conn: &DatabaseConnection, + authentication: Authentication, + ) -> Result { + if self.config.visibility == Visibility::Private { + let caller: UserModel = authentication.get_user(conn).await??; + if let Some(value) = caller.can_read_from(&self.config)? { + return Err(value.into()); + } + } + + match self + .storage + .get_file_as_response(&self.config, path) + .await + .map_err(InternalError::from)? + { + StorageFileResponse::List(list) => { + let files = self.process_storage_files(list, path).await?; + Ok(RepoResponse::try_from((files, StatusCode::OK))?) + } + value => Ok(RepoResponse::FileResponse(value)), + } + } + + async fn handle_put( + &self, + path: &str, + _: &HeaderMap, + conn: &DatabaseConnection, + authentication: Authentication, + bytes: Bytes, + ) -> Result { + let caller: UserModel = authentication.get_user(conn).await??; + if let Some(_value) = caller.can_deploy_to(&self.config)? {} + match self.config.policy { + Policy::Release => { + if path.contains("-SNAPSHOT") { + return Err(APIError::from(( + "SNAPSHOT in release only", + StatusCode::BAD_REQUEST, + )) + .into()); + } + } + Policy::Snapshot => { + if !path.contains("-SNAPSHOT") { + return Err(APIError::from(( + "Release in a snapshot only", + StatusCode::BAD_REQUEST, + )) + .into()); + } + } + Policy::Mixed => {} + } + let exists = self + .storage + .save_file(&self.config, bytes.as_ref(), path) + .await + .map_err(InternalError::from)?; + + // Post Deploy Handler + if path.ends_with(".pom") { + let vec = bytes.as_ref().to_vec(); + let result = String::from_utf8(vec).map_err(APIError::bad_request)?; + let pom: Pom = serde_xml_rs::from_str(&result).map_err(APIError::bad_request)?; + + let project_folder = format!("{}/{}", pom.group_id.replace('.', "/"), pom.artifact_id); + let version_folder = format!("{}/{}", &project_folder, &pom.version); + if let Err(error) = self + .post_deploy(project_folder, version_folder, caller, pom.into()) + .await + { + error!("Unable to complete post processing Tasks {}", error); + } + } + // Everything was ok + Ok(RepoResponse::PUTResponse( + exists, + format!( + "/storages/{}/{}/{}", + &self.storage.storage_config().name, + &self.config.name, + path + ), + )) + } +} +impl NitroRepositoryHandler + for HostedMavenRepository<'_, StorageType> +{ + fn parse_project_to_directory>(value: S) -> String { + value.into().replace('.', "/").replace(':', "/") + } + + fn storage(&self) -> &StorageType { + &self.storage + } + + fn repository(&self) -> &RepositoryConfig { + &self.config + } +} diff --git a/backend/src/repository/maven/mod.rs b/backend/src/repository/maven/mod.rs index b93604ff..c6c266f7 100644 --- a/backend/src/repository/maven/mod.rs +++ b/backend/src/repository/maven/mod.rs @@ -4,13 +4,14 @@ use actix_web::web::Bytes; use async_trait::async_trait; use log::error; use sea_orm::DatabaseConnection; +use std::ops::Deref; use tokio::sync::RwLockReadGuard; use crate::authentication::Authentication; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; -use crate::repository::handler::RepositoryHandler; -use crate::repository::maven::models::Pom; +use crate::repository::handler::{repository_handler, RepositoryHandler}; +use crate::repository::maven::models::{MavenSettings, MavenType, Pom}; use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; use crate::repository::response::RepoResponse; use crate::repository::settings::{Policy, RepositoryConfig, Visibility}; @@ -18,120 +19,53 @@ use crate::storage::file::StorageFileResponse; use crate::storage::models::Storage; use crate::system::permissions::options::CanIDo; use crate::system::user::UserModel; - +use hosted::HostedMavenRepository; +use proxy::ProxyMavenRepository; pub mod error; +pub mod hosted; pub mod models; +pub mod proxy; mod utils; -pub struct MavenHandler<'a, S: Storage> { - config: RepositoryConfig, - storage: RwLockReadGuard<'a, S>, -} +use actix_web::Error; + +repository_handler!( + MavenHandler, + Hosted, + HostedMavenRepository, + Proxy, + ProxyMavenRepository +); impl<'a, S: Storage> MavenHandler<'a, S> { - pub fn create( + pub async fn create( repository: RepositoryConfig, storage: RwLockReadGuard<'a, S>, - ) -> MavenHandler<'a, S> { - MavenHandler::<'a> { - config: repository, - storage, - } - } -} - -#[async_trait] -impl<'a, S: Storage> RepositoryHandler<'a, S> for MavenHandler<'a, S> { - async fn handle_get( - &self, - path: &str, - _: &HeaderMap, - conn: &DatabaseConnection, - authentication: Authentication, - ) -> Result { - if self.config.visibility == Visibility::Private { - let caller: UserModel = authentication.get_user(conn).await??; - if let Some(value) = caller.can_read_from(&self.config)? { - return Err(value.into()); - } - } - - match self - .storage - .get_file_as_response(&self.config, path) - .await - .map_err(InternalError::from)? - { - StorageFileResponse::List(list) => { - let files = self.process_storage_files(list, path).await?; - Ok(RepoResponse::try_from((files, StatusCode::OK))?) - } - value => Ok(RepoResponse::FileResponse(value)), - } - } - - async fn handle_put( - &self, - path: &str, - _: &HeaderMap, - conn: &DatabaseConnection, - authentication: Authentication, - bytes: Bytes, - ) -> Result { - let caller: UserModel = authentication.get_user(conn).await??; - if let Some(_value) = caller.can_deploy_to(&self.config)? {} - match self.config.policy { - Policy::Release => { - if path.contains("-SNAPSHOT") { - return Err(APIError::from(( - "SNAPSHOT in release only", - StatusCode::BAD_REQUEST, - )) - .into()); + ) -> Result, InternalError> { + let result = repository + .get_config::(storage.deref()) + .await?; + if let Some(config) = result { + match config.repository_type { + MavenType::Hosted => Ok(HostedMavenRepository { + config: repository, + storage, } - } - Policy::Snapshot => { - if !path.contains("-SNAPSHOT") { - return Err(APIError::from(( - "Release in a snapshot only", - StatusCode::BAD_REQUEST, - )) - .into()); + .into()), + MavenType::Proxy { proxies } => Ok(ProxyMavenRepository { + config: repository, + proxy: proxies, + storage, } + .into()), } - Policy::Mixed => {} - } - let exists = self - .storage - .save_file(&self.config, bytes.as_ref(), path) - .await - .map_err(InternalError::from)?; - - // Post Deploy Handler - if path.ends_with(".pom") { - let vec = bytes.as_ref().to_vec(); - let result = String::from_utf8(vec).map_err(APIError::bad_request)?; - let pom: Pom = serde_xml_rs::from_str(&result).map_err(APIError::bad_request)?; - - let project_folder = format!("{}/{}", pom.group_id.replace('.', "/"), pom.artifact_id); - let version_folder = format!("{}/{}", &project_folder, &pom.version); - if let Err(error) = self - .post_deploy(project_folder, version_folder, caller, pom.into()) - .await - { - error!("Unable to complete post processing Tasks {}", error); + } else { + Ok(HostedMavenRepository { + config: repository, + storage, } + .into()) } - // Everything was ok - Ok(RepoResponse::PUTResponse( - exists, - format!( - "/storages/{}/{}/{}", - &self.storage.storage_config().name, - &self.config.name, - path - ), - )) } } @@ -141,10 +75,16 @@ impl NitroRepositoryHandler for MavenHandler< } fn storage(&self) -> &StorageType { - &self.storage + match self { + MavenHandler::Hosted(repository) => &repository.storage, + MavenHandler::Proxy(repository) => &repository.storage, + } } fn repository(&self) -> &RepositoryConfig { - &self.config + match self { + MavenHandler::Hosted(repository) => &repository.config, + MavenHandler::Proxy(repository) => &repository.config, + } } } diff --git a/backend/src/repository/maven/models.rs b/backend/src/repository/maven/models.rs index 524c7c9a..e59c5886 100644 --- a/backend/src/repository/maven/models.rs +++ b/backend/src/repository/maven/models.rs @@ -5,7 +5,23 @@ use crate::repository::settings::RepositoryConfigType; use crate::utils::get_current_time; #[derive(Debug, Serialize, Deserialize, Clone, Default)] -pub struct MavenSettings {} +pub struct MavenSettings { + pub repository_type: MavenType, +} +#[derive(Debug, Serialize, Deserialize, Clone, Default)] +pub enum MavenType { + #[default] + Hosted, + Proxy { + proxies: Vec, + }, +} +#[derive(Debug, Serialize, Deserialize, Clone, Default)] +pub struct ProxySettings { + pub proxy_url: String, + pub proxy_username: String, + pub proxy_password: String, +} impl RepositoryConfigType for MavenSettings { fn config_name() -> &'static str { diff --git a/backend/src/repository/maven/proxy.rs b/backend/src/repository/maven/proxy.rs new file mode 100644 index 00000000..ce509e68 --- /dev/null +++ b/backend/src/repository/maven/proxy.rs @@ -0,0 +1,30 @@ +use crate::repository::handler::RepositoryHandler; +use crate::repository::maven::models::ProxySettings; +use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; +use crate::repository::settings::RepositoryConfig; +use crate::storage::models::Storage; +use async_trait::async_trait; +use tokio::sync::RwLockReadGuard; + +pub struct ProxyMavenRepository<'a, S: Storage> { + pub config: RepositoryConfig, + pub proxy: Vec, + pub storage: RwLockReadGuard<'a, S>, +} +#[async_trait] +impl<'a, S: Storage> RepositoryHandler<'a, S> for ProxyMavenRepository<'a, S> {} +impl NitroRepositoryHandler + for ProxyMavenRepository<'_, StorageType> +{ + fn parse_project_to_directory>(value: S) -> String { + value.into().replace('.', "/").replace(':', "/") + } + + fn storage(&self) -> &StorageType { + &self.storage + } + + fn repository(&self) -> &RepositoryConfig { + &self.config + } +} diff --git a/backend/src/repository/nitro/dynamic.rs b/backend/src/repository/nitro/dynamic.rs index 5ed66219..f2d49dd3 100644 --- a/backend/src/repository/nitro/dynamic.rs +++ b/backend/src/repository/nitro/dynamic.rs @@ -24,14 +24,14 @@ macro_rules! nitro_repo_handler { )* } #[inline] - pub fn get_nitro_handler( + pub async fn get_nitro_handler( storage: RwLockReadGuard<'_, StorageType>, repository_config: RepositoryConfig, ) -> Result, InternalError> { match repository_config.repository_type { $( RepositoryType::$name => { - let handler = $ty::create(repository_config, storage); + let handler = $ty::create(repository_config, storage).await?; Ok(NitroRepoHandler::Supported(DynamicNitroRepositoryHandler::$name(handler))) }, )* diff --git a/backend/src/repository/npm/mod.rs b/backend/src/repository/npm/mod.rs index ce68738f..fdd47038 100644 --- a/backend/src/repository/npm/mod.rs +++ b/backend/src/repository/npm/mod.rs @@ -34,14 +34,14 @@ pub struct NPMHandler<'a, StorageType: Storage> { } impl<'a, StorageType: Storage> NPMHandler<'a, StorageType> { - pub fn create( + pub async fn create( repository: RepositoryConfig, storage: RwLockReadGuard<'a, StorageType>, - ) -> NPMHandler<'a, StorageType> { - NPMHandler { + ) -> Result, InternalError> { + Ok(NPMHandler { config: repository, storage, - } + }) } fn bad_npm_command() -> actix_web::Error { APIError::from(("Bad NPM Command", StatusCode::BAD_REQUEST)).into() diff --git a/backend/src/repository/raw/mod.rs b/backend/src/repository/raw/mod.rs index bf61b98c..f5fe3c62 100644 --- a/backend/src/repository/raw/mod.rs +++ b/backend/src/repository/raw/mod.rs @@ -1,15 +1,20 @@ +use crate::error::internal_error::InternalError; use crate::repository::handler::RepositoryHandler; use crate::repository::settings::RepositoryConfig; use crate::storage::models::Storage; use async_trait::async_trait; use tokio::sync::RwLockReadGuard; + pub struct RawHandler<'a, StorageType: Storage> { config: RepositoryConfig, storage: RwLockReadGuard<'a, StorageType>, } impl<'a, StorageType: Storage> RawHandler<'a, StorageType> { - pub fn create(config: RepositoryConfig, storage: RwLockReadGuard<'a, StorageType>) -> Self { - RawHandler { config, storage } + pub async fn create( + config: RepositoryConfig, + storage: RwLockReadGuard<'a, StorageType>, + ) -> Result, InternalError> { + Ok(RawHandler { config, storage }) } } diff --git a/backend/src/repository/web/multi/admin.rs b/backend/src/repository/web/multi/admin.rs index 1ddb0729..139c9061 100644 --- a/backend/src/repository/web/multi/admin.rs +++ b/backend/src/repository/web/multi/admin.rs @@ -10,7 +10,8 @@ use crate::authentication::Authentication; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; -use crate::repository::settings::{Policy, Visibility}; +use crate::repository::maven::models::MavenSettings; +use crate::repository::settings::{Policy, RepositoryConfig, Visibility}; use crate::repository::web::RepositoryResponse; use crate::repository::RepositoryType; use crate::storage::error::StorageError; @@ -19,6 +20,9 @@ use crate::storage::multi::MultiStorageController; use crate::system::permissions::options::CanIDo; use crate::system::user::UserModel; use paste::paste; +use serde_json::Value; +use tokio::sync::RwLockReadGuard; + /// Get all repositories from the storage #[get("/repositories/{storage_name}")] pub async fn get_repositories( @@ -47,25 +51,46 @@ pub async fn create_repository( database: web::Data, auth: Authentication, query_params: web::Path<(String, String, RepositoryType)>, + inner_config: web::Json>, ) -> actix_web::Result { let user: UserModel = auth.get_user(&database).await??; user.can_i_edit_repos()?; let (storage_name, repository_name, repository_type) = query_params.into_inner(); let storage = crate::helpers::get_storage!(storage_handler, storage_name); - if let Err(error) = storage - .create_repository(repository_name, repository_type) + match storage + .create_repository(repository_name.clone(), repository_type) .await { - return match error { + Ok(()) => { + let repository_config = storage + .get_repository(repository_name.as_str()) + .await + .map_err(actix_web::error::ErrorInternalServerError)?; + match repository_config { + None => Ok(HttpResponse::InternalServerError().finish()), + Some(config) => { + if let Some(inner_config) = inner_config.into_inner() { + match config.repository_type { + RepositoryType::Maven => { + let maven: MavenSettings = serde_json::from_value(inner_config) + .map_err(actix_web::error::ErrorBadRequest)?; + config.save_config(storage.deref(), Some(&maven)).await?; + } + _ => {} + } + } + Ok(HttpResponse::NoContent().finish()) + } + } + } + Err(error) => match error { StorageError::RepositoryAlreadyExists => { Err(APIError::from(("Repository already exists", StatusCode::CONFLICT)).into()) } value => Err(InternalError::from(value).into()), - }; + }, } - - Ok(HttpResponse::NoContent().finish()) } #[derive(Deserialize)] diff --git a/backend/src/repository/web/multi/public/project.rs b/backend/src/repository/web/multi/public/project.rs index 0419548c..139e9ff0 100644 --- a/backend/src/repository/web/multi/public/project.rs +++ b/backend/src/repository/web/multi/public/project.rs @@ -40,7 +40,7 @@ pub async fn get_project( return Err(value.into()); } } - let handler = get_nitro_handler(storage, repository)?; + let handler = get_nitro_handler(storage, repository).await?; match handler { NitroRepoHandler::Supported(supported) => { let value = if let Some(version) = version { From c32daeffcf56f07abab6eeea1177105e22e4e953 Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Wed, 20 Jul 2022 12:38:07 -0400 Subject: [PATCH 38/76] Staging Layout --- backend/src/repository/maven/mod.rs | 22 ++++++++++- backend/src/repository/maven/models.rs | 24 +++++++++--- backend/src/repository/maven/staging.rs | 52 +++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 7 deletions(-) create mode 100644 backend/src/repository/maven/staging.rs diff --git a/backend/src/repository/maven/mod.rs b/backend/src/repository/maven/mod.rs index c6c266f7..5d790a97 100644 --- a/backend/src/repository/maven/mod.rs +++ b/backend/src/repository/maven/mod.rs @@ -21,10 +21,12 @@ use crate::system::permissions::options::CanIDo; use crate::system::user::UserModel; use hosted::HostedMavenRepository; use proxy::ProxyMavenRepository; +use staging::StagingRepository; pub mod error; pub mod hosted; pub mod models; pub mod proxy; +mod staging; mod utils; use actix_web::Error; @@ -34,7 +36,9 @@ repository_handler!( Hosted, HostedMavenRepository, Proxy, - ProxyMavenRepository + ProxyMavenRepository, + Staging, + StagingRepository ); impl<'a, S: Storage> MavenHandler<'a, S> { @@ -47,7 +51,7 @@ impl<'a, S: Storage> MavenHandler<'a, S> { .await?; if let Some(config) = result { match config.repository_type { - MavenType::Hosted => Ok(HostedMavenRepository { + MavenType::Hosted { .. } => Ok(HostedMavenRepository { config: repository, storage, } @@ -58,6 +62,18 @@ impl<'a, S: Storage> MavenHandler<'a, S> { storage, } .into()), + MavenType::Staging { + stage_to, + pre_stage_requirements, + } => { + let staging = StagingRepository { + config: repository, + stage_to, + storage, + deploy_requirement: pre_stage_requirements, + }; + Ok(staging.into()) + } } } else { Ok(HostedMavenRepository { @@ -78,6 +94,7 @@ impl NitroRepositoryHandler for MavenHandler< match self { MavenHandler::Hosted(repository) => &repository.storage, MavenHandler::Proxy(repository) => &repository.storage, + MavenHandler::Staging(repository) => &repository.storage, } } @@ -85,6 +102,7 @@ impl NitroRepositoryHandler for MavenHandler< match self { MavenHandler::Hosted(repository) => &repository.config, MavenHandler::Proxy(repository) => &repository.config, + MavenHandler::Staging(repository) => &repository.config, } } } diff --git a/backend/src/repository/maven/models.rs b/backend/src/repository/maven/models.rs index e59c5886..5b80319d 100644 --- a/backend/src/repository/maven/models.rs +++ b/backend/src/repository/maven/models.rs @@ -1,3 +1,4 @@ +use crate::repository::maven::staging::{DeployRequirement, StageSettings}; use serde::{Deserialize, Serialize}; use crate::repository::nitro::VersionData; @@ -8,13 +9,26 @@ use crate::utils::get_current_time; pub struct MavenSettings { pub repository_type: MavenType, } -#[derive(Debug, Serialize, Deserialize, Clone, Default)] + +#[derive(Debug, Serialize, Deserialize, Clone)] pub enum MavenType { - #[default] - Hosted, - Proxy { - proxies: Vec, + /// Hosted on the Storage Only + Hosted { allow_pushing: bool }, + /// An intermediary repository for intake of new artifacts. Pushes the artifacts to other repositories + Staging { + stage_to: Vec, + pre_stage_requirements: Vec, }, + /// Uses Remote Proxies to get the artifacts. + /// Uses the storage to hold a backup of the artifacts. + Proxy { proxies: Vec }, +} +impl Default for MavenType { + fn default() -> Self { + MavenType::Hosted { + allow_pushing: true, + } + } } #[derive(Debug, Serialize, Deserialize, Clone, Default)] pub struct ProxySettings { diff --git a/backend/src/repository/maven/staging.rs b/backend/src/repository/maven/staging.rs new file mode 100644 index 00000000..d6ff867d --- /dev/null +++ b/backend/src/repository/maven/staging.rs @@ -0,0 +1,52 @@ +use crate::repository::handler::RepositoryHandler; +use crate::repository::maven::models::ProxySettings; +use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; +use crate::repository::settings::RepositoryConfig; +use crate::storage::models::Storage; +use async_trait::async_trait; +use serde::{Deserialize, Serialize}; +use tokio::sync::RwLockReadGuard; +#[derive(Debug, Serialize, Deserialize, Clone)] +pub enum StageSettings { + InternalRepository { + storage: String, + repository: String, + }, + // The Po mans Repository. (For https://github.com/NickAcPT) + GitPush { + git_url: String, + git_branch: String, + git_username: String, + git_password: String, + }, + ExternalRepository { + repository: String, + username: String, + password: String, + }, +} +#[derive(Debug, Serialize, Deserialize, Clone)] +pub enum DeployRequirement {} +pub struct StagingRepository<'a, S: Storage> { + pub config: RepositoryConfig, + pub storage: RwLockReadGuard<'a, S>, + pub stage_to: Vec, + pub deploy_requirement: Vec, +} +#[async_trait] +impl<'a, S: Storage> RepositoryHandler<'a, S> for StagingRepository<'a, S> {} +impl NitroRepositoryHandler + for StagingRepository<'_, StorageType> +{ + fn parse_project_to_directory>(value: S) -> String { + value.into().replace('.', "/").replace(':', "/") + } + + fn storage(&self) -> &StorageType { + &self.storage + } + + fn repository(&self) -> &RepositoryConfig { + &self.config + } +} From 45d47d22047b038bf5f9637b6493027593e26787 Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Wed, 20 Jul 2022 15:03:57 -0400 Subject: [PATCH 39/76] Proof of concept with proxy --- backend/Cargo.toml | 6 +- backend/src/bin/nitro_repo_full.rs | 1 + backend/src/repository/maven/models.rs | 9 ++- backend/src/repository/maven/proxy.rs | 84 +++++++++++++++++++++++- backend/src/storage/bad_storage.rs | 11 ++++ backend/src/storage/local_storage/mod.rs | 39 +++++++++++ backend/src/storage/mod.rs | 14 ++++ backend/src/storage/models.rs | 9 +++ backend/src/storage/multi/mod.rs | 2 +- 9 files changed, 168 insertions(+), 7 deletions(-) diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 25343646..b0dc1499 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -48,7 +48,11 @@ tokio = { version = "1.20.0", features = ["full"] } uuid = { version = "1.1.2", features = ["serde", "v4"] } style-term = "1.0.0" mime_guess = "2.0.4" -paste="1.0.7" +paste = "1.0.7" +reqwest = { version = "0.11.11", features = ["stream"] } +bytes = "1.2.0" +tokio-stream = "0.1.9" +lockfree = "0.5.1" # Log nitro_log = { git = "https://github.com/wyatt-herkamp/nitro_log", features = ["chrono", "style-term"] } log = { version = "0.4.17", features = ["kv_unstable", "kv_unstable_std", "kv_unstable_serde"] } diff --git a/backend/src/bin/nitro_repo_full.rs b/backend/src/bin/nitro_repo_full.rs index c8b06075..8cca37b0 100644 --- a/backend/src/bin/nitro_repo_full.rs +++ b/backend/src/bin/nitro_repo_full.rs @@ -11,6 +11,7 @@ use actix_web::{web, App, HttpServer}; use api::authentication::middleware::HandleSession; use api::authentication::session::SessionManager; use api::cli::handle_cli; +use api::repository::maven::models::{MavenSettings, MavenType, ProxySettings}; use api::settings::load_configs; use api::settings::models::GeneralSettings; use api::storage::multi::MultiStorageController; diff --git a/backend/src/repository/maven/models.rs b/backend/src/repository/maven/models.rs index 5b80319d..01a71a28 100644 --- a/backend/src/repository/maven/models.rs +++ b/backend/src/repository/maven/models.rs @@ -11,6 +11,7 @@ pub struct MavenSettings { } #[derive(Debug, Serialize, Deserialize, Clone)] +#[serde(tag = "page_type", content = "content")] pub enum MavenType { /// Hosted on the Storage Only Hosted { allow_pushing: bool }, @@ -33,8 +34,12 @@ impl Default for MavenType { #[derive(Debug, Serialize, Deserialize, Clone, Default)] pub struct ProxySettings { pub proxy_url: String, - pub proxy_username: String, - pub proxy_password: String, + pub proxy_username: Option, +} +#[derive(Debug, Serialize, Deserialize, Clone, Default)] +pub struct LoginSettings { + pub username: String, + pub password: String, } impl RepositoryConfigType for MavenSettings { diff --git a/backend/src/repository/maven/proxy.rs b/backend/src/repository/maven/proxy.rs index ce509e68..f215c22f 100644 --- a/backend/src/repository/maven/proxy.rs +++ b/backend/src/repository/maven/proxy.rs @@ -1,18 +1,96 @@ +use crate::authentication::Authentication; +use crate::error::internal_error::InternalError; use crate::repository::handler::RepositoryHandler; use crate::repository::maven::models::ProxySettings; use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; -use crate::repository::settings::RepositoryConfig; +use crate::repository::response::RepoResponse; +use crate::repository::settings::{RepositoryConfig, Visibility}; +use crate::storage::file::StorageFileResponse; use crate::storage::models::Storage; +use crate::system::permissions::options::CanIDo; +use crate::system::user::UserModel; +use actix_web::http::header::HeaderMap; +use actix_web::http::StatusCode; +use actix_web::web::Bytes; +use actix_web::{Error, HttpResponse}; use async_trait::async_trait; +use bytes::{BufMut, BytesMut}; +use futures::channel::mpsc::unbounded; +use futures_util::stream::StreamExt; +use futures_util::SinkExt; +use sea_orm::DatabaseConnection; +use tokio::io::{duplex, AsyncWriteExt}; use tokio::sync::RwLockReadGuard; - pub struct ProxyMavenRepository<'a, S: Storage> { pub config: RepositoryConfig, pub proxy: Vec, pub storage: RwLockReadGuard<'a, S>, } #[async_trait] -impl<'a, S: Storage> RepositoryHandler<'a, S> for ProxyMavenRepository<'a, S> {} +impl<'a, S: Storage> RepositoryHandler<'a, S> for ProxyMavenRepository<'a, S> { + async fn handle_get( + &self, + path: &str, + http: &HeaderMap, + conn: &DatabaseConnection, + authentication: Authentication, + ) -> Result { + if self.config.visibility == Visibility::Private { + let caller: UserModel = authentication.get_user(conn).await??; + if let Some(value) = caller.can_read_from(&self.config)? { + return Err(value.into()); + } + } + + match self + .storage + .get_file_as_response(&self.config, path) + .await + .map_err(InternalError::from)? + { + StorageFileResponse::List(list) => { + let files = self.process_storage_files(list, path).await?; + Ok(RepoResponse::try_from((files, StatusCode::OK))?) + } + + StorageFileResponse::NotFound => { + let builder = reqwest::ClientBuilder::new() + .user_agent("Nitro Repo Proxy Service") + .build() + .unwrap(); + for proxy in &self.proxy { + let url = format!("{}/{}", proxy.proxy_url, path); + let mut response = builder.get(&url).send().await; + if let Ok(mut response) = response { + if response.status().is_success() { + let mut stream = response.bytes_stream(); + let (mut server, mut client) = + unbounded::>(); + let (mut file_server, mut file_client) = unbounded::(); + actix_web::rt::spawn(async move { + while let Some(chunk) = stream.next().await { + if let Ok(chunk) = chunk { + file_server.send(chunk.clone()).await.unwrap(); + server.send(Ok(chunk)).await.unwrap(); + } + } + }); + self.storage + .write_file_stream(&self.config, file_client, path) + .expect("Failed to write file stream"); + + return Ok(RepoResponse::HttpResponse( + HttpResponse::Ok().streaming(client), + )); + } + } + } + Ok(RepoResponse::FileResponse(StorageFileResponse::NotFound)) + } + v => Ok(RepoResponse::FileResponse(v)), + } + } +} impl NitroRepositoryHandler for ProxyMavenRepository<'_, StorageType> { diff --git a/backend/src/storage/bad_storage.rs b/backend/src/storage/bad_storage.rs index e78720bb..115d8cf2 100644 --- a/backend/src/storage/bad_storage.rs +++ b/backend/src/storage/bad_storage.rs @@ -1,4 +1,6 @@ use async_trait::async_trait; +use bytes::Bytes; +use futures::Stream; use log::warn; use serde::de::DeserializeOwned; use serde::Serialize; @@ -115,6 +117,15 @@ impl Storage for BadStorage { panic!("This should not be called!") } + fn write_file_stream + Unpin + Send + Sync + 'static>( + &self, + repository: &RepositoryConfig, + s: S, + location: &str, + ) -> Result { + panic!("This should not be called!") + } + async fn delete_file( &self, _repository: &RepositoryConfig, diff --git a/backend/src/storage/local_storage/mod.rs b/backend/src/storage/local_storage/mod.rs index 0066929e..76714c25 100644 --- a/backend/src/storage/local_storage/mod.rs +++ b/backend/src/storage/local_storage/mod.rs @@ -2,6 +2,8 @@ use std::collections::HashMap; use std::path::PathBuf; use async_trait::async_trait; +use bytes::Bytes; +use futures::Stream; use log::{debug, trace, warn}; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; @@ -9,6 +11,7 @@ use serde_json::Value; use tokio::fs::{create_dir_all, read_to_string, remove_dir, remove_file, OpenOptions}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::sync::{RwLock, RwLockReadGuard}; +use tokio_stream::StreamExt; use crate::repository::settings::{RepositoryConfig, RepositoryType}; use crate::repository::REPOSITORY_CONF_FOLDER; @@ -301,6 +304,42 @@ impl Storage for LocalStorage { Ok(exists) } + fn write_file_stream + Unpin + Send + Sync + 'static>( + &self, + repository: &RepositoryConfig, + mut s: S, + location: &str, + ) -> Result { + let file_location = self.get_repository_folder(&repository.name).join(location); + trace!("Saving File {:?}", &file_location); + std::fs::create_dir_all(file_location.parent().ok_or(StorageError::ParentIssue)?)?; + + let exists = if file_location.exists() { true } else { false }; + let existss = exists; + tokio::spawn(async move { + let mut s = s; + if existss { + remove_file(&file_location) + .await + .expect("Failed to remove file"); + } + let mut file_location = OpenOptions::new() + .create_new(true) + .write(true) + .open(file_location) + .await + .expect("Failed to open file"); + while let Some(chunk) = s.next().await { + file_location + .write_all(chunk.as_ref()) + .await + .expect("Failed to write file"); + } + trace!("File saved"); + }); + Ok(exists) + } + async fn delete_file( &self, repository: &RepositoryConfig, diff --git a/backend/src/storage/mod.rs b/backend/src/storage/mod.rs index 7d51087a..4c2a13dc 100644 --- a/backend/src/storage/mod.rs +++ b/backend/src/storage/mod.rs @@ -1,4 +1,6 @@ use async_trait::async_trait; +use bytes::Bytes; +use futures::Stream; use serde::de::DeserializeOwned; use serde::Serialize; use serde_json::Value; @@ -160,6 +162,18 @@ impl Storage for DynamicStorage { } } + fn write_file_stream + Unpin + Send + Sync + 'static>( + &self, + repository: &RepositoryConfig, + s: S, + location: &str, + ) -> Result { + match self { + DynamicStorage::LocalStorage(local) => local.write_file_stream(repository, s, location), + DynamicStorage::BadStorage(bad) => bad.write_file_stream(repository, s, location), + } + } + async fn delete_file( &self, repository: &RepositoryConfig, diff --git a/backend/src/storage/models.rs b/backend/src/storage/models.rs index 10f117b0..c4237825 100644 --- a/backend/src/storage/models.rs +++ b/backend/src/storage/models.rs @@ -1,10 +1,12 @@ use std::fmt::{Debug, Display, Formatter}; use async_trait::async_trait; +use bytes::Bytes; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use serde_json::Value; use tokio::sync::RwLockReadGuard; +use tokio_stream::Stream; use crate::repository::settings::{RepositoryConfig, RepositoryType}; use crate::storage::error::StorageError; @@ -165,6 +167,13 @@ pub trait Storage: Send + Sync { file: &[u8], location: &str, ) -> Result; + fn write_file_stream + Unpin + Send + Sync + 'static>( + &self, + repository: &RepositoryConfig, + s: S, + location: &str, + ) -> Result; + /// Deletes a file at a given location async fn delete_file( &self, diff --git a/backend/src/storage/multi/mod.rs b/backend/src/storage/multi/mod.rs index 72ab05f0..ef7ebb7c 100644 --- a/backend/src/storage/multi/mod.rs +++ b/backend/src/storage/multi/mod.rs @@ -55,7 +55,7 @@ pub async fn save_storages(storages: &Vec) -> Result<(), StorageEr file.write_all(result.as_bytes()).await?; Ok(()) } - +#[derive(Debug)] pub struct MultiStorageController { pub storages: RwLock>, } From 08fed4875ac4498340ca88879c2aaf43d29012be Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Thu, 21 Jul 2022 08:12:49 -0400 Subject: [PATCH 40/76] Staging Starter --- backend/Cargo.toml | 5 +- backend/src/bin/nitro_repo_full.rs | 3 +- backend/src/repository/maven/hosted.rs | 4 +- backend/src/repository/maven/mod.rs | 8 +- backend/src/repository/maven/models.rs | 43 --- backend/src/repository/maven/proxy.rs | 2 +- backend/src/repository/maven/settings.rs | 51 ++++ backend/src/repository/maven/staging.rs | 173 +++++++++++- backend/src/repository/mod.rs | 1 + backend/src/repository/staging/dynamic.rs | 58 ++++ backend/src/repository/staging/mod.rs | 35 +++ backend/src/repository/web/multi/admin.rs | 2 +- .../repository/web/multi/public/project.rs | 2 +- .../web/multi/public/repositories.rs | 2 +- backend/src/storage/dynamic.rs | 264 ++++++++++++++++++ backend/src/storage/mod.rs | 252 +---------------- backend/src/storage/models.rs | 2 +- backend/src/storage/multi/mod.rs | 2 +- 18 files changed, 602 insertions(+), 307 deletions(-) create mode 100644 backend/src/repository/maven/settings.rs create mode 100644 backend/src/repository/staging/dynamic.rs create mode 100644 backend/src/repository/staging/mod.rs create mode 100644 backend/src/storage/dynamic.rs diff --git a/backend/Cargo.toml b/backend/Cargo.toml index b0dc1499..04dd64ef 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -53,6 +53,7 @@ reqwest = { version = "0.11.11", features = ["stream"] } bytes = "1.2.0" tokio-stream = "0.1.9" lockfree = "0.5.1" + # Log nitro_log = { git = "https://github.com/wyatt-herkamp/nitro_log", features = ["chrono", "style-term"] } log = { version = "0.4.17", features = ["kv_unstable", "kv_unstable_std", "kv_unstable_serde"] } @@ -72,7 +73,9 @@ semver = "1.0.12" # Cache redis = "0.21.5" comrak = "0.14" - +# Staging +tempfile="3.3.0" +git2 = "0.14.4" [build-dependencies] vergen = "7.0.0" [features] diff --git a/backend/src/bin/nitro_repo_full.rs b/backend/src/bin/nitro_repo_full.rs index 8cca37b0..1b61e0cd 100644 --- a/backend/src/bin/nitro_repo_full.rs +++ b/backend/src/bin/nitro_repo_full.rs @@ -11,7 +11,8 @@ use actix_web::{web, App, HttpServer}; use api::authentication::middleware::HandleSession; use api::authentication::session::SessionManager; use api::cli::handle_cli; -use api::repository::maven::models::{MavenSettings, MavenType, ProxySettings}; +use api::repository::maven::settings::{MavenSettings, MavenType, ProxySettings}; +use api::repository::maven::staging::StageSettings; use api::settings::load_configs; use api::settings::models::GeneralSettings; use api::storage::multi::MultiStorageController; diff --git a/backend/src/repository/maven/hosted.rs b/backend/src/repository/maven/hosted.rs index e03ebf07..4c6f156c 100644 --- a/backend/src/repository/maven/hosted.rs +++ b/backend/src/repository/maven/hosted.rs @@ -2,7 +2,8 @@ use crate::authentication::Authentication; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; use crate::repository::handler::RepositoryHandler; -use crate::repository::maven::models::{Pom, ProxySettings}; +use crate::repository::maven::models::Pom; +use crate::repository::maven::settings::ProxySettings; use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; use crate::repository::response::RepoResponse; use crate::repository::settings::{Policy, RepositoryConfig, Visibility}; @@ -17,6 +18,7 @@ use async_trait::async_trait; use log::error; use sea_orm::DatabaseConnection; use tokio::sync::RwLockReadGuard; + pub struct HostedMavenRepository<'a, S: Storage> { pub config: RepositoryConfig, pub storage: RwLockReadGuard<'a, S>, diff --git a/backend/src/repository/maven/mod.rs b/backend/src/repository/maven/mod.rs index 5d790a97..9f1d79bf 100644 --- a/backend/src/repository/maven/mod.rs +++ b/backend/src/repository/maven/mod.rs @@ -11,7 +11,7 @@ use crate::authentication::Authentication; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; use crate::repository::handler::{repository_handler, RepositoryHandler}; -use crate::repository::maven::models::{MavenSettings, MavenType, Pom}; +use crate::repository::maven::models::Pom; use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; use crate::repository::response::RepoResponse; use crate::repository::settings::{Policy, RepositoryConfig, Visibility}; @@ -26,10 +26,12 @@ pub mod error; pub mod hosted; pub mod models; pub mod proxy; -mod staging; +pub mod settings; +pub mod staging; mod utils; use actix_web::Error; +use settings::{MavenSettings, MavenType}; repository_handler!( MavenHandler, @@ -65,12 +67,14 @@ impl<'a, S: Storage> MavenHandler<'a, S> { MavenType::Staging { stage_to, pre_stage_requirements, + parent, } => { let staging = StagingRepository { config: repository, stage_to, storage, deploy_requirement: pre_stage_requirements, + parent, }; Ok(staging.into()) } diff --git a/backend/src/repository/maven/models.rs b/backend/src/repository/maven/models.rs index 01a71a28..71809f72 100644 --- a/backend/src/repository/maven/models.rs +++ b/backend/src/repository/maven/models.rs @@ -5,49 +5,6 @@ use crate::repository::nitro::VersionData; use crate::repository::settings::RepositoryConfigType; use crate::utils::get_current_time; -#[derive(Debug, Serialize, Deserialize, Clone, Default)] -pub struct MavenSettings { - pub repository_type: MavenType, -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -#[serde(tag = "page_type", content = "content")] -pub enum MavenType { - /// Hosted on the Storage Only - Hosted { allow_pushing: bool }, - /// An intermediary repository for intake of new artifacts. Pushes the artifacts to other repositories - Staging { - stage_to: Vec, - pre_stage_requirements: Vec, - }, - /// Uses Remote Proxies to get the artifacts. - /// Uses the storage to hold a backup of the artifacts. - Proxy { proxies: Vec }, -} -impl Default for MavenType { - fn default() -> Self { - MavenType::Hosted { - allow_pushing: true, - } - } -} -#[derive(Debug, Serialize, Deserialize, Clone, Default)] -pub struct ProxySettings { - pub proxy_url: String, - pub proxy_username: Option, -} -#[derive(Debug, Serialize, Deserialize, Clone, Default)] -pub struct LoginSettings { - pub username: String, - pub password: String, -} - -impl RepositoryConfigType for MavenSettings { - fn config_name() -> &'static str { - "maven.json" - } -} - #[derive(Debug, Serialize, Deserialize, Clone)] pub struct DeployMetadata { #[serde(rename = "groupId")] diff --git a/backend/src/repository/maven/proxy.rs b/backend/src/repository/maven/proxy.rs index f215c22f..557f6884 100644 --- a/backend/src/repository/maven/proxy.rs +++ b/backend/src/repository/maven/proxy.rs @@ -1,7 +1,7 @@ use crate::authentication::Authentication; use crate::error::internal_error::InternalError; use crate::repository::handler::RepositoryHandler; -use crate::repository::maven::models::ProxySettings; +use crate::repository::maven::settings::ProxySettings; use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; use crate::repository::response::RepoResponse; use crate::repository::settings::{RepositoryConfig, Visibility}; diff --git a/backend/src/repository/maven/settings.rs b/backend/src/repository/maven/settings.rs new file mode 100644 index 00000000..37476d71 --- /dev/null +++ b/backend/src/repository/maven/settings.rs @@ -0,0 +1,51 @@ +use crate::repository::maven::staging::{DeployRequirement, StageSettings}; +use crate::repository::settings::RepositoryConfigType; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize, Clone, Default)] +pub struct MavenSettings { + pub repository_type: MavenType, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +#[serde(tag = "page_type", content = "content")] +pub enum MavenType { + /// Hosted on the Storage Only + Hosted { allow_pushing: bool }, + /// An intermediary repository for intake of new artifacts. Pushes the artifacts to other repositories + Staging { + /// This is a parent that nothing is actually pushed it. It just allows for data retrieval. + parent: ProxySettings, + stage_to: Vec, + pre_stage_requirements: Vec, + }, + /// Uses Remote Proxies to get the artifacts. + /// Uses the storage to hold a backup of the artifacts. + Proxy { proxies: Vec }, +} + +impl Default for MavenType { + fn default() -> Self { + MavenType::Hosted { + allow_pushing: true, + } + } +} + +#[derive(Debug, Serialize, Deserialize, Clone, Default)] +pub struct ProxySettings { + pub proxy_url: String, + pub login: Option, +} + +#[derive(Debug, Serialize, Deserialize, Clone, Default)] +pub struct LoginSettings { + pub username: String, + pub password: String, +} + +impl RepositoryConfigType for MavenSettings { + fn config_name() -> &'static str { + "maven.json" + } +} diff --git a/backend/src/repository/maven/staging.rs b/backend/src/repository/maven/staging.rs index d6ff867d..73ee773f 100644 --- a/backend/src/repository/maven/staging.rs +++ b/backend/src/repository/maven/staging.rs @@ -1,11 +1,36 @@ +use crate::authentication::Authentication; +use crate::error::api_error::APIError; +use crate::error::internal_error::InternalError; use crate::repository::handler::RepositoryHandler; -use crate::repository::maven::models::ProxySettings; +use crate::repository::maven::models::Pom; +use crate::repository::maven::settings::{MavenSettings, MavenType, ProxySettings}; use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; -use crate::repository::settings::RepositoryConfig; +use crate::repository::response::RepoResponse; +use crate::repository::settings::{Policy, RepositoryConfig, Visibility}; +use crate::repository::staging::{ProcessingStage, ProjectsToStage, StageHandler}; +use crate::storage::dynamic::DynamicStorage; +use crate::storage::file::StorageFileResponse; use crate::storage::models::Storage; +use crate::storage::multi::MultiStorageController; +use crate::system::permissions::options::CanIDo; +use crate::system::user::UserModel; +use actix_web::http::header::HeaderMap; +use actix_web::http::StatusCode; +use actix_web::web::Bytes; +use actix_web::{Error, HttpResponse}; use async_trait::async_trait; +use bytes::{BufMut, BytesMut}; +use futures::channel::mpsc::unbounded; +use futures_util::stream::StreamExt; +use futures_util::SinkExt; +use sea_orm::DatabaseConnection; use serde::{Deserialize, Serialize}; +use std::ops::Deref; +use std::path::PathBuf; +use std::sync::Arc; +use tokio::io::{duplex, AsyncWriteExt}; use tokio::sync::RwLockReadGuard; + #[derive(Debug, Serialize, Deserialize, Clone)] pub enum StageSettings { InternalRepository { @@ -31,10 +56,152 @@ pub struct StagingRepository<'a, S: Storage> { pub config: RepositoryConfig, pub storage: RwLockReadGuard<'a, S>, pub stage_to: Vec, + pub parent: ProxySettings, pub deploy_requirement: Vec, } + +impl<'a, S: Storage> StagingRepository<'a, S> { + pub async fn create( + repository: RepositoryConfig, + storage: RwLockReadGuard<'a, S>, + ) -> Result, InternalError> { + let result = repository + .get_config::(storage.deref()) + .await?; + if let Some(config) = result { + match config.repository_type { + MavenType::Staging { + stage_to, + pre_stage_requirements, + parent, + } => { + let staging = StagingRepository { + config: repository, + stage_to, + storage, + deploy_requirement: pre_stage_requirements, + parent, + }; + Ok(staging.into()) + } + _ => { + panic!("Staging Repository can only be used with Staging Repository Type"); + } + } + } else { + panic!("Staging Repository can only be used with Staging Repository Type"); + } + } +} + +#[async_trait] +impl<'a, S: Storage> StageHandler<'a, S> for StagingRepository<'a, S> { + async fn push( + &self, + directory: String, + process: ProcessingStage, + storages: Arc, + ) -> Result<(), InternalError> { + todo!() + } +} #[async_trait] -impl<'a, S: Storage> RepositoryHandler<'a, S> for StagingRepository<'a, S> {} +impl<'a, S: Storage> RepositoryHandler<'a, S> for StagingRepository<'a, S> { + async fn handle_get( + &self, + path: &str, + http: &HeaderMap, + conn: &DatabaseConnection, + authentication: Authentication, + ) -> Result { + if self.config.visibility == Visibility::Private { + let caller: UserModel = authentication.get_user(conn).await??; + if let Some(value) = caller.can_read_from(&self.config)? { + return Err(value.into()); + } + } + + match self + .storage + .get_file_as_response(&self.config, path) + .await + .map_err(InternalError::from)? + { + StorageFileResponse::List(list) => { + let files = self.process_storage_files(list, path).await?; + Ok(RepoResponse::try_from((files, StatusCode::OK))?) + } + + StorageFileResponse::NotFound => { + let builder = reqwest::ClientBuilder::new() + .user_agent("Nitro Repo Staging Service") + .build() + .unwrap(); + let url = format!("{}/{}", self.parent.proxy_url, path); + let mut response = builder.get(&url).send().await; + if let Ok(mut response) = response { + if response.status().is_success() { + let mut stream = response.bytes_stream(); + return Ok(RepoResponse::HttpResponse( + HttpResponse::Ok().streaming(stream), + )); + } + } + + Ok(RepoResponse::FileResponse(StorageFileResponse::NotFound)) + } + v => Ok(RepoResponse::FileResponse(v)), + } + } + + async fn handle_put( + &self, + path: &str, + _: &HeaderMap, + conn: &DatabaseConnection, + authentication: Authentication, + bytes: Bytes, + ) -> Result { + let caller: UserModel = authentication.get_user(conn).await??; + if let Some(_value) = caller.can_deploy_to(&self.config)? {} + match self.config.policy { + Policy::Release => { + if path.contains("-SNAPSHOT") { + return Err(APIError::from(( + "SNAPSHOT in release only", + StatusCode::BAD_REQUEST, + )) + .into()); + } + } + Policy::Snapshot => { + if !path.contains("-SNAPSHOT") { + return Err(APIError::from(( + "Release in a snapshot only", + StatusCode::BAD_REQUEST, + )) + .into()); + } + } + Policy::Mixed => {} + } + let exists = self + .storage + .save_file(&self.config, bytes.as_ref(), path) + .await + .map_err(InternalError::from)?; + // Everything was ok + Ok(RepoResponse::PUTResponse( + exists, + format!( + "/storages/{}/{}/{}", + &self.storage.storage_config().name, + &self.config.name, + path + ), + )) + } +} impl NitroRepositoryHandler for StagingRepository<'_, StorageType> { diff --git a/backend/src/repository/mod.rs b/backend/src/repository/mod.rs index d676ea53..9ea30c54 100644 --- a/backend/src/repository/mod.rs +++ b/backend/src/repository/mod.rs @@ -10,6 +10,7 @@ pub mod npm; pub mod raw; pub mod response; pub mod settings; +pub mod staging; pub mod web; pub static REPOSITORY_CONF: &str = "repository.nitro_repo"; diff --git a/backend/src/repository/staging/dynamic.rs b/backend/src/repository/staging/dynamic.rs new file mode 100644 index 00000000..02c6d6d3 --- /dev/null +++ b/backend/src/repository/staging/dynamic.rs @@ -0,0 +1,58 @@ +use super::super::maven::staging::StagingRepository; +use super::{ProcessingStage, StageHandler}; +use crate::error::internal_error::InternalError; +use crate::repository::settings::{RepositoryConfig, RepositoryType}; +use crate::storage::models::Storage; +use crate::storage::multi::MultiStorageController; +use std::sync::Arc; +use tokio::sync::RwLockReadGuard; + +macro_rules! gen_dynamic_stage { + ($($name: ident, $ty:tt),*) => { + + pub enum DynamicStageHandler<'a, StorageType: Storage> { + $( + $name($ty<'a, StorageType>), + )* + } + #[inline] + pub async fn get_stage_handler( + storage: RwLockReadGuard<'_, StorageType>, + repository_config: RepositoryConfig, + ) -> Result, InternalError> { + match repository_config.repository_type { + $( + RepositoryType::$name => { + let handler = $ty::create(repository_config, storage).await?; + Ok(StageHandlerResult::Supported(DynamicStageHandler::$name(handler))) + }, + )* + _ => Ok(StageHandlerResult::Unsupported(repository_config)), + + } + } + #[async_trait::async_trait] + impl<'a, StorageType: Storage> StageHandler<'a, StorageType> + for DynamicStageHandler<'a, StorageType>{ + async fn push( + &self, + directory: String, + process: ProcessingStage, + storages: Arc, + ) -> Result<(), InternalError>{ + match self { + $( + DynamicStageHandler::$name(handler) => handler.push(directory, process, storages).await, + )* + } + } + } + }; +} +pub enum StageHandlerResult<'a, StorageType: Storage> { + Supported(DynamicStageHandler<'a, StorageType>), + /// it is a teapot! [Teapot](https://http.cat/418) + Unsupported(RepositoryConfig), +} + +gen_dynamic_stage!(Maven, StagingRepository); diff --git a/backend/src/repository/staging/mod.rs b/backend/src/repository/staging/mod.rs new file mode 100644 index 00000000..e1effe5c --- /dev/null +++ b/backend/src/repository/staging/mod.rs @@ -0,0 +1,35 @@ +pub mod dynamic; + +use crate::error::internal_error::InternalError; +use crate::repository::response::RepoResponse; +use crate::repository::settings::RepositoryConfigType; +use crate::storage::models::Storage; +use crate::storage::multi::MultiStorageController; +use async_trait::async_trait; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use std::path::PathBuf; +use std::sync::Arc; + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct ProcessingStage { + pub files: Vec, +} +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct ProjectsToStage { + pub projects: Vec, +} +impl RepositoryConfigType for ProcessingStage { + fn config_name() -> &'static str { + "to_stage.json" + } +} +#[async_trait] +pub trait StageHandler<'a, S: Storage> { + async fn push( + &self, + directory: String, + process: ProcessingStage, + storages: Arc, + ) -> Result<(), InternalError>; +} diff --git a/backend/src/repository/web/multi/admin.rs b/backend/src/repository/web/multi/admin.rs index 139c9061..8775edaa 100644 --- a/backend/src/repository/web/multi/admin.rs +++ b/backend/src/repository/web/multi/admin.rs @@ -10,7 +10,7 @@ use crate::authentication::Authentication; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; -use crate::repository::maven::models::MavenSettings; +use crate::repository::maven::settings::MavenSettings; use crate::repository::settings::{Policy, RepositoryConfig, Visibility}; use crate::repository::web::RepositoryResponse; use crate::repository::RepositoryType; diff --git a/backend/src/repository/web/multi/public/project.rs b/backend/src/repository/web/multi/public/project.rs index 139e9ff0..753b8d30 100644 --- a/backend/src/repository/web/multi/public/project.rs +++ b/backend/src/repository/web/multi/public/project.rs @@ -10,9 +10,9 @@ use crate::error::internal_error::InternalError; use crate::repository::settings::repository_page::{PageType, RepositoryPage}; use crate::repository::settings::{RepositoryConfig, Visibility}; +use crate::storage::dynamic::DynamicStorage; use crate::storage::models::Storage; use crate::storage::multi::MultiStorageController; -use crate::storage::DynamicStorage; use crate::system::permissions::options::{CanIDo, MissingPermission}; use crate::system::user::UserModel; diff --git a/backend/src/repository/web/multi/public/repositories.rs b/backend/src/repository/web/multi/public/repositories.rs index a7fc861c..caa6f391 100644 --- a/backend/src/repository/web/multi/public/repositories.rs +++ b/backend/src/repository/web/multi/public/repositories.rs @@ -10,9 +10,9 @@ use crate::error::internal_error::InternalError; use crate::repository::settings::repository_page::{PageType, RepositoryPage}; use crate::repository::settings::{RepositoryConfig, RepositoryType, Visibility}; +use crate::storage::dynamic::DynamicStorage; use crate::storage::models::Storage; use crate::storage::multi::MultiStorageController; -use crate::storage::DynamicStorage; use crate::system::permissions::options::{CanIDo, MissingPermission}; use crate::system::user::UserModel; #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/backend/src/storage/dynamic.rs b/backend/src/storage/dynamic.rs new file mode 100644 index 00000000..329eccf5 --- /dev/null +++ b/backend/src/storage/dynamic.rs @@ -0,0 +1,264 @@ +use crate::repository::settings::{RepositoryConfig, RepositoryType}; +use crate::storage::bad_storage::BadStorage; +use crate::storage::error::StorageError; +use crate::storage::file::{StorageFile, StorageFileResponse}; +use crate::storage::local_storage::LocalStorage; +use crate::storage::models::{ + Storage, StorageConfig, StorageFactory, StorageSaver, StorageStatus, StorageType, +}; +use async_trait::async_trait; +use bytes::Bytes; +use futures::Stream; +use serde::de::DeserializeOwned; +use serde::Serialize; +use serde_json::Value; +use tokio::sync::RwLockReadGuard; + +#[derive(Debug)] +pub enum DynamicStorage { + LocalStorage(LocalStorage), + BadStorage(BadStorage), +} + +#[async_trait] +impl Storage for DynamicStorage { + fn create_new(_config: StorageFactory) -> Result + where + Self: Sized, + { + panic!("Illegal Call") + } + + fn new(_config: StorageFactory) -> Result + where + Self: Sized, + { + panic!("Illegal Call") + } + + async fn load(&mut self) -> Result<(), StorageError> { + match self { + DynamicStorage::LocalStorage(local) => local.load().await, + DynamicStorage::BadStorage(bad) => bad.load().await, + } + } + + fn unload(&mut self) -> Result<(), StorageError> { + match self { + DynamicStorage::LocalStorage(local) => local.unload(), + DynamicStorage::BadStorage(bad) => bad.unload(), + } + } + + fn config_for_saving(&self) -> StorageSaver { + match self { + DynamicStorage::LocalStorage(local) => local.config_for_saving(), + DynamicStorage::BadStorage(bad) => bad.config_for_saving(), + } + } + + fn storage_config(&self) -> &StorageConfig { + match self { + DynamicStorage::LocalStorage(local) => local.storage_config(), + DynamicStorage::BadStorage(bad) => bad.storage_config(), + } + } + + fn impl_config(&self) -> Value { + match self { + DynamicStorage::LocalStorage(local) => local.impl_config(), + DynamicStorage::BadStorage(bad) => bad.impl_config(), + } + } + + fn storage_type(&self) -> &StorageType { + match self { + DynamicStorage::LocalStorage(local) => local.storage_type(), + DynamicStorage::BadStorage(bad) => bad.storage_type(), + } + } + + fn status(&self) -> &StorageStatus { + match self { + DynamicStorage::LocalStorage(local) => local.status(), + DynamicStorage::BadStorage(bad) => bad.status(), + } + } + + async fn create_repository( + &self, + name: String, + repository_type: RepositoryType, + ) -> Result<(), StorageError> { + match self { + DynamicStorage::LocalStorage(local) => { + local.create_repository(name, repository_type).await + } + DynamicStorage::BadStorage(bad) => bad.create_repository(name, repository_type).await, + } + } + + async fn delete_repository( + &self, + repository: &RepositoryConfig, + delete_files: bool, + ) -> Result<(), StorageError> { + match self { + DynamicStorage::LocalStorage(local) => { + local.delete_repository(repository, delete_files).await + } + DynamicStorage::BadStorage(bad) => { + bad.delete_repository(repository, delete_files).await + } + } + } + + async fn get_repositories(&self) -> Result, StorageError> { + match self { + DynamicStorage::LocalStorage(local) => local.get_repositories().await, + DynamicStorage::BadStorage(bad) => bad.get_repositories().await, + } + } + + async fn get_repository( + &self, + repository: &str, + ) -> Result>, StorageError> { + match self { + DynamicStorage::LocalStorage(local) => local.get_repository(repository).await, + DynamicStorage::BadStorage(bad) => bad.get_repository(repository).await, + } + } + + async fn update_repository(&self, repository: RepositoryConfig) -> Result<(), StorageError> { + match self { + DynamicStorage::LocalStorage(local) => local.update_repository(repository).await, + DynamicStorage::BadStorage(bad) => bad.update_repository(repository).await, + } + } + + async fn save_file( + &self, + repository: &RepositoryConfig, + file: &[u8], + location: &str, + ) -> Result { + match self { + DynamicStorage::LocalStorage(local) => { + local.save_file(repository, file, location).await + } + DynamicStorage::BadStorage(bad) => bad.save_file(repository, file, location).await, + } + } + + fn write_file_stream + Unpin + Send + Sync + 'static>( + &self, + repository: &RepositoryConfig, + s: S, + location: &str, + ) -> Result { + match self { + DynamicStorage::LocalStorage(local) => local.write_file_stream(repository, s, location), + DynamicStorage::BadStorage(bad) => bad.write_file_stream(repository, s, location), + } + } + + async fn delete_file( + &self, + repository: &RepositoryConfig, + location: &str, + ) -> Result<(), StorageError> { + match self { + DynamicStorage::LocalStorage(local) => local.delete_file(repository, location).await, + DynamicStorage::BadStorage(bad) => bad.delete_file(repository, location).await, + } + } + + async fn get_file_as_response( + &self, + repository: &RepositoryConfig, + location: &str, + ) -> Result { + match self { + DynamicStorage::LocalStorage(local) => { + local.get_file_as_response(repository, location).await + } + DynamicStorage::BadStorage(bad) => bad.get_file_as_response(repository, location).await, + } + } + + async fn get_file_information( + &self, + repository: &RepositoryConfig, + location: &str, + ) -> Result, StorageError> { + match self { + DynamicStorage::LocalStorage(local) => { + local.get_file_information(repository, location).await + } + DynamicStorage::BadStorage(bad) => bad.get_file_information(repository, location).await, + } + } + + async fn get_file( + &self, + repository: &RepositoryConfig, + location: &str, + ) -> Result>, StorageError> { + match self { + DynamicStorage::LocalStorage(local) => local.get_file(repository, location).await, + DynamicStorage::BadStorage(bad) => bad.get_file(repository, location).await, + } + } + + async fn update_repository_config( + &self, + repository: &RepositoryConfig, + config_name: &str, + data: &ConfigType, + ) -> Result<(), StorageError> { + match self { + DynamicStorage::LocalStorage(local) => { + local + .update_repository_config(repository, config_name, data) + .await + } + DynamicStorage::BadStorage(bad) => { + bad.update_repository_config(repository, config_name, data) + .await + } + } + } + + async fn get_repository_config( + &self, + repository: &RepositoryConfig, + config_name: &str, + ) -> Result, StorageError> { + match self { + DynamicStorage::LocalStorage(local) => { + local.get_repository_config(repository, config_name).await + } + DynamicStorage::BadStorage(bad) => { + bad.get_repository_config(repository, config_name).await + } + } + } + + async fn delete_repository_config( + &self, + repository: &RepositoryConfig, + config_name: &str, + ) -> Result<(), StorageError> { + match self { + DynamicStorage::LocalStorage(local) => { + local + .delete_repository_config(repository, config_name) + .await + } + DynamicStorage::BadStorage(bad) => { + bad.delete_repository_config(repository, config_name).await + } + } + } +} diff --git a/backend/src/storage/mod.rs b/backend/src/storage/mod.rs index 4c2a13dc..facaad40 100644 --- a/backend/src/storage/mod.rs +++ b/backend/src/storage/mod.rs @@ -16,260 +16,12 @@ use crate::storage::models::{ }; pub mod bad_storage; +pub mod dynamic; pub mod error; pub mod file; pub mod local_storage; pub mod models; pub mod multi; - +pub use dynamic::DynamicStorage; pub static STORAGES_CONFIG: &str = "storages.nitro_repo"; pub static STORAGE_CONFIG: &str = "storage.nitro_repo"; - -#[derive(Debug)] -pub enum DynamicStorage { - LocalStorage(LocalStorage), - BadStorage(BadStorage), -} - -#[async_trait] -impl Storage for DynamicStorage { - fn create_new(_config: StorageFactory) -> Result - where - Self: Sized, - { - panic!("Illegal Call") - } - - fn new(_config: StorageFactory) -> Result - where - Self: Sized, - { - panic!("Illegal Call") - } - - async fn load(&mut self) -> Result<(), StorageError> { - match self { - DynamicStorage::LocalStorage(local) => local.load().await, - DynamicStorage::BadStorage(bad) => bad.load().await, - } - } - - fn unload(&mut self) -> Result<(), StorageError> { - match self { - DynamicStorage::LocalStorage(local) => local.unload(), - DynamicStorage::BadStorage(bad) => bad.unload(), - } - } - - fn config_for_saving(&self) -> StorageSaver { - match self { - DynamicStorage::LocalStorage(local) => local.config_for_saving(), - DynamicStorage::BadStorage(bad) => bad.config_for_saving(), - } - } - - fn storage_config(&self) -> &StorageConfig { - match self { - DynamicStorage::LocalStorage(local) => local.storage_config(), - DynamicStorage::BadStorage(bad) => bad.storage_config(), - } - } - - fn impl_config(&self) -> Value { - match self { - DynamicStorage::LocalStorage(local) => local.impl_config(), - DynamicStorage::BadStorage(bad) => bad.impl_config(), - } - } - - fn storage_type(&self) -> &StorageType { - match self { - DynamicStorage::LocalStorage(local) => local.storage_type(), - DynamicStorage::BadStorage(bad) => bad.storage_type(), - } - } - - fn status(&self) -> &StorageStatus { - match self { - DynamicStorage::LocalStorage(local) => local.status(), - DynamicStorage::BadStorage(bad) => bad.status(), - } - } - - async fn create_repository( - &self, - name: String, - repository_type: RepositoryType, - ) -> Result<(), StorageError> { - match self { - DynamicStorage::LocalStorage(local) => { - local.create_repository(name, repository_type).await - } - DynamicStorage::BadStorage(bad) => bad.create_repository(name, repository_type).await, - } - } - - async fn delete_repository( - &self, - repository: &RepositoryConfig, - delete_files: bool, - ) -> Result<(), StorageError> { - match self { - DynamicStorage::LocalStorage(local) => { - local.delete_repository(repository, delete_files).await - } - DynamicStorage::BadStorage(bad) => { - bad.delete_repository(repository, delete_files).await - } - } - } - - async fn get_repositories(&self) -> Result, StorageError> { - match self { - DynamicStorage::LocalStorage(local) => local.get_repositories().await, - DynamicStorage::BadStorage(bad) => bad.get_repositories().await, - } - } - - async fn get_repository( - &self, - repository: &str, - ) -> Result>, StorageError> { - match self { - DynamicStorage::LocalStorage(local) => local.get_repository(repository).await, - DynamicStorage::BadStorage(bad) => bad.get_repository(repository).await, - } - } - - async fn update_repository(&self, repository: RepositoryConfig) -> Result<(), StorageError> { - match self { - DynamicStorage::LocalStorage(local) => local.update_repository(repository).await, - DynamicStorage::BadStorage(bad) => bad.update_repository(repository).await, - } - } - - async fn save_file( - &self, - repository: &RepositoryConfig, - file: &[u8], - location: &str, - ) -> Result { - match self { - DynamicStorage::LocalStorage(local) => { - local.save_file(repository, file, location).await - } - DynamicStorage::BadStorage(bad) => bad.save_file(repository, file, location).await, - } - } - - fn write_file_stream + Unpin + Send + Sync + 'static>( - &self, - repository: &RepositoryConfig, - s: S, - location: &str, - ) -> Result { - match self { - DynamicStorage::LocalStorage(local) => local.write_file_stream(repository, s, location), - DynamicStorage::BadStorage(bad) => bad.write_file_stream(repository, s, location), - } - } - - async fn delete_file( - &self, - repository: &RepositoryConfig, - location: &str, - ) -> Result<(), StorageError> { - match self { - DynamicStorage::LocalStorage(local) => local.delete_file(repository, location).await, - DynamicStorage::BadStorage(bad) => bad.delete_file(repository, location).await, - } - } - - async fn get_file_as_response( - &self, - repository: &RepositoryConfig, - location: &str, - ) -> Result { - match self { - DynamicStorage::LocalStorage(local) => { - local.get_file_as_response(repository, location).await - } - DynamicStorage::BadStorage(bad) => bad.get_file_as_response(repository, location).await, - } - } - - async fn get_file_information( - &self, - repository: &RepositoryConfig, - location: &str, - ) -> Result, StorageError> { - match self { - DynamicStorage::LocalStorage(local) => { - local.get_file_information(repository, location).await - } - DynamicStorage::BadStorage(bad) => bad.get_file_information(repository, location).await, - } - } - - async fn get_file( - &self, - repository: &RepositoryConfig, - location: &str, - ) -> Result>, StorageError> { - match self { - DynamicStorage::LocalStorage(local) => local.get_file(repository, location).await, - DynamicStorage::BadStorage(bad) => bad.get_file(repository, location).await, - } - } - - async fn update_repository_config( - &self, - repository: &RepositoryConfig, - config_name: &str, - data: &ConfigType, - ) -> Result<(), StorageError> { - match self { - DynamicStorage::LocalStorage(local) => { - local - .update_repository_config(repository, config_name, data) - .await - } - DynamicStorage::BadStorage(bad) => { - bad.update_repository_config(repository, config_name, data) - .await - } - } - } - - async fn get_repository_config( - &self, - repository: &RepositoryConfig, - config_name: &str, - ) -> Result, StorageError> { - match self { - DynamicStorage::LocalStorage(local) => { - local.get_repository_config(repository, config_name).await - } - DynamicStorage::BadStorage(bad) => { - bad.get_repository_config(repository, config_name).await - } - } - } - - async fn delete_repository_config( - &self, - repository: &RepositoryConfig, - config_name: &str, - ) -> Result<(), StorageError> { - match self { - DynamicStorage::LocalStorage(local) => { - local - .delete_repository_config(repository, config_name) - .await - } - DynamicStorage::BadStorage(bad) => { - bad.delete_repository_config(repository, config_name).await - } - } - } -} diff --git a/backend/src/storage/models.rs b/backend/src/storage/models.rs index c4237825..abc5d7f5 100644 --- a/backend/src/storage/models.rs +++ b/backend/src/storage/models.rs @@ -9,10 +9,10 @@ use tokio::sync::RwLockReadGuard; use tokio_stream::Stream; use crate::repository::settings::{RepositoryConfig, RepositoryType}; +use crate::storage::dynamic::DynamicStorage; use crate::storage::error::StorageError; use crate::storage::file::{StorageFile, StorageFileResponse}; use crate::storage::local_storage::LocalStorage; -use crate::storage::DynamicStorage; pub static STORAGE_FILE: &str = "storages.json"; pub static STORAGE_FILE_BAK: &str = "storages.json.bak"; diff --git a/backend/src/storage/multi/mod.rs b/backend/src/storage/multi/mod.rs index ef7ebb7c..522cc314 100644 --- a/backend/src/storage/multi/mod.rs +++ b/backend/src/storage/multi/mod.rs @@ -8,12 +8,12 @@ use tokio::io::AsyncWriteExt; use tokio::sync::{RwLock, RwLockReadGuard}; use crate::storage::bad_storage::BadStorage; +use crate::storage::dynamic::DynamicStorage; use crate::storage::error::StorageError; use crate::storage::file::StorageFile; use crate::storage::models::{ Storage, StorageFactory, StorageSaver, StorageStatus, STORAGE_FILE, STORAGE_FILE_BAK, }; -use crate::storage::DynamicStorage; pub mod web; From 61097dfb26d87fa1953c11dde2d9b73ab1d50f7a Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Thu, 21 Jul 2022 14:16:44 -0400 Subject: [PATCH 41/76] Repositories with State --- backend/Cargo.toml | 1 - backend/src/bin/nitro_repo_full.rs | 13 + backend/src/helpers.rs | 1 - backend/src/repository/ci/mod.rs | 23 +- backend/src/repository/docker/mod.rs | 24 +- backend/src/repository/handler.rs | 98 +++--- backend/src/repository/maven/hosted.rs | 44 ++- backend/src/repository/maven/mod.rs | 36 +-- backend/src/repository/maven/models.rs | 4 +- backend/src/repository/maven/proxy.rs | 38 +-- backend/src/repository/maven/staging.rs | 56 ++-- backend/src/repository/mod.rs | 1 - backend/src/repository/nitro/dynamic.rs | 98 ++---- backend/src/repository/nitro/mod.rs | 1 - .../src/repository/nitro/nitro_repository.rs | 70 +++-- .../src/repository/nitro/post_deploy/mod.rs | 1 - backend/src/repository/npm/mod.rs | 46 ++- backend/src/repository/raw/mod.rs | 23 +- backend/src/repository/settings/mod.rs | 30 +- backend/src/repository/staging/dynamic.rs | 28 +- backend/src/repository/staging/mod.rs | 7 +- backend/src/repository/web/mod.rs | 9 +- backend/src/repository/web/multi/admin.rs | 75 +---- backend/src/repository/web/multi/configs.rs | 6 +- backend/src/repository/web/multi/mod.rs | 18 +- .../repository/web/multi/public/project.rs | 53 ++-- .../web/multi/public/repositories.rs | 25 +- .../web/multi/repository_handler.rs | 61 ++-- backend/src/storage/bad_storage.rs | 164 +--------- backend/src/storage/dynamic.rs | 264 ---------------- backend/src/storage/local_storage/mod.rs | 292 ++++++------------ backend/src/storage/mod.rs | 166 +++++++++- backend/src/storage/models.rs | 132 +++----- backend/src/storage/multi/mod.rs | 159 ++++------ backend/src/storage/multi/web/admin.rs | 14 +- backend/src/storage/multi/web/public.rs | 3 +- 36 files changed, 743 insertions(+), 1341 deletions(-) delete mode 100644 backend/src/repository/nitro/post_deploy/mod.rs delete mode 100644 backend/src/storage/dynamic.rs diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 04dd64ef..aa3f9c83 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -35,7 +35,6 @@ serde_json = "1.0.82" futures = "0.3.21" serde-xml-rs = "0.5.1" toml = "0.5.9" - # utils rand = "0.8.5" rust-embed = { version = "6.4.0", features = ["interpolate-folder-path"] } diff --git a/backend/src/bin/nitro_repo_full.rs b/backend/src/bin/nitro_repo_full.rs index 1b61e0cd..23cfccf2 100644 --- a/backend/src/bin/nitro_repo_full.rs +++ b/backend/src/bin/nitro_repo_full.rs @@ -15,7 +15,9 @@ use api::repository::maven::settings::{MavenSettings, MavenType, ProxySettings}; use api::repository::maven::staging::StageSettings; use api::settings::load_configs; use api::settings::models::GeneralSettings; +use api::storage::local_storage::LocalConfig; use api::storage::multi::MultiStorageController; +use api::storage::{GeneralConfig, StorageConfig, StorageSaver, StorageType}; use api::utils::load_logger; use api::{frontend, repository, storage, system, NitroRepo}; use log::info; @@ -25,6 +27,17 @@ use tokio::sync::RwLock; #[main] async fn main() -> std::io::Result<()> { + let test = StorageSaver { + storage_type: StorageType::LocalStorage, + generic_config: GeneralConfig { + id: "public".to_string(), + created: 0, + }, + handler_config: StorageConfig::LocalStorage(LocalConfig { + location: Default::default(), + }), + }; + println!("{}", serde_json::to_string_pretty(&test).unwrap()); if handle_cli().await.map_err(convert_error)? { return Ok(()); } diff --git a/backend/src/helpers.rs b/backend/src/helpers.rs index 47113319..4b159a01 100644 --- a/backend/src/helpers.rs +++ b/backend/src/helpers.rs @@ -26,7 +26,6 @@ macro_rules! get_repository { ($storage:ident, $repository:ident) => { if let Some(value) = $storage .get_repository(&$repository) - .await .map_err(actix_web::error::ErrorInternalServerError)? { value diff --git a/backend/src/repository/ci/mod.rs b/backend/src/repository/ci/mod.rs index 0763d93e..24cd24dd 100644 --- a/backend/src/repository/ci/mod.rs +++ b/backend/src/repository/ci/mod.rs @@ -1,22 +1,31 @@ use crate::error::internal_error::InternalError; -use crate::repository::handler::RepositoryHandler; +use crate::repository::handler::Repository; use crate::repository::settings::RepositoryConfig; use crate::storage::models::Storage; use async_trait::async_trait; +use std::sync::Arc; use tokio::sync::RwLockReadGuard; -pub struct CIHandler<'a, StorageType: Storage> { +pub struct CIHandler { config: RepositoryConfig, - storage: RwLockReadGuard<'a, StorageType>, + storage: Arc, } -impl<'a, StorageType: Storage> CIHandler<'a, StorageType> { +impl CIHandler { pub async fn create( config: RepositoryConfig, - storage: RwLockReadGuard<'a, StorageType>, - ) -> Result, InternalError> { + storage: Arc, + ) -> Result, InternalError> { Ok(CIHandler { config, storage }) } } #[async_trait] -impl<'a, StorageType: Storage> RepositoryHandler<'a, StorageType> for CIHandler<'a, StorageType> {} +impl Repository for CIHandler { + fn get_repository(&self) -> &RepositoryConfig { + &self.config + } + + fn get_storage(&self) -> &StorageType { + &self.storage + } +} diff --git a/backend/src/repository/docker/mod.rs b/backend/src/repository/docker/mod.rs index 9dde81f5..3c09a97a 100644 --- a/backend/src/repository/docker/mod.rs +++ b/backend/src/repository/docker/mod.rs @@ -1,25 +1,31 @@ use crate::error::internal_error::InternalError; -use crate::repository::handler::RepositoryHandler; +use crate::repository::handler::Repository; use crate::repository::settings::RepositoryConfig; use crate::storage::models::Storage; use async_trait::async_trait; +use std::sync::Arc; use tokio::sync::RwLockReadGuard; -pub struct DockerHandler<'a, StorageType: Storage> { +pub struct DockerHandler { config: RepositoryConfig, - storage: RwLockReadGuard<'a, StorageType>, + storage: Arc, } -impl<'a, StorageType: Storage> DockerHandler<'a, StorageType> { +impl DockerHandler { pub async fn create( config: RepositoryConfig, - storage: RwLockReadGuard<'a, StorageType>, - ) -> Result, InternalError> { + storage: Arc, + ) -> Result, InternalError> { Ok(DockerHandler { config, storage }) } } #[async_trait] -impl<'a, StorageType: Storage> RepositoryHandler<'a, StorageType> - for DockerHandler<'a, StorageType> -{ +impl Repository for DockerHandler { + fn get_repository(&self) -> &RepositoryConfig { + &self.config + } + + fn get_storage(&self) -> &StorageType { + &self.storage + } } diff --git a/backend/src/repository/handler.rs b/backend/src/repository/handler.rs index 1a3858af..eb27bfcb 100644 --- a/backend/src/repository/handler.rs +++ b/backend/src/repository/handler.rs @@ -4,23 +4,22 @@ use actix_web::web::Bytes; use actix_web::Error; use async_trait::async_trait; use sea_orm::DatabaseConnection; +use std::sync::{Arc, Weak}; use tokio::sync::RwLockReadGuard; use crate::authentication::Authentication; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; -use crate::repository::ci::CIHandler; -use crate::repository::docker::DockerHandler; -use crate::repository::maven::MavenHandler; -use crate::repository::npm::NPMHandler; -use crate::repository::raw::RawHandler; + use crate::repository::response::RepoResponse; use crate::repository::settings::RepositoryConfig; -use crate::repository::settings::RepositoryType; use crate::storage::models::Storage; - +use serde::{Deserialize, Serialize}; #[async_trait] -pub trait RepositoryHandler<'a, S: Storage>: Send + Sync { +pub trait Repository: Send + Sync { + fn get_repository(&self) -> &RepositoryConfig; + fn get_storage(&self) -> &S; + /// Handles a get request to a Repo async fn handle_get( &self, @@ -98,23 +97,39 @@ pub trait RepositoryHandler<'a, S: Storage>: Send + Sync { macro_rules! repository_handler { ($name:ident, $($repository_type:ident,$repository_tt:tt),*) => { - pub enum $name<'a, StorageType: Storage> { + + pub enum $name { $( - $repository_type($repository_tt<'a, StorageType>), + $repository_type($repository_tt), )* } // Implement From<$repository_tt> for $name $( - impl<'a, StorageType: Storage> From<$repository_tt<'a, StorageType>> for $name<'a, StorageType> { - fn from(repository: $repository_tt<'a, StorageType>) -> Self { + impl<'a, StorageType: Storage> From<$repository_tt> for $name { + fn from(repository: $repository_tt) -> Self { $name::$repository_type(repository) } } )* #[async_trait] - impl<'a, StorageType: Storage> RepositoryHandler<'a, StorageType> - for $name<'a, StorageType> + impl Repository + for $name { + fn get_repository(&self) -> &RepositoryConfig { + match self { + $( + $name::$repository_type(repository) => repository.get_repository(), + )* + } + } + fn get_storage(&self) -> &StorageType { + match self { + $( + $name::$repository_type(repository) => repository.get_storage(), + )* + } + } + async fn handle_get( &self, path: &str, @@ -225,34 +240,47 @@ macro_rules! dynamic_repository_handler { DynamicRepositoryHandler, $($repository_type,$repository_tt),* ); - #[inline] - pub async fn get_repository_handler( - storage: RwLockReadGuard<'_, StorageType>, + + /// Types of Repositories that can exist. + #[derive(Serialize, Deserialize, Clone, Debug, strum_macros::Display, strum_macros::EnumString)] + pub enum RepositoryType { + $($repository_type),* + } + + impl DynamicRepositoryHandler{ + #[inline] + pub async fn new_dyn_storage( + storage: Arc, repository_config: RepositoryConfig, - ) -> Result>, InternalError> { - match repository_config.repository_type { + ) -> Result, InternalError> { + let repository_handler = match repository_config.repository_type { $( RepositoryType::$repository_type => { - let handler = $repository_tt::create(repository_config, storage).await?; - Ok(Some(DynamicRepositoryHandler::$repository_type(handler))) - }, + let repository = $repository_tt::create( + repository_config, + storage, + ).await?; + DynamicRepositoryHandler::$repository_type(repository) + } )* - } + }; + Ok(repository_handler) + } } }; } +// NPM, +// NPMHandler, +// Docker, +// DockerHandler, +// CI, +// CIHandler, +// Raw, +// RawHandler -dynamic_repository_handler!( - NPM, - NPMHandler, - Maven, - MavenHandler, - Docker, - DockerHandler, - CI, - CIHandler, - Raw, - RawHandler -); +use crate::repository::maven::MavenHandler; +dynamic_repository_handler!(Maven, MavenHandler); +use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; +crate::repository::nitro::dynamic::nitro_repo_handler!(DynamicRepositoryHandler,); diff --git a/backend/src/repository/maven/hosted.rs b/backend/src/repository/maven/hosted.rs index 4c6f156c..9dfa605d 100644 --- a/backend/src/repository/maven/hosted.rs +++ b/backend/src/repository/maven/hosted.rs @@ -1,10 +1,9 @@ use crate::authentication::Authentication; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; -use crate::repository::handler::RepositoryHandler; +use crate::repository::handler::Repository; use crate::repository::maven::models::Pom; use crate::repository::maven::settings::ProxySettings; -use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; use crate::repository::response::RepoResponse; use crate::repository::settings::{Policy, RepositoryConfig, Visibility}; use crate::storage::file::StorageFileResponse; @@ -17,14 +16,23 @@ use actix_web::web::Bytes; use async_trait::async_trait; use log::error; use sea_orm::DatabaseConnection; +use std::sync::{Arc, Weak}; use tokio::sync::RwLockReadGuard; -pub struct HostedMavenRepository<'a, S: Storage> { +pub struct HostedMavenRepository { pub config: RepositoryConfig, - pub storage: RwLockReadGuard<'a, S>, + pub storage: Arc, } #[async_trait] -impl<'a, S: Storage> RepositoryHandler<'a, S> for HostedMavenRepository<'a, S> { +impl Repository for HostedMavenRepository { + fn get_repository(&self) -> &RepositoryConfig { + &self.config + } + + fn get_storage(&self) -> &S { + self.storage.as_ref() + } + async fn handle_get( &self, path: &str, @@ -46,8 +54,9 @@ impl<'a, S: Storage> RepositoryHandler<'a, S> for HostedMavenRepository<'a, S> { .map_err(InternalError::from)? { StorageFileResponse::List(list) => { - let files = self.process_storage_files(list, path).await?; - Ok(RepoResponse::try_from((files, StatusCode::OK))?) + /* let files = self.process_storage_files(list, path).await?; + Ok(RepoResponse::try_from((files, StatusCode::OK))?)*/ + panic!("Not implemented") } value => Ok(RepoResponse::FileResponse(value)), } @@ -91,7 +100,7 @@ impl<'a, S: Storage> RepositoryHandler<'a, S> for HostedMavenRepository<'a, S> { .map_err(InternalError::from)?; // Post Deploy Handler - if path.ends_with(".pom") { + /* if path.ends_with(".pom") { let vec = bytes.as_ref().to_vec(); let result = String::from_utf8(vec).map_err(APIError::bad_request)?; let pom: Pom = serde_xml_rs::from_str(&result).map_err(APIError::bad_request)?; @@ -104,31 +113,16 @@ impl<'a, S: Storage> RepositoryHandler<'a, S> for HostedMavenRepository<'a, S> { { error!("Unable to complete post processing Tasks {}", error); } - } + }*/ // Everything was ok Ok(RepoResponse::PUTResponse( exists, format!( "/storages/{}/{}/{}", - &self.storage.storage_config().name, + &self.storage.storage_config().generic_config.id, &self.config.name, path ), )) } } -impl NitroRepositoryHandler - for HostedMavenRepository<'_, StorageType> -{ - fn parse_project_to_directory>(value: S) -> String { - value.into().replace('.', "/").replace(':', "/") - } - - fn storage(&self) -> &StorageType { - &self.storage - } - - fn repository(&self) -> &RepositoryConfig { - &self.config - } -} diff --git a/backend/src/repository/maven/mod.rs b/backend/src/repository/maven/mod.rs index 9f1d79bf..3ed4292e 100644 --- a/backend/src/repository/maven/mod.rs +++ b/backend/src/repository/maven/mod.rs @@ -5,14 +5,14 @@ use async_trait::async_trait; use log::error; use sea_orm::DatabaseConnection; use std::ops::Deref; +use std::sync::{Arc, Weak}; use tokio::sync::RwLockReadGuard; use crate::authentication::Authentication; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; -use crate::repository::handler::{repository_handler, RepositoryHandler}; +use crate::repository::handler::{repository_handler, Repository}; use crate::repository::maven::models::Pom; -use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; use crate::repository::response::RepoResponse; use crate::repository::settings::{Policy, RepositoryConfig, Visibility}; use crate::storage::file::StorageFileResponse; @@ -43,14 +43,12 @@ repository_handler!( StagingRepository ); -impl<'a, S: Storage> MavenHandler<'a, S> { +impl MavenHandler { pub async fn create( repository: RepositoryConfig, - storage: RwLockReadGuard<'a, S>, - ) -> Result, InternalError> { - let result = repository - .get_config::(storage.deref()) - .await?; + storage: Arc, + ) -> Result, InternalError> { + let result = repository.get_config::(&storage).await?; if let Some(config) = result { match config.repository_type { MavenType::Hosted { .. } => Ok(HostedMavenRepository { @@ -88,25 +86,3 @@ impl<'a, S: Storage> MavenHandler<'a, S> { } } } - -impl NitroRepositoryHandler for MavenHandler<'_, StorageType> { - fn parse_project_to_directory>(value: S) -> String { - value.into().replace('.', "/").replace(':', "/") - } - - fn storage(&self) -> &StorageType { - match self { - MavenHandler::Hosted(repository) => &repository.storage, - MavenHandler::Proxy(repository) => &repository.storage, - MavenHandler::Staging(repository) => &repository.storage, - } - } - - fn repository(&self) -> &RepositoryConfig { - match self { - MavenHandler::Hosted(repository) => &repository.config, - MavenHandler::Proxy(repository) => &repository.config, - MavenHandler::Staging(repository) => &repository.config, - } - } -} diff --git a/backend/src/repository/maven/models.rs b/backend/src/repository/maven/models.rs index 71809f72..5b3636eb 100644 --- a/backend/src/repository/maven/models.rs +++ b/backend/src/repository/maven/models.rs @@ -1,7 +1,6 @@ use crate::repository::maven::staging::{DeployRequirement, StageSettings}; use serde::{Deserialize, Serialize}; -use crate::repository::nitro::VersionData; use crate::repository::settings::RepositoryConfigType; use crate::utils::get_current_time; @@ -44,7 +43,7 @@ pub struct Pom { pub url: Option, pub scm: Option, } - +/* impl Into for Pom { fn into(self) -> VersionData { VersionData { @@ -57,3 +56,4 @@ impl Into for Pom { } } } +*/ diff --git a/backend/src/repository/maven/proxy.rs b/backend/src/repository/maven/proxy.rs index 557f6884..b2ad4f31 100644 --- a/backend/src/repository/maven/proxy.rs +++ b/backend/src/repository/maven/proxy.rs @@ -1,8 +1,7 @@ use crate::authentication::Authentication; use crate::error::internal_error::InternalError; -use crate::repository::handler::RepositoryHandler; +use crate::repository::handler::Repository; use crate::repository::maven::settings::ProxySettings; -use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; use crate::repository::response::RepoResponse; use crate::repository::settings::{RepositoryConfig, Visibility}; use crate::storage::file::StorageFileResponse; @@ -19,15 +18,24 @@ use futures::channel::mpsc::unbounded; use futures_util::stream::StreamExt; use futures_util::SinkExt; use sea_orm::DatabaseConnection; +use std::sync::{Arc, Weak}; use tokio::io::{duplex, AsyncWriteExt}; use tokio::sync::RwLockReadGuard; -pub struct ProxyMavenRepository<'a, S: Storage> { +pub struct ProxyMavenRepository { pub config: RepositoryConfig, pub proxy: Vec, - pub storage: RwLockReadGuard<'a, S>, + pub storage: Arc, } #[async_trait] -impl<'a, S: Storage> RepositoryHandler<'a, S> for ProxyMavenRepository<'a, S> { +impl Repository for ProxyMavenRepository { + fn get_repository(&self) -> &RepositoryConfig { + &self.config + } + + fn get_storage(&self) -> &S { + self.storage.as_ref() + } + async fn handle_get( &self, path: &str, @@ -49,8 +57,9 @@ impl<'a, S: Storage> RepositoryHandler<'a, S> for ProxyMavenRepository<'a, S> { .map_err(InternalError::from)? { StorageFileResponse::List(list) => { - let files = self.process_storage_files(list, path).await?; - Ok(RepoResponse::try_from((files, StatusCode::OK))?) + /* let files = self.process_storage_files(list, path).await?; + Ok(RepoResponse::try_from((files, StatusCode::OK))?)*/ + panic!("Not implemented") } StorageFileResponse::NotFound => { @@ -91,18 +100,3 @@ impl<'a, S: Storage> RepositoryHandler<'a, S> for ProxyMavenRepository<'a, S> { } } } -impl NitroRepositoryHandler - for ProxyMavenRepository<'_, StorageType> -{ - fn parse_project_to_directory>(value: S) -> String { - value.into().replace('.', "/").replace(':', "/") - } - - fn storage(&self) -> &StorageType { - &self.storage - } - - fn repository(&self) -> &RepositoryConfig { - &self.config - } -} diff --git a/backend/src/repository/maven/staging.rs b/backend/src/repository/maven/staging.rs index 73ee773f..404e5e0e 100644 --- a/backend/src/repository/maven/staging.rs +++ b/backend/src/repository/maven/staging.rs @@ -1,17 +1,16 @@ use crate::authentication::Authentication; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; -use crate::repository::handler::RepositoryHandler; +use crate::repository::handler::Repository; use crate::repository::maven::models::Pom; use crate::repository::maven::settings::{MavenSettings, MavenType, ProxySettings}; -use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; use crate::repository::response::RepoResponse; use crate::repository::settings::{Policy, RepositoryConfig, Visibility}; use crate::repository::staging::{ProcessingStage, ProjectsToStage, StageHandler}; -use crate::storage::dynamic::DynamicStorage; use crate::storage::file::StorageFileResponse; use crate::storage::models::Storage; use crate::storage::multi::MultiStorageController; +use crate::storage::DynamicStorage; use crate::system::permissions::options::CanIDo; use crate::system::user::UserModel; use actix_web::http::header::HeaderMap; @@ -27,7 +26,7 @@ use sea_orm::DatabaseConnection; use serde::{Deserialize, Serialize}; use std::ops::Deref; use std::path::PathBuf; -use std::sync::Arc; +use std::sync::{Arc, Weak}; use tokio::io::{duplex, AsyncWriteExt}; use tokio::sync::RwLockReadGuard; @@ -52,22 +51,20 @@ pub enum StageSettings { } #[derive(Debug, Serialize, Deserialize, Clone)] pub enum DeployRequirement {} -pub struct StagingRepository<'a, S: Storage> { +pub struct StagingRepository { pub config: RepositoryConfig, - pub storage: RwLockReadGuard<'a, S>, + pub storage: Arc, pub stage_to: Vec, pub parent: ProxySettings, pub deploy_requirement: Vec, } -impl<'a, S: Storage> StagingRepository<'a, S> { +impl<'a, S: Storage> StagingRepository { pub async fn create( repository: RepositoryConfig, - storage: RwLockReadGuard<'a, S>, - ) -> Result, InternalError> { - let result = repository - .get_config::(storage.deref()) - .await?; + storage: Arc, + ) -> Result, InternalError> { + let result = repository.get_config::(&storage).await?; if let Some(config) = result { match config.repository_type { MavenType::Staging { @@ -95,18 +92,26 @@ impl<'a, S: Storage> StagingRepository<'a, S> { } #[async_trait] -impl<'a, S: Storage> StageHandler<'a, S> for StagingRepository<'a, S> { +impl<'a, S: Storage> StageHandler for StagingRepository { async fn push( &self, directory: String, process: ProcessingStage, - storages: Arc, + storages: Arc>, ) -> Result<(), InternalError> { todo!() } } #[async_trait] -impl<'a, S: Storage> RepositoryHandler<'a, S> for StagingRepository<'a, S> { +impl Repository for StagingRepository { + fn get_repository(&self) -> &RepositoryConfig { + &self.config + } + + fn get_storage(&self) -> &S { + self.storage.as_ref() + } + async fn handle_get( &self, path: &str, @@ -128,8 +133,10 @@ impl<'a, S: Storage> RepositoryHandler<'a, S> for StagingRepository<'a, S> { .map_err(InternalError::from)? { StorageFileResponse::List(list) => { + /* let files = self.process_storage_files(list, path).await?; - Ok(RepoResponse::try_from((files, StatusCode::OK))?) + Ok(RepoResponse::try_from((files, StatusCode::OK))?)*/ + panic!("Not implemented") } StorageFileResponse::NotFound => { @@ -195,25 +202,10 @@ impl<'a, S: Storage> RepositoryHandler<'a, S> for StagingRepository<'a, S> { exists, format!( "/storages/{}/{}/{}", - &self.storage.storage_config().name, + &self.storage.storage_config().generic_config.id, &self.config.name, path ), )) } } -impl NitroRepositoryHandler - for StagingRepository<'_, StorageType> -{ - fn parse_project_to_directory>(value: S) -> String { - value.into().replace('.', "/").replace(':', "/") - } - - fn storage(&self) -> &StorageType { - &self.storage - } - - fn repository(&self) -> &RepositoryConfig { - &self.config - } -} diff --git a/backend/src/repository/mod.rs b/backend/src/repository/mod.rs index 9ea30c54..378f7ab6 100644 --- a/backend/src/repository/mod.rs +++ b/backend/src/repository/mod.rs @@ -16,4 +16,3 @@ pub mod web; pub static REPOSITORY_CONF: &str = "repository.nitro_repo"; pub static REPOSITORY_CONF_FOLDER: &str = ".config.nitro_repo"; pub static REPOSITORY_CONF_BAK: &str = "repository.nitro_repo.bak"; -pub use handler::get_repository_handler; diff --git a/backend/src/repository/nitro/dynamic.rs b/backend/src/repository/nitro/dynamic.rs index f2d49dd3..914d5c12 100644 --- a/backend/src/repository/nitro/dynamic.rs +++ b/backend/src/repository/nitro/dynamic.rs @@ -1,69 +1,30 @@ -use crate::error::internal_error::InternalError; -use crate::repository::maven::MavenHandler; -use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; -use crate::repository::nitro::{NitroFileResponse, NitroRepoVersions, VersionData}; -use crate::repository::npm::NPMHandler; -use crate::repository::response::Project; -use crate::repository::settings::RepositoryConfig; -use crate::repository::settings::RepositoryType; -use crate::storage::file::StorageDirectoryResponse; -use crate::storage::models::Storage; -use crate::system::user::database::Model; -use async_trait::async_trait; -use tokio::sync::RwLockReadGuard; - /// Impls the NitroRepository for the DynamicNitroRepositoryHandler /// # Arguments /// Array of the Repository Types macro_rules! nitro_repo_handler { - ($($name: ident, $ty:tt),*) => { - - pub enum DynamicNitroRepositoryHandler<'a, StorageType: Storage> { - $( - $name($ty<'a, StorageType>), - )* - } - #[inline] - pub async fn get_nitro_handler( - storage: RwLockReadGuard<'_, StorageType>, - repository_config: RepositoryConfig, - ) -> Result, InternalError> { - match repository_config.repository_type { - $( - RepositoryType::$name => { - let handler = $ty::create(repository_config, storage).await?; - Ok(NitroRepoHandler::Supported(DynamicNitroRepositoryHandler::$name(handler))) - }, - )* - _ => Ok(NitroRepoHandler::Unsupported(repository_config)), - - } - } - #[async_trait] + ($v:ident, $($name: ident, $ty:tt),*) => { + #[async_trait::async_trait] impl<'a, StorageType: Storage> NitroRepositoryHandler - for DynamicNitroRepositoryHandler<'a, StorageType> + for $v { fn parse_project_to_directory>(_value: S) -> String { panic!("Parse Should be implemented in the Dynamic Nitro Repository Handler"); } - - fn storage(&self) -> &StorageType { + fn supports_nitro(&self) -> bool { match self { - $(DynamicNitroRepositoryHandler::$name(handler) => handler.storage(),)* + $($v::$name(handler) => handler.supports_nitro(),)* + _ => false, } } - fn repository(&self) -> &RepositoryConfig { - match self { - $(DynamicNitroRepositoryHandler::$name(handler) =>handler.repository() ,)* - } - } async fn get_versions( &self, project: &str, - ) -> Result, InternalError> { + ) -> Result, InternalError> { match self { - $(DynamicNitroRepositoryHandler::$name(handler) => handler.get_versions(project).await,)* + $($v::$name(handler) => handler.get_versions(project).await,)* + _ => unsafe{ std::hint::unreachable_unchecked() }, + } } @@ -71,51 +32,54 @@ macro_rules! nitro_repo_handler { &self, project: &str, version: &str, - ) -> Result, InternalError> { + ) -> Result, InternalError> { match self { - $(DynamicNitroRepositoryHandler::$name(handler) => handler.get_project_specific_version(project, version).await,)* + $($v::$name(handler) => handler.get_project_specific_version(project, version).await,)* + _ => unsafe{ std::hint::unreachable_unchecked() }, } } async fn get_project_latest( &self, project: &str, - ) -> Result, InternalError> { + ) -> Result, InternalError> { match self { - $(DynamicNitroRepositoryHandler::$name(handler) => handler.get_project_latest(project).await,)* + $($v::$name(handler) => handler.get_project_latest(project).await,)* + _ => unsafe{ std::hint::unreachable_unchecked() }, + } } async fn latest_version(&self, project: &str) -> Result, InternalError> { match self { - $(DynamicNitroRepositoryHandler::$name(handler) => handler.latest_version(project).await,)* + $($v::$name(handler) => handler.latest_version(project).await,)* + _ => unsafe{ std::hint::unreachable_unchecked() }, + } } async fn process_storage_files( &self, - directory: StorageDirectoryResponse, + directory: crate::storage::file::StorageDirectoryResponse, requested_dir: &str, - ) -> Result { + ) -> Result { match self { - $(DynamicNitroRepositoryHandler::$name(handler) => handler.process_storage_files(directory, requested_dir).await,)* + $($v::$name(handler) => handler.process_storage_files(directory, requested_dir).await,)* + _ => unsafe{ std::hint::unreachable_unchecked() }, + } } async fn post_deploy( &self, project_folder: String, version_folder: String, - model: Model, - version_data: VersionData, + model: crate::system::user::database::Model, + version_data: crate::repository::nitro::VersionData, ) -> Result<(), InternalError> { match self { - $(DynamicNitroRepositoryHandler::$name(handler) => handler.post_deploy(project_folder, version_folder, model, version_data).await,)* + $($v::$name(handler) => handler.post_deploy(project_folder, version_folder, model, version_data).await,)* + _ => unsafe{ std::hint::unreachable_unchecked() }, + } } } }; } -pub enum NitroRepoHandler<'a, StorageType: Storage> { - Supported(DynamicNitroRepositoryHandler<'a, StorageType>), - /// it is a teapot! [Teapot](https://http.cat/418) - Unsupported(RepositoryConfig), -} - -nitro_repo_handler!(Maven, MavenHandler, NPM, NPMHandler); +pub(crate) use nitro_repo_handler; diff --git a/backend/src/repository/nitro/mod.rs b/backend/src/repository/nitro/mod.rs index bc091261..eaacf02b 100644 --- a/backend/src/repository/nitro/mod.rs +++ b/backend/src/repository/nitro/mod.rs @@ -6,7 +6,6 @@ use crate::utils::get_current_time; pub mod dynamic; pub mod nitro_repository; -pub mod post_deploy; pub mod utils; #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/backend/src/repository/nitro/nitro_repository.rs b/backend/src/repository/nitro/nitro_repository.rs index 19cea280..e9a636ca 100644 --- a/backend/src/repository/nitro/nitro_repository.rs +++ b/backend/src/repository/nitro/nitro_repository.rs @@ -3,6 +3,7 @@ use log::{debug, error, trace}; use crate::constants::{PROJECT_FILE, VERSION_DATA}; use crate::error::internal_error::InternalError; +use crate::repository::handler::Repository; use crate::repository::nitro::utils::{ get_project_data, get_version_data, get_versions, update_project_in_repositories, }; @@ -17,10 +18,11 @@ use crate::storage::models::Storage; use crate::system::user::UserModel; #[async_trait] -pub trait NitroRepositoryHandler { +pub trait NitroRepositoryHandler: Repository { + fn supports_nitro(&self) -> bool { + true + } fn parse_project_to_directory>(value: S) -> String; - fn storage(&self) -> &StorageType; - fn repository(&self) -> &RepositoryConfig; /// Handles a List of versions request async fn get_versions( &self, @@ -28,8 +30,8 @@ pub trait NitroRepositoryHandler { ) -> Result, InternalError> { Ok(Some( get_versions( - self.storage(), - self.repository(), + self.get_storage(), + self.get_repository(), Self::parse_project_to_directory(project), ) .await?, @@ -42,18 +44,22 @@ pub trait NitroRepositoryHandler { ) -> Result, InternalError> { let project_dir = Self::parse_project_to_directory(project); - let project_data = - get_project_data(self.storage(), self.repository(), &project_dir.clone()).await?; + let project_data = get_project_data( + self.get_storage(), + self.get_repository(), + &project_dir.clone(), + ) + .await?; if let Some(project_data) = project_data { let version_data = get_version_data( - self.storage(), - self.repository(), + self.get_storage(), + self.get_repository(), &format!("{}/{}", project_dir, &version), ) .await?; let project = Project { - repo_summary: self.repository().clone(), + repo_summary: self.get_repository().clone(), project: project_data, version: version_data, frontend_response: String::new(), @@ -66,17 +72,17 @@ pub trait NitroRepositoryHandler { let project_dir = Self::parse_project_to_directory(project); let project_data = - get_project_data(self.storage(), self.repository(), &project_dir).await?; + get_project_data(self.get_storage(), self.get_repository(), &project_dir).await?; if let Some(project_data) = project_data { let version_data = get_version_data( - self.storage(), - self.repository(), + self.get_storage(), + self.get_repository(), &format!("{}/{}", &project_dir, &project_data.versions.latest_version), ) .await?; let project = Project { - repo_summary: self.repository().clone(), + repo_summary: self.get_repository().clone(), project: project_data, version: version_data, frontend_response: String::new(), @@ -90,7 +96,7 @@ pub trait NitroRepositoryHandler { async fn latest_version(&self, project: &str) -> Result, InternalError> { let project_dir = Self::parse_project_to_directory(project); let project_data = - get_project_data(self.storage(), self.repository(), &project_dir).await?; + get_project_data(self.get_storage(), self.get_repository(), &project_dir).await?; if let Some(project_data) = project_data { let latest_release = project_data.versions.latest_release; if latest_release.is_empty() { @@ -117,11 +123,11 @@ pub trait NitroRepositoryHandler { }); } let value = if let Some(project_data) = - get_project_data(self.storage(), self.repository(), requested_dir).await? + get_project_data(self.get_storage(), self.get_repository(), requested_dir).await? { let version_data = get_version_data( - self.storage(), - self.repository(), + self.get_storage(), + self.get_repository(), &format!( "{}/{}", &requested_dir, &project_data.versions.latest_version @@ -130,22 +136,22 @@ pub trait NitroRepositoryHandler { .await?; let project = Project { - repo_summary: self.repository().clone(), + repo_summary: self.get_repository().clone(), project: project_data, version: version_data, frontend_response: String::new(), }; NitroFileResponseType::Project(project) } else if let Some(version) = - get_version_data(self.storage(), self.repository(), requested_dir).await? + get_version_data(self.get_storage(), self.get_repository(), requested_dir).await? { let project_dir = Self::parse_project_to_directory(&version.name); - let project = get_project_data(self.storage(), self.repository(), &project_dir) + let project = get_project_data(self.get_storage(), self.get_repository(), &project_dir) .await? .unwrap(); let project = Project { - repo_summary: self.repository().clone(), + repo_summary: self.get_repository().clone(), project, version: Some(version), frontend_response: String::new(), @@ -175,14 +181,14 @@ pub trait NitroRepositoryHandler { trace!("Version File Location {}", version_file); let result: Result<(), InternalError> = { let option = self - .storage() - .get_file(self.repository(), &project_file) + .get_storage() + .get_file(self.get_repository(), &project_file) .await?; let mut project_data: ProjectData = if let Some(data) = option { let string = String::from_utf8(data)?; let value = serde_json::from_str(&string)?; - self.storage() - .delete_file(self.repository(), &project_file) + self.get_storage() + .delete_file(self.get_repository(), &project_file) .await?; value } else { @@ -190,16 +196,16 @@ pub trait NitroRepositoryHandler { ProjectData::default() }; project_data.versions.update_version(&version_data.version); - self.storage() + self.get_storage() .save_file( - self.repository(), + self.get_repository(), serde_json::to_string_pretty(&project_data)?.as_bytes(), &project_file, ) .await?; - self.storage() + self.get_storage() .save_file( - self.repository(), + self.get_repository(), serde_json::to_string_pretty(&version_data)?.as_bytes(), &version_file, ) @@ -215,8 +221,8 @@ pub trait NitroRepositoryHandler { ); } if let Err(error) = update_project_in_repositories( - self.storage(), - self.repository(), + self.get_storage(), + self.get_repository(), version_data.name.clone(), ) .await diff --git a/backend/src/repository/nitro/post_deploy/mod.rs b/backend/src/repository/nitro/post_deploy/mod.rs deleted file mode 100644 index 8b137891..00000000 --- a/backend/src/repository/nitro/post_deploy/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/backend/src/repository/npm/mod.rs b/backend/src/repository/npm/mod.rs index fdd47038..665d3b14 100644 --- a/backend/src/repository/npm/mod.rs +++ b/backend/src/repository/npm/mod.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; use std::string::String; +use std::sync::Arc; use actix_web::http::header::HeaderMap; use actix_web::http::StatusCode; @@ -13,7 +14,7 @@ use tokio::sync::RwLockReadGuard; use crate::authentication::{verify_login, Authentication}; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; -use crate::repository::handler::RepositoryHandler; +use crate::repository::handler::Repository; use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; use crate::repository::npm::models::{Attachment, LoginRequest, LoginResponse, PublishRequest}; use crate::repository::npm::utils::generate_get_response; @@ -28,16 +29,16 @@ pub mod error; pub mod models; mod utils; -pub struct NPMHandler<'a, StorageType: Storage> { +pub struct NPMHandler { config: RepositoryConfig, - storage: RwLockReadGuard<'a, StorageType>, + storage: Arc, } -impl<'a, StorageType: Storage> NPMHandler<'a, StorageType> { +impl NPMHandler { pub async fn create( repository: RepositoryConfig, - storage: RwLockReadGuard<'a, StorageType>, - ) -> Result, InternalError> { + storage: Arc, + ) -> Result, InternalError> { Ok(NPMHandler { config: repository, storage, @@ -50,7 +51,14 @@ impl<'a, StorageType: Storage> NPMHandler<'a, StorageType> { // name/version #[async_trait] -impl<'a, StorageType: Storage> RepositoryHandler<'a, StorageType> for NPMHandler<'a, StorageType> { +impl Repository for NPMHandler { + fn get_repository(&self) -> &RepositoryConfig { + &self.config + } + + fn get_storage(&self) -> &StorageType { + &self.storage + } async fn handle_get( &self, path: &str, @@ -101,8 +109,10 @@ impl<'a, StorageType: Storage> RepositoryHandler<'a, StorageType> for NPMHandler .map_err(InternalError::from)? { StorageFileResponse::List(list) => { + /* let files = self.process_storage_files(list, path).await?; - Ok(RepoResponse::try_from((files, StatusCode::OK))?) + Ok(RepoResponse::try_from((files, StatusCode::OK))?)*/ + panic!("Not implemented") } value => Ok(RepoResponse::FileResponse(value)), } @@ -201,7 +211,7 @@ impl<'a, StorageType: Storage> RepositoryHandler<'a, StorageType> for NPMHandler trace!("Project Folder Location {}", project_folder); let version_for_saving = version_data.clone(); let user = caller.clone(); - if let Err(error) = self + /* if let Err(error) = self .post_deploy( project_folder, version_folder, @@ -211,7 +221,7 @@ impl<'a, StorageType: Storage> RepositoryHandler<'a, StorageType> for NPMHandler .await { error!("Unable to complete post processing Tasks {}", error); - } + }*/ } } @@ -219,7 +229,7 @@ impl<'a, StorageType: Storage> RepositoryHandler<'a, StorageType> for NPMHandler exists, format!( "/storages/{}/{}/{}", - &self.storage.storage_config().name, + &self.storage.storage_config().generic_config.id, &self.config.name, path ), @@ -231,17 +241,3 @@ impl<'a, StorageType: Storage> RepositoryHandler<'a, StorageType> for NPMHandler } } } - -impl NitroRepositoryHandler for NPMHandler<'_, StorageType> { - fn parse_project_to_directory>(path: S) -> String { - path.into().replace('.', "/").replace(':', "/") - } - - fn storage(&self) -> &StorageType { - &self.storage - } - - fn repository(&self) -> &RepositoryConfig { - &self.config - } -} diff --git a/backend/src/repository/raw/mod.rs b/backend/src/repository/raw/mod.rs index f5fe3c62..db6f2336 100644 --- a/backend/src/repository/raw/mod.rs +++ b/backend/src/repository/raw/mod.rs @@ -1,22 +1,31 @@ use crate::error::internal_error::InternalError; -use crate::repository::handler::RepositoryHandler; +use crate::repository::handler::Repository; use crate::repository::settings::RepositoryConfig; use crate::storage::models::Storage; use async_trait::async_trait; +use std::sync::Arc; use tokio::sync::RwLockReadGuard; -pub struct RawHandler<'a, StorageType: Storage> { +pub struct RawHandler { config: RepositoryConfig, - storage: RwLockReadGuard<'a, StorageType>, + storage: Arc, } -impl<'a, StorageType: Storage> RawHandler<'a, StorageType> { +impl RawHandler { pub async fn create( config: RepositoryConfig, - storage: RwLockReadGuard<'a, StorageType>, - ) -> Result, InternalError> { + storage: Arc, + ) -> Result, InternalError> { Ok(RawHandler { config, storage }) } } #[async_trait] -impl<'a, StorageType: Storage> RepositoryHandler<'a, StorageType> for RawHandler<'a, StorageType> {} +impl Repository for RawHandler { + fn get_repository(&self) -> &RepositoryConfig { + &self.config + } + + fn get_storage(&self) -> &StorageType { + &self.storage + } +} diff --git a/backend/src/repository/settings/mod.rs b/backend/src/repository/settings/mod.rs index f7a12abe..057372b4 100644 --- a/backend/src/repository/settings/mod.rs +++ b/backend/src/repository/settings/mod.rs @@ -4,6 +4,7 @@ use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use crate::error::internal_error::InternalError; +pub use crate::repository::handler::RepositoryType; use crate::storage::models::Storage; pub mod badge; @@ -41,21 +42,6 @@ fn default() -> bool { true } -/// Types of Repositories that can exist. -#[derive(Serialize, Deserialize, Clone, Debug, strum_macros::Display, strum_macros::EnumString)] -pub enum RepositoryType { - /// A Maven Repository - Maven, - /// A NPM Repository - NPM, - /// CI Artifact Upload - CI, - /// A Docker Repository - Docker, - /// Raw Repository - Raw, -} - /// The Basic Repository Config /// These values are core to the existence of the Repository #[derive(Clone, Debug, Serialize, Deserialize)] @@ -109,19 +95,7 @@ impl RepositoryConfig { storage: &StorageType, config: Option<&Config>, ) -> Result<(), InternalError> { - if let Some(value) = config { - storage - .update_repository_config(self, Config::config_name(), &value) - .await - .map_err(InternalError::StorageError) - } else { - // Deleting the config means for the Config type that the feature set has been disabled - // If the type should not be disabled. This is a bug. - storage - .delete_repository_config(self, Config::config_name()) - .await - .map_err(InternalError::StorageError) - } + panic!("To be replaced"); } } diff --git a/backend/src/repository/staging/dynamic.rs b/backend/src/repository/staging/dynamic.rs index 02c6d6d3..852d83bc 100644 --- a/backend/src/repository/staging/dynamic.rs +++ b/backend/src/repository/staging/dynamic.rs @@ -4,41 +4,33 @@ use crate::error::internal_error::InternalError; use crate::repository::settings::{RepositoryConfig, RepositoryType}; use crate::storage::models::Storage; use crate::storage::multi::MultiStorageController; +use crate::storage::DynamicStorage; use std::sync::Arc; use tokio::sync::RwLockReadGuard; macro_rules! gen_dynamic_stage { ($($name: ident, $ty:tt),*) => { - pub enum DynamicStageHandler<'a, StorageType: Storage> { + pub enum DynamicStageHandler { $( - $name($ty<'a, StorageType>), + $name($ty), )* } #[inline] pub async fn get_stage_handler( - storage: RwLockReadGuard<'_, StorageType>, + storage: Arc, repository_config: RepositoryConfig, ) -> Result, InternalError> { - match repository_config.repository_type { - $( - RepositoryType::$name => { - let handler = $ty::create(repository_config, storage).await?; - Ok(StageHandlerResult::Supported(DynamicStageHandler::$name(handler))) - }, - )* - _ => Ok(StageHandlerResult::Unsupported(repository_config)), - - } + panic!("Not implemented"); } #[async_trait::async_trait] - impl<'a, StorageType: Storage> StageHandler<'a, StorageType> - for DynamicStageHandler<'a, StorageType>{ + impl StageHandler + for DynamicStageHandler{ async fn push( &self, directory: String, process: ProcessingStage, - storages: Arc, + storages: Arc>, ) -> Result<(), InternalError>{ match self { $( @@ -49,8 +41,8 @@ macro_rules! gen_dynamic_stage { } }; } -pub enum StageHandlerResult<'a, StorageType: Storage> { - Supported(DynamicStageHandler<'a, StorageType>), +pub enum StageHandlerResult { + Supported(DynamicStageHandler), /// it is a teapot! [Teapot](https://http.cat/418) Unsupported(RepositoryConfig), } diff --git a/backend/src/repository/staging/mod.rs b/backend/src/repository/staging/mod.rs index e1effe5c..d06a46f4 100644 --- a/backend/src/repository/staging/mod.rs +++ b/backend/src/repository/staging/mod.rs @@ -5,11 +5,12 @@ use crate::repository::response::RepoResponse; use crate::repository::settings::RepositoryConfigType; use crate::storage::models::Storage; use crate::storage::multi::MultiStorageController; +use crate::storage::DynamicStorage; use async_trait::async_trait; use serde::{Deserialize, Serialize}; use serde_json::Value; use std::path::PathBuf; -use std::sync::Arc; +use std::sync::{Arc, Weak}; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct ProcessingStage { @@ -25,11 +26,11 @@ impl RepositoryConfigType for ProcessingStage { } } #[async_trait] -pub trait StageHandler<'a, S: Storage> { +pub trait StageHandler { async fn push( &self, directory: String, process: ProcessingStage, - storages: Arc, + storages: Arc>, ) -> Result<(), InternalError>; } diff --git a/backend/src/repository/web/mod.rs b/backend/src/repository/web/mod.rs index 141fa53a..b0f742f2 100644 --- a/backend/src/repository/web/mod.rs +++ b/backend/src/repository/web/mod.rs @@ -18,14 +18,7 @@ pub struct RepositoryResponse<'a> { impl<'a> RepositoryResponse<'a> { pub async fn new( config: &'a RepositoryConfig, - storage: &StorageType, ) -> Result, InternalError> { - let frontend = config.get_config(storage).await?; - let badge = config.get_config(storage).await?; - Ok(RepositoryResponse { - config, - frontend, - badge, - }) + todo!("create big boi") } } diff --git a/backend/src/repository/web/multi/admin.rs b/backend/src/repository/web/multi/admin.rs index 8775edaa..95b19c32 100644 --- a/backend/src/repository/web/multi/admin.rs +++ b/backend/src/repository/web/multi/admin.rs @@ -10,6 +10,7 @@ use crate::authentication::Authentication; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; +use crate::repository::handler::Repository; use crate::repository::maven::settings::MavenSettings; use crate::repository::settings::{Policy, RepositoryConfig, Visibility}; use crate::repository::web::RepositoryResponse; @@ -17,6 +18,7 @@ use crate::repository::RepositoryType; use crate::storage::error::StorageError; use crate::storage::models::Storage; use crate::storage::multi::MultiStorageController; +use crate::storage::DynamicStorage; use crate::system::permissions::options::CanIDo; use crate::system::user::UserModel; use paste::paste; @@ -26,7 +28,7 @@ use tokio::sync::RwLockReadGuard; /// Get all repositories from the storage #[get("/repositories/{storage_name}")] pub async fn get_repositories( - storage_handler: web::Data, + storage_handler: web::Data>, database: web::Data, auth: Authentication, storage_name: web::Path, @@ -36,18 +38,13 @@ pub async fn get_repositories( let storage = crate::helpers::get_storage!(storage_handler, storage_name); - Ok(HttpResponse::Ok().json( - storage - .get_repositories() - .await - .map_err(InternalError::from)?, - )) + Ok(HttpResponse::Ok().json(storage.get_repository_list().map_err(InternalError::from)?)) } /// Create a new repository #[post("/repositories/{storage_name}/new/{repository_name}/{repository_type}")] pub async fn create_repository( - storage_handler: web::Data, + storage_handler: web::Data>, database: web::Data, auth: Authentication, query_params: web::Path<(String, String, RepositoryType)>, @@ -58,39 +55,7 @@ pub async fn create_repository( let (storage_name, repository_name, repository_type) = query_params.into_inner(); let storage = crate::helpers::get_storage!(storage_handler, storage_name); - match storage - .create_repository(repository_name.clone(), repository_type) - .await - { - Ok(()) => { - let repository_config = storage - .get_repository(repository_name.as_str()) - .await - .map_err(actix_web::error::ErrorInternalServerError)?; - match repository_config { - None => Ok(HttpResponse::InternalServerError().finish()), - Some(config) => { - if let Some(inner_config) = inner_config.into_inner() { - match config.repository_type { - RepositoryType::Maven => { - let maven: MavenSettings = serde_json::from_value(inner_config) - .map_err(actix_web::error::ErrorBadRequest)?; - config.save_config(storage.deref(), Some(&maven)).await?; - } - _ => {} - } - } - Ok(HttpResponse::NoContent().finish()) - } - } - } - Err(error) => match error { - StorageError::RepositoryAlreadyExists => { - Err(APIError::from(("Repository already exists", StatusCode::CONFLICT)).into()) - } - value => Err(InternalError::from(value).into()), - }, - } + todo!("Create Repository"); } #[derive(Deserialize)] @@ -103,7 +68,7 @@ pub struct GetRepositoryQuery { /// If the query param all_info is present. It will include other repository configs such as Frontend and Badge #[get("/repositories/{storage_name}/{repository_name}")] pub async fn get_repository( - storage_handler: web::Data, + storage_handler: web::Data>, database: web::Data, auth: Authentication, path_params: web::Path<(String, String)>, @@ -113,17 +78,9 @@ pub async fn get_repository( user.can_i_edit_repos()?; let (storage_name, repository_name) = path_params.into_inner(); let storage = crate::helpers::get_storage!(storage_handler, storage_name); - let repository = crate::helpers::get_repository!(storage, repository_name) - .deref() - .clone(); - // Check if the query param contains all_info - if query_params.all_info { - //Generate a RepositoryResponse - let response = RepositoryResponse::new(&repository, storage.deref()).await?; - Ok(HttpResponse::Ok().json(response)) - } else { - Ok(HttpResponse::Ok().json(repository)) - } + let repository = crate::helpers::get_repository!(storage, repository_name); + + Ok(HttpResponse::Ok().json(repository.get_repository())) } #[derive(Deserialize)] @@ -134,7 +91,7 @@ pub struct DeleteRepositoryQuery { #[delete("/repositories/{storage_name}/{repository_name}")] pub async fn delete_repository( - storage_handler: web::Data, + storage_handler: web::Data>, database: web::Data, auth: Authentication, path_params: web::Path<(String, String)>, @@ -144,11 +101,9 @@ pub async fn delete_repository( user.can_i_edit_repos()?; let (storage_name, repository_name) = path_params.into_inner(); let storage = crate::helpers::get_storage!(storage_handler, storage_name); - let repository = crate::helpers::get_repository!(storage, repository_name) - .deref() - .clone(); + let repository = crate::helpers::get_repository!(storage, repository_name); storage - .delete_repository(&repository, query_params.purge_repository) + .delete_repository(repository_name, query_params.purge_repository) .await .map_err(InternalError::from)?; Ok(HttpResponse::NoContent().finish()) @@ -158,7 +113,7 @@ macro_rules! update_repository_core_prop { $( paste! { pub async fn []( - storage_handler: web::Data, + storage_handler: web::Data>, database: web::Data, auth: Authentication, path_params: web::Path<(String, String, $value_type)>, @@ -191,4 +146,4 @@ macro_rules! update_repository_core_prop { } }; } -update_repository_core_prop!(visibility, Visibility, active, bool, policy, Policy); +//update_repository_core_prop!(visibility, Visibility, active, bool, policy, Policy); diff --git a/backend/src/repository/web/multi/configs.rs b/backend/src/repository/web/multi/configs.rs index db338c89..0392889c 100644 --- a/backend/src/repository/web/multi/configs.rs +++ b/backend/src/repository/web/multi/configs.rs @@ -2,7 +2,7 @@ macro_rules! define_repository_config_get { ($value:literal,$ty:tt ) => { paste::paste! { pub async fn []( - storage_handler: actix_web::web::Data, + storage_handler: actix_web::web::Data>, database: actix_web::web::Data, auth: crate::authentication::Authentication, path_params: actix_web::web::Path<(String, String)>, @@ -31,7 +31,7 @@ macro_rules! define_repository_config_set { ($value:literal,$ty:tt ) => { paste::paste! { pub async fn []( - storage_handler: actix_web::web::Data, + storage_handler: actix_web::web::Data>, database: actix_web::web::Data, auth: crate::authentication::Authentication, path_params: actix_web::web::Path<(String, String)>, @@ -58,7 +58,7 @@ macro_rules! define_repository_config_delete { ($value:literal,$ty:tt ) => { paste::paste! { pub async fn []( - storage_handler: actix_web::web::Data, + storage_handler: actix_web::web::Data>, database: actix_web::web::Data, auth: crate::authentication::Authentication, path_params: actix_web::web::Path<(String, String)>, diff --git a/backend/src/repository/web/multi/mod.rs b/backend/src/repository/web/multi/mod.rs index b73bbe8f..35b0925a 100644 --- a/backend/src/repository/web/multi/mod.rs +++ b/backend/src/repository/web/multi/mod.rs @@ -28,8 +28,7 @@ pub fn init_admin(cfg: &mut web::ServiceConfig) { .service(admin::get_repositories) .service(admin::create_repository) .service(admin::delete_repository); - cfg.configure(admin::register_core_updates); - cfg.configure(configs_impls::init_repository_configs); + //cfg.configure(admin::register_core_updates); } pub mod configs_impls { @@ -37,12 +36,11 @@ pub mod configs_impls { use crate::repository::settings::badge::BadgeSettings; use crate::repository::settings::frontend::Frontend; use crate::repository::settings::repository_page::RepositoryPage; - define_repository_config_handlers_group!( - "badge", - BadgeSettings, - "frontend", - Frontend, - "repository_page", - RepositoryPage - ); + // define_repository_config_handlers_group!( + // "badge", + // BadgeSettings, + // "frontend", + // Frontend, + // RepositoryPage + // ); } diff --git a/backend/src/repository/web/multi/public/project.rs b/backend/src/repository/web/multi/public/project.rs index 753b8d30..65d38661 100644 --- a/backend/src/repository/web/multi/public/project.rs +++ b/backend/src/repository/web/multi/public/project.rs @@ -7,57 +7,52 @@ use std::ops::Deref; use crate::authentication::Authentication; use crate::error::internal_error::InternalError; +use crate::repository::handler::Repository; use crate::repository::settings::repository_page::{PageType, RepositoryPage}; use crate::repository::settings::{RepositoryConfig, Visibility}; -use crate::storage::dynamic::DynamicStorage; use crate::storage::models::Storage; use crate::storage::multi::MultiStorageController; +use crate::storage::DynamicStorage; use crate::system::permissions::options::{CanIDo, MissingPermission}; use crate::system::user::UserModel; -use crate::repository::nitro::dynamic::{ - get_nitro_handler, DynamicNitroRepositoryHandler, NitroRepoHandler, -}; use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; use crate::repository::nitro::{ProjectRequest, VersionData}; use crate::repository::settings::RepositoryType; pub async fn get_project( - storage_handler: web::Data, + storage_handler: web::Data>, database: web::Data, authentication: Authentication, path: web::Path, ) -> actix_web::Result { let (storage_name, repository_name, project, version) = path.into_inner().into_inner(); let storage = crate::helpers::get_storage!(storage_handler, storage_name); - let repository = crate::helpers::get_repository!(storage, repository_name) - .deref() - .clone(); - if !repository.visibility.eq(&Visibility::Public) { + let repository = crate::helpers::get_repository!(storage, repository_name); + if !repository.supports_nitro() { + return Ok(HttpResponse::BadRequest().finish()); + } + if !repository + .get_repository() + .visibility + .eq(&Visibility::Public) + { let caller: UserModel = authentication.get_user(database.as_ref()).await??; - if let Some(value) = caller.can_read_from(&repository)? { + if let Some(value) = caller.can_read_from(repository.get_repository())? { return Err(value.into()); } } - let handler = get_nitro_handler(storage, repository).await?; - match handler { - NitroRepoHandler::Supported(supported) => { - let value = if let Some(version) = version { - supported - .get_project_specific_version(project.as_str(), version.as_ref()) - .await? - } else { - supported.get_project_latest(project.as_str()).await? - }; - if let Some(value) = value { - return Ok(HttpResponse::Ok().json(value)); - } else { - Ok(HttpResponse::NotFound().finish()) - } - } - NitroRepoHandler::Unsupported(_) => { - return Ok(HttpResponse::BadRequest().finish()); - } + let value = if let Some(version) = version { + repository + .get_project_specific_version(project.as_str(), version.as_ref()) + .await? + } else { + repository.get_project_latest(project.as_str()).await? + }; + if let Some(value) = value { + return Ok(HttpResponse::Ok().json(value)); + } else { + Ok(HttpResponse::NotFound().finish()) } } diff --git a/backend/src/repository/web/multi/public/repositories.rs b/backend/src/repository/web/multi/public/repositories.rs index caa6f391..3bfed6f5 100644 --- a/backend/src/repository/web/multi/public/repositories.rs +++ b/backend/src/repository/web/multi/public/repositories.rs @@ -7,12 +7,13 @@ use std::ops::Deref; use crate::authentication::Authentication; use crate::error::internal_error::InternalError; +use crate::repository::handler::Repository; use crate::repository::settings::repository_page::{PageType, RepositoryPage}; use crate::repository::settings::{RepositoryConfig, RepositoryType, Visibility}; -use crate::storage::dynamic::DynamicStorage; use crate::storage::models::Storage; use crate::storage::multi::MultiStorageController; +use crate::storage::DynamicStorage; use crate::system::permissions::options::{CanIDo, MissingPermission}; use crate::system::user::UserModel; #[derive(Debug, Clone, Serialize, Deserialize)] @@ -23,7 +24,7 @@ pub struct PublicRepositoryResponse { #[get("repositories/{storage_name}")] pub async fn get_repositories( - storage_handler: web::Data, + storage_handler: web::Data>, database: web::Data, authentication: Authentication, path: web::Path, @@ -33,8 +34,7 @@ pub async fn get_repositories( let caller: Option = authentication.get_user(database.as_ref()).await?.ok(); let vec: Vec = value - .get_repositories() - .await + .get_repository_list() .map_err(actix_web::error::ErrorInternalServerError)? .into_iter() .filter(|repo| { @@ -71,7 +71,7 @@ pub struct RepositoryPageResponse { } #[get("repositories/{storage_name}/{repository_name}")] pub async fn get_repository( - storage_handler: web::Data, + storage_handler: web::Data>, database: web::Data, authentication: Authentication, path: web::Path<(String, String)>, @@ -79,14 +79,19 @@ pub async fn get_repository( let (storage_name, repository_name) = path.into_inner(); let storage = crate::helpers::get_storage!(storage_handler, storage_name); let repository = crate::helpers::get_repository!(storage, repository_name); - if !repository.visibility.eq(&Visibility::Public) { + if !repository + .get_repository() + .visibility + .eq(&Visibility::Public) + { let caller: UserModel = authentication.get_user(database.as_ref()).await??; - if let Some(value) = caller.can_read_from(&repository)? { + if let Some(value) = caller.can_read_from(repository.get_repository())? { return Err(value.into()); } } let repository_page: Option = repository - .get_config::(storage.deref()) + .get_repository() + .get_config::(&storage) .await?; let page_content = if let Some(value) = repository_page { match value.page_type { @@ -104,8 +109,8 @@ pub async fn get_repository( String::new() }; let value = RepositoryPageResponse { - name: repository.name.clone(), - repository_type: repository.repository_type.clone(), + name: repository.get_repository().name.clone(), + repository_type: repository.get_repository().repository_type.clone(), page_content, }; diff --git a/backend/src/repository/web/multi/repository_handler.rs b/backend/src/repository/web/multi/repository_handler.rs index 471e5694..b4797068 100644 --- a/backend/src/repository/web/multi/repository_handler.rs +++ b/backend/src/repository/web/multi/repository_handler.rs @@ -7,11 +7,11 @@ use std::ops::Deref; use crate::authentication::Authentication; use crate::error::api_error::APIError; -use crate::repository::get_repository_handler; -use crate::repository::handler::RepositoryHandler; +use crate::repository::handler::Repository; use crate::repository::response::RepoResponse; use crate::storage::models::Storage; use crate::storage::multi::MultiStorageController; +use crate::storage::DynamicStorage; #[derive(Deserialize, Clone)] pub struct GetPath { pub storage: String, @@ -26,27 +26,22 @@ impl GetPath { } pub async fn get_repository( pool: web::Data, - storages: web::Data, + storages: web::Data>, auth: Authentication, r: HttpRequest, path: web::Path, ) -> actix_web::Result { let (storage_name, repository_name, file) = path.into_inner().into_inner(); let storage = crate::helpers::get_storage!(storages, storage_name); - let repository = crate::helpers::get_repository!(storage, repository_name) - .deref() - .clone(); - let repository_handler = get_repository_handler(storage, repository) - .await? - .ok_or_else(APIError::repository_not_found)?; - repository_handler + let repository = crate::helpers::get_repository!(storage, repository_name); + repository .handle_get(&file, r.headers(), pool.get_ref(), auth) .await } pub async fn put_repository( pool: web::Data, - storages: web::Data, + storages: web::Data>, auth: Authentication, r: HttpRequest, path: web::Path, @@ -54,40 +49,30 @@ pub async fn put_repository( ) -> actix_web::Result { let (storage_name, repository_name, file) = path.into_inner().into_inner(); let storage = crate::helpers::get_storage!(storages, storage_name); - let repository = crate::helpers::get_repository!(storage, repository_name) - .deref() - .clone(); - let repository_handler = get_repository_handler(storage, repository) - .await? - .ok_or_else(APIError::repository_not_found)?; - repository_handler + let repository = crate::helpers::get_repository!(storage, repository_name); + repository .handle_put(&file, r.headers(), pool.get_ref(), auth, bytes) .await } pub async fn head_repository( pool: web::Data, - storages: web::Data, + storages: web::Data>, auth: Authentication, r: HttpRequest, path: web::Path, ) -> actix_web::Result { let (storage_name, repository_name, file) = path.into_inner().into_inner(); let storage = crate::helpers::get_storage!(storages, storage_name); - let repository = crate::helpers::get_repository!(storage, repository_name) - .deref() - .clone(); - let repository_handler = get_repository_handler(storage, repository) - .await? - .ok_or_else(APIError::repository_not_found)?; - repository_handler + let repository = crate::helpers::get_repository!(storage, repository_name); + repository .handle_head(&file, r.headers(), pool.get_ref(), auth) .await } pub async fn post_repository( pool: web::Data, - storages: web::Data, + storages: web::Data>, auth: Authentication, r: HttpRequest, path: web::Path, @@ -95,20 +80,15 @@ pub async fn post_repository( ) -> actix_web::Result { let (storage_name, repository_name, file) = path.into_inner().into_inner(); let storage = crate::helpers::get_storage!(storages, storage_name); - let repository = crate::helpers::get_repository!(storage, repository_name) - .deref() - .clone(); - let repository_handler = get_repository_handler(storage, repository) - .await? - .ok_or_else(APIError::repository_not_found)?; - repository_handler - .handle_post(&file, r.headers(), pool.get_ref(), auth, bytes) + let repository = crate::helpers::get_repository!(storage, repository_name); + repository + .handle_put(&file, r.headers(), pool.get_ref(), auth, bytes) .await } pub async fn patch_repository( pool: web::Data, - storages: web::Data, + storages: web::Data>, auth: Authentication, r: HttpRequest, path: web::Path, @@ -116,13 +96,8 @@ pub async fn patch_repository( ) -> actix_web::Result { let (storage_name, repository_name, file) = path.into_inner().into_inner(); let storage = crate::helpers::get_storage!(storages, storage_name); - let repository = crate::helpers::get_repository!(storage, repository_name) - .deref() - .clone(); - let repository_handler = get_repository_handler(storage, repository) - .await? - .ok_or_else(APIError::repository_not_found)?; - repository_handler + let repository = crate::helpers::get_repository!(storage, repository_name); + repository .handle_patch(&file, r.headers(), pool.get_ref(), auth, bytes) .await } diff --git a/backend/src/storage/bad_storage.rs b/backend/src/storage/bad_storage.rs index 115d8cf2..8a2d8aef 100644 --- a/backend/src/storage/bad_storage.rs +++ b/backend/src/storage/bad_storage.rs @@ -10,176 +10,20 @@ use tokio::sync::RwLockReadGuard; use crate::repository::settings::{RepositoryConfig, RepositoryType}; use crate::storage::error::StorageError; use crate::storage::file::{StorageFile, StorageFileResponse}; -use crate::storage::models::{ - Storage, StorageConfig, StorageFactory, StorageSaver, StorageStatus, StorageType, -}; +use crate::storage::models::StorageStatus; +use crate::storage::StorageSaver; /// This is a storage that is here to represent a storage that failed to load from the config stage #[derive(Debug)] pub struct BadStorage { - pub factory: StorageFactory, + pub factory: StorageSaver, pub status: StorageStatus, } impl BadStorage { - pub fn create(factory: StorageFactory, error: StorageError) -> BadStorage { + pub fn create(factory: StorageSaver, error: StorageError) -> BadStorage { BadStorage { factory, status: StorageStatus::CreateError(error), } } } -#[async_trait] -impl Storage for BadStorage { - fn create_new(_config: StorageFactory) -> Result - where - Self: Sized, - { - panic!("Illegal Call") - } - - fn new(_: StorageFactory) -> Result - where - Self: Sized, - { - panic!("This should not be called!") - } - async fn load(&mut self) -> Result<(), StorageError> { - warn!("Unable to load Storage Error {}", self.status); - Ok(()) - } - - fn unload(&mut self) -> Result<(), StorageError> { - warn!("Unloaded the Bad Storage"); - Ok(()) - } - - fn config_for_saving(&self) -> StorageSaver { - StorageSaver { - storage_type: self.factory.storage_type.clone(), - generic_config: self.factory.generic_config.clone(), - handler_config: self.factory.handler_config.clone(), - } - } - - fn storage_config(&self) -> &StorageConfig { - &self.factory.generic_config - } - - fn impl_config(&self) -> Value { - self.factory.handler_config.clone() - } - - fn storage_type(&self) -> &StorageType { - &self.factory.storage_type - } - - fn status(&self) -> &StorageStatus { - &self.status - } - - async fn create_repository( - &self, - _name: String, - _repository_type: RepositoryType, - ) -> Result<(), StorageError> { - panic!("This should not be called!") - } - - async fn delete_repository( - &self, - _repository: &RepositoryConfig, - _delete_files: bool, - ) -> Result<(), StorageError> { - panic!("This should not be called!") - } - - async fn get_repositories(&self) -> Result, StorageError> { - panic!("This should not be called!") - } - - async fn get_repository( - &self, - _repository: &str, - ) -> Result>, StorageError> { - panic!("This should not be called!") - } - - async fn update_repository(&self, _repository: RepositoryConfig) -> Result<(), StorageError> { - panic!("This should not be called!") - } - - async fn save_file( - &self, - _repository: &RepositoryConfig, - _file: &[u8], - _location: &str, - ) -> Result { - panic!("This should not be called!") - } - - fn write_file_stream + Unpin + Send + Sync + 'static>( - &self, - repository: &RepositoryConfig, - s: S, - location: &str, - ) -> Result { - panic!("This should not be called!") - } - - async fn delete_file( - &self, - _repository: &RepositoryConfig, - _location: &str, - ) -> Result<(), StorageError> { - panic!("This should not be called!") - } - - async fn get_file_as_response( - &self, - _repository: &RepositoryConfig, - _location: &str, - ) -> Result { - panic!("This should not be called!") - } - - async fn get_file_information( - &self, - _repository: &RepositoryConfig, - _location: &str, - ) -> Result, StorageError> { - panic!("This should not be called!") - } - - async fn get_file( - &self, - _repository: &RepositoryConfig, - _location: &str, - ) -> Result>, StorageError> { - panic!("This should not be called!") - } - - async fn update_repository_config( - &self, - _repository: &RepositoryConfig, - _config_name: &str, - _data: &ConfigType, - ) -> Result<(), StorageError> { - panic!("This should not be called!") - } - - async fn get_repository_config( - &self, - _repository: &RepositoryConfig, - _config_name: &str, - ) -> Result, StorageError> { - panic!("This should not be called!") - } - - async fn delete_repository_config( - &self, - _repository: &RepositoryConfig, - _config_name: &str, - ) -> Result<(), StorageError> { - panic!("This should not be called!") - } -} diff --git a/backend/src/storage/dynamic.rs b/backend/src/storage/dynamic.rs deleted file mode 100644 index 329eccf5..00000000 --- a/backend/src/storage/dynamic.rs +++ /dev/null @@ -1,264 +0,0 @@ -use crate::repository::settings::{RepositoryConfig, RepositoryType}; -use crate::storage::bad_storage::BadStorage; -use crate::storage::error::StorageError; -use crate::storage::file::{StorageFile, StorageFileResponse}; -use crate::storage::local_storage::LocalStorage; -use crate::storage::models::{ - Storage, StorageConfig, StorageFactory, StorageSaver, StorageStatus, StorageType, -}; -use async_trait::async_trait; -use bytes::Bytes; -use futures::Stream; -use serde::de::DeserializeOwned; -use serde::Serialize; -use serde_json::Value; -use tokio::sync::RwLockReadGuard; - -#[derive(Debug)] -pub enum DynamicStorage { - LocalStorage(LocalStorage), - BadStorage(BadStorage), -} - -#[async_trait] -impl Storage for DynamicStorage { - fn create_new(_config: StorageFactory) -> Result - where - Self: Sized, - { - panic!("Illegal Call") - } - - fn new(_config: StorageFactory) -> Result - where - Self: Sized, - { - panic!("Illegal Call") - } - - async fn load(&mut self) -> Result<(), StorageError> { - match self { - DynamicStorage::LocalStorage(local) => local.load().await, - DynamicStorage::BadStorage(bad) => bad.load().await, - } - } - - fn unload(&mut self) -> Result<(), StorageError> { - match self { - DynamicStorage::LocalStorage(local) => local.unload(), - DynamicStorage::BadStorage(bad) => bad.unload(), - } - } - - fn config_for_saving(&self) -> StorageSaver { - match self { - DynamicStorage::LocalStorage(local) => local.config_for_saving(), - DynamicStorage::BadStorage(bad) => bad.config_for_saving(), - } - } - - fn storage_config(&self) -> &StorageConfig { - match self { - DynamicStorage::LocalStorage(local) => local.storage_config(), - DynamicStorage::BadStorage(bad) => bad.storage_config(), - } - } - - fn impl_config(&self) -> Value { - match self { - DynamicStorage::LocalStorage(local) => local.impl_config(), - DynamicStorage::BadStorage(bad) => bad.impl_config(), - } - } - - fn storage_type(&self) -> &StorageType { - match self { - DynamicStorage::LocalStorage(local) => local.storage_type(), - DynamicStorage::BadStorage(bad) => bad.storage_type(), - } - } - - fn status(&self) -> &StorageStatus { - match self { - DynamicStorage::LocalStorage(local) => local.status(), - DynamicStorage::BadStorage(bad) => bad.status(), - } - } - - async fn create_repository( - &self, - name: String, - repository_type: RepositoryType, - ) -> Result<(), StorageError> { - match self { - DynamicStorage::LocalStorage(local) => { - local.create_repository(name, repository_type).await - } - DynamicStorage::BadStorage(bad) => bad.create_repository(name, repository_type).await, - } - } - - async fn delete_repository( - &self, - repository: &RepositoryConfig, - delete_files: bool, - ) -> Result<(), StorageError> { - match self { - DynamicStorage::LocalStorage(local) => { - local.delete_repository(repository, delete_files).await - } - DynamicStorage::BadStorage(bad) => { - bad.delete_repository(repository, delete_files).await - } - } - } - - async fn get_repositories(&self) -> Result, StorageError> { - match self { - DynamicStorage::LocalStorage(local) => local.get_repositories().await, - DynamicStorage::BadStorage(bad) => bad.get_repositories().await, - } - } - - async fn get_repository( - &self, - repository: &str, - ) -> Result>, StorageError> { - match self { - DynamicStorage::LocalStorage(local) => local.get_repository(repository).await, - DynamicStorage::BadStorage(bad) => bad.get_repository(repository).await, - } - } - - async fn update_repository(&self, repository: RepositoryConfig) -> Result<(), StorageError> { - match self { - DynamicStorage::LocalStorage(local) => local.update_repository(repository).await, - DynamicStorage::BadStorage(bad) => bad.update_repository(repository).await, - } - } - - async fn save_file( - &self, - repository: &RepositoryConfig, - file: &[u8], - location: &str, - ) -> Result { - match self { - DynamicStorage::LocalStorage(local) => { - local.save_file(repository, file, location).await - } - DynamicStorage::BadStorage(bad) => bad.save_file(repository, file, location).await, - } - } - - fn write_file_stream + Unpin + Send + Sync + 'static>( - &self, - repository: &RepositoryConfig, - s: S, - location: &str, - ) -> Result { - match self { - DynamicStorage::LocalStorage(local) => local.write_file_stream(repository, s, location), - DynamicStorage::BadStorage(bad) => bad.write_file_stream(repository, s, location), - } - } - - async fn delete_file( - &self, - repository: &RepositoryConfig, - location: &str, - ) -> Result<(), StorageError> { - match self { - DynamicStorage::LocalStorage(local) => local.delete_file(repository, location).await, - DynamicStorage::BadStorage(bad) => bad.delete_file(repository, location).await, - } - } - - async fn get_file_as_response( - &self, - repository: &RepositoryConfig, - location: &str, - ) -> Result { - match self { - DynamicStorage::LocalStorage(local) => { - local.get_file_as_response(repository, location).await - } - DynamicStorage::BadStorage(bad) => bad.get_file_as_response(repository, location).await, - } - } - - async fn get_file_information( - &self, - repository: &RepositoryConfig, - location: &str, - ) -> Result, StorageError> { - match self { - DynamicStorage::LocalStorage(local) => { - local.get_file_information(repository, location).await - } - DynamicStorage::BadStorage(bad) => bad.get_file_information(repository, location).await, - } - } - - async fn get_file( - &self, - repository: &RepositoryConfig, - location: &str, - ) -> Result>, StorageError> { - match self { - DynamicStorage::LocalStorage(local) => local.get_file(repository, location).await, - DynamicStorage::BadStorage(bad) => bad.get_file(repository, location).await, - } - } - - async fn update_repository_config( - &self, - repository: &RepositoryConfig, - config_name: &str, - data: &ConfigType, - ) -> Result<(), StorageError> { - match self { - DynamicStorage::LocalStorage(local) => { - local - .update_repository_config(repository, config_name, data) - .await - } - DynamicStorage::BadStorage(bad) => { - bad.update_repository_config(repository, config_name, data) - .await - } - } - } - - async fn get_repository_config( - &self, - repository: &RepositoryConfig, - config_name: &str, - ) -> Result, StorageError> { - match self { - DynamicStorage::LocalStorage(local) => { - local.get_repository_config(repository, config_name).await - } - DynamicStorage::BadStorage(bad) => { - bad.get_repository_config(repository, config_name).await - } - } - } - - async fn delete_repository_config( - &self, - repository: &RepositoryConfig, - config_name: &str, - ) -> Result<(), StorageError> { - match self { - DynamicStorage::LocalStorage(local) => { - local - .delete_repository_config(repository, config_name) - .await - } - DynamicStorage::BadStorage(bad) => { - bad.delete_repository_config(repository, config_name).await - } - } - } -} diff --git a/backend/src/storage/local_storage/mod.rs b/backend/src/storage/local_storage/mod.rs index 76714c25..6a3d8f29 100644 --- a/backend/src/storage/local_storage/mod.rs +++ b/backend/src/storage/local_storage/mod.rs @@ -1,9 +1,13 @@ use std::collections::HashMap; +use std::hint::unreachable_unchecked; use std::path::PathBuf; +use std::sync::Arc; +use crate::repository::handler::{DynamicRepositoryHandler, Repository}; use async_trait::async_trait; use bytes::Bytes; use futures::Stream; +use lockfree::map::{Map, Removed}; use log::{debug, trace, warn}; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; @@ -18,18 +22,17 @@ use crate::repository::REPOSITORY_CONF_FOLDER; use crate::storage::error::StorageError; use crate::storage::error::StorageError::RepositoryMissing; use crate::storage::file::{StorageDirectoryResponse, StorageFile, StorageFileResponse}; -use crate::storage::models::{ - Storage, StorageConfig, StorageFactory, StorageSaver, StorageStatus, StorageType, -}; -use crate::storage::STORAGE_CONFIG; + +use crate::storage::models::{Storage, StorageStatus}; +use crate::storage::{DynamicStorage, StorageConfig, StorageSaver, STORAGE_CONFIG}; use crate::utils::get_current_time; #[derive(Debug)] pub struct LocalStorage { pub config: LocalConfig, - pub storage_config: StorageConfig, + pub storage_config: StorageSaver, pub status: StorageStatus, - pub repositories: RwLock>, + pub repositories: Map>>, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -66,8 +69,16 @@ impl LocalStorage { } Ok(values) } + async fn number_of_repos(path: PathBuf) -> Result { + trace!("Loading repositories from {}", path.display()); + if !path.exists() { + return Ok(0); + } + let string = read_to_string(&path).await?; + let result: Vec = serde_json::from_str(&string)?; + Ok(result.len()) + } async fn save_repositories(&self) -> Result<(), StorageError> { - let repositories = self.repositories.read().await; let conf = self.get_storage_folder().join(STORAGE_CONFIG); let mut file = OpenOptions::new() @@ -75,7 +86,11 @@ impl LocalStorage { .write(true) .open(conf) .await?; - let values: Vec<&RepositoryConfig> = repositories.values().collect(); + let values: Vec = self + .repositories + .iter() + .map(|v| v.val().get_repository().clone()) + .collect(); let string = serde_json::to_string_pretty(&values)?; file.write_all(string.as_bytes()).await?; Ok(()) @@ -84,198 +99,106 @@ impl LocalStorage { #[async_trait] impl Storage for LocalStorage { - fn create_new(config: StorageFactory) -> Result + type Repository = DynamicRepositoryHandler; + + async fn create_new(config: StorageSaver) -> Result where Self: Sized, { - let string = std::env::var("STORAGE_LOCATION").map_err(|e| { - ( - StorageError::StorageCreateError(e.to_string()), - config.clone(), - ) - })?; - let location = PathBuf::from(&string); - let local_config = LocalConfig { - location: location - .join(&config.generic_config.name) - .canonicalize() - .map_err(|e| { - ( - StorageError::StorageCreateError(e.to_string()), - config.clone(), - ) - })?, - }; - Ok(LocalStorage { - config: local_config, - storage_config: config.generic_config, - status: StorageStatus::Unloaded, - repositories: RwLock::new(HashMap::new()), - }) + todo!() } - fn new(config: StorageFactory) -> Result + async fn new(config: StorageSaver) -> Result where Self: Sized, { - match serde_json::from_value::(config.handler_config.clone()) { - Ok(local) => { - let storage = LocalStorage { - storage_config: config.generic_config, - config: local, - repositories: RwLock::new(Default::default()), - status: StorageStatus::Unloaded, - }; - Ok(storage) - } - Err(error) => Err((StorageError::JSONError(error), config)), - } + let v = if let StorageConfig::LocalStorage(local) = config.handler_config.clone() { + local + } else { + unsafe { unreachable_unchecked() } + }; + let mut storage = LocalStorage { + config: v, + storage_config: config, + status: StorageStatus::Unloaded, + repositories: Map::new(), + }; + Ok(storage) } - async fn load(&mut self) -> Result<(), StorageError> { - if self.status == StorageStatus::Loaded { - return Err(StorageError::LoadFailure( - "Attempted Double Load".to_string(), - )); - } + + async fn get_repos_to_load(&self) -> Result, StorageError> { let repositories = Self::load_repositories(PathBuf::from(&self.config.location).join(STORAGE_CONFIG)) .await?; - self.repositories = RwLock::new(repositories); - return Ok(()); + Ok(repositories) + } + + fn add_repo_loaded + Send>( + &self, + repo: R, + ) -> Result<(), StorageError> { + let repo = repo.into(); + self.repositories + .insert(repo.get_repository().name.clone(), Arc::new(repo)); + Ok(()) } fn unload(&mut self) -> Result<(), StorageError> { - let mut repositories = self.repositories.blocking_write(); //repositories.drain() <--- Note to self. if we add a repository closing. Use this - repositories.clear(); + self.repositories.clear(); self.status = StorageStatus::Unloaded; Ok(()) } - fn config_for_saving(&self) -> StorageSaver { - let value = serde_json::to_value(self.config.clone()).unwrap(); - StorageSaver { - storage_type: StorageType::LocalStorage, - generic_config: self.storage_config.clone(), - handler_config: value, - } - } - fn storage_config(&self) -> &StorageConfig { + fn storage_config(&self) -> &StorageSaver { &self.storage_config } - fn impl_config(&self) -> Value { - serde_json::to_value(self.config.clone()).unwrap() - } - - fn storage_type(&self) -> &StorageType { - &StorageType::LocalStorage - } - - fn status(&self) -> &StorageStatus { - &self.status - } - - async fn create_repository( + async fn create_repository + Send>( &self, - name: String, - repository_type: RepositoryType, + repository: R, ) -> Result<(), StorageError> { - let mut repositories = self.repositories.write().await; - let repository_folder = self.get_repository_folder(&name); - if repositories.contains_key(&name) { - return Err(StorageError::RepositoryAlreadyExists); - } - if repository_folder.exists() { - warn!( - "Creating {:?} on already existing files. This could result in unexpected behavior", - &repository_folder - ); - } - let config = RepositoryConfig { - name: name.clone(), - repository_type, - storage: self.storage_config.name.clone(), - visibility: Default::default(), - active: true, - policy: Default::default(), - created: get_current_time(), - }; - let conf_folder = self - .get_repository_folder(&name) - .join(REPOSITORY_CONF_FOLDER); - if !conf_folder.exists() { - create_dir_all(&conf_folder).await?; - } - let buf = conf_folder.join("config.json"); - let mut file = OpenOptions::new() - .create_new(true) - .write(true) - .open(buf) - .await?; - file.write_all(serde_json::to_string_pretty(&config)?.as_bytes()) - .await?; - repositories.insert(name.clone(), config); - drop(repositories); - self.save_repositories().await?; - Ok(()) + todo!() } - async fn delete_repository( + async fn delete_repository + Send>( &self, - repository: &RepositoryConfig, + repository: S, delete_files: bool, ) -> Result<(), StorageError> { - let mut repositories = self.repositories.write().await; - if repositories.remove(&repository.name).is_none() { - return Err(RepositoryMissing); - } - let repository_folder = self.get_repository_folder(&repository.name); + todo!() + } - if delete_files { - remove_dir(repository_folder).await?; - } else { - let conf_folder = repository_folder.join(REPOSITORY_CONF_FOLDER); - if conf_folder.exists() { - remove_dir(conf_folder).await?; - } - } - drop(repositories); - self.save_repositories().await?; - Ok(()) + fn get_repository_list(&self) -> Result, StorageError> { + todo!() } - async fn get_repositories(&self) -> Result, StorageError> { - let mut repositories_res = Vec::new(); + fn get_repository>( + &self, + repository: S, + ) -> Result>, StorageError> { + todo!() + } - let repositories = self.repositories.read().await; - for (_, config) in repositories.iter() { - repositories_res.push(config.clone()); - } - return Ok(repositories_res); + fn remove_repository_for_updating>( + &self, + repository: S, + ) -> Result>, StorageError> { + todo!() } - async fn get_repository( + async fn add_repository_for_updating( &self, - repository: &str, - ) -> Result>, StorageError> { - let repositories = self.repositories.read().await; - if !repositories.contains_key(repository) { - return Ok(None); - } - Ok(Some(RwLockReadGuard::map(repositories, |repos| { - repos.get(repository).unwrap() - }))) + repository_arc: Self::Repository, + ) -> Result<(), StorageError> { + todo!() } - async fn update_repository(&self, repository: RepositoryConfig) -> Result<(), StorageError> { - let mut repositories = self.repositories.write().await; - if !repositories.contains_key(&repository.name) { - return Err(RepositoryMissing); - } - repositories.insert(repository.name.clone(), repository); - self.save_repositories().await?; - return Ok(()); + async fn add_repository_for_updating_removed( + &self, + repository_arc: Removed>, + ) -> Result<(), StorageError> { + todo!() } async fn save_file( @@ -361,7 +284,10 @@ impl Storage for LocalStorage { return Ok(StorageFileResponse::NotFound); } if file_location.is_dir() { - let mut path = format!("{}/{}", self.storage_config.name, repository.name); + let mut path = format!( + "{}/{}", + self.storage_config.generic_config.id, repository.name + ); for x in location.split('/') { if !x.is_empty() { @@ -425,31 +351,6 @@ impl Storage for LocalStorage { Ok(Some(bytes)) } - async fn update_repository_config( - &self, - repository: &RepositoryConfig, - config_name: &str, - data: &ConfigType, - ) -> Result<(), StorageError> { - let repositories = self.repositories.write().await; - if !repositories.contains_key(&repository.name) { - return Err(StorageError::RepositoryMissing); - } - let buf = self - .get_repository_folder(repository.name.as_str()) - .join(".config.nitro_repo") - .join(config_name); - trace!("Saving Config {:?}", &buf); - let mut file = OpenOptions::new() - .write(true) - .create(true) - .open(buf) - .await?; - file.write_all(serde_json::to_string(data).unwrap().as_bytes()) - .await?; - return Ok(()); - } - async fn get_repository_config( &self, repository: &RepositoryConfig, @@ -468,21 +369,4 @@ impl Storage for LocalStorage { .map(Some) } } - - async fn delete_repository_config( - &self, - repository: &RepositoryConfig, - config_name: &str, - ) -> Result<(), StorageError> { - let repositories = self.repositories.write().await; - if !repositories.contains_key(&repository.name) { - return Err(StorageError::RepositoryMissing); - } - let buf = self - .get_repository_folder(repository.name.as_str()) - .join(".config.nitro_repo") - .join(config_name); - remove_file(buf).await?; - return Ok(()); - } } diff --git a/backend/src/storage/mod.rs b/backend/src/storage/mod.rs index facaad40..92b9544e 100644 --- a/backend/src/storage/mod.rs +++ b/backend/src/storage/mod.rs @@ -1,27 +1,177 @@ use async_trait::async_trait; use bytes::Bytes; use futures::Stream; +use lockfree::map::Removed; use serde::de::DeserializeOwned; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use serde_json::Value; +use std::sync::Arc; use tokio::sync::RwLockReadGuard; use crate::repository::settings::{RepositoryConfig, RepositoryType}; -use crate::storage::bad_storage::BadStorage; use crate::storage::error::StorageError; use crate::storage::file::{StorageFile, StorageFileResponse}; -use crate::storage::local_storage::LocalStorage; -use crate::storage::models::{ - Storage, StorageConfig, StorageFactory, StorageSaver, StorageStatus, StorageType, -}; +use crate::storage::models::{Storage, StorageStatus}; pub mod bad_storage; -pub mod dynamic; pub mod error; pub mod file; pub mod local_storage; pub mod models; pub mod multi; -pub use dynamic::DynamicStorage; pub static STORAGES_CONFIG: &str = "storages.nitro_repo"; pub static STORAGE_CONFIG: &str = "storage.nitro_repo"; +use crate::repository::handler::DynamicRepositoryHandler; +use bad_storage::BadStorage; +use local_storage::{LocalConfig, LocalStorage}; +use std::collections::HashMap; +use std::hint::unreachable_unchecked; +macro_rules! storages { + ($($name:ident, $ty:tt, $config:tt),*) => { + #[derive(Debug, Clone, Serialize, Deserialize)] + pub enum StorageType{ + $($name,)* + } + #[derive(Debug, Clone, Serialize, Deserialize)] + pub enum StorageConfig { + $($name($config),)* + } + #[derive(Debug)] + pub enum DynamicStorage{ + BadStorage(BadStorage), + $($name($ty),)* + } +#[async_trait] +impl Storage for DynamicStorage{ + type Repository = DynamicRepositoryHandler; + + async fn create_new(config: StorageSaver) -> Result where Self: Sized { + match config.storage_type.clone() { + $(StorageType::$name => { + let factory = config.clone(); + $ty::create_new(config).await.map(|storage| DynamicStorage::$name(storage)) + })* + } + } + + async fn new(config: StorageSaver) -> Result where Self: Sized { + match config.storage_type.clone() { + $(StorageType::$name => { + let factory = config.clone(); + $ty::new(config).await.map(|storage| DynamicStorage::$name(storage)) + })* + } + } + async fn get_repos_to_load(&self) -> Result, StorageError>{ + match self { + $(DynamicStorage::$name(storage) => storage.get_repos_to_load().await,)* + _ => unsafe{ unreachable_unchecked() } + } + } + + fn add_repo_loaded + Send>(&self, repo: R) -> Result<(), StorageError>{ + match self { + $(DynamicStorage::$name(storage) => storage.add_repo_loaded(repo),)* + _ => unsafe{ unreachable_unchecked() } + } + } + + fn unload(&mut self) -> Result<(), StorageError> { + match self { + $(DynamicStorage::$name(storage) => storage.unload(),)* + _ => unsafe{ unreachable_unchecked() } + } + } + + fn storage_config(&self) -> &StorageSaver { + match self { + $(DynamicStorage::$name(storage) => storage.storage_config(),)* + DynamicStorage::BadStorage(storage) => &storage.factory, + } + } + + async fn create_repository + Send>(&self, repository: R) -> Result<(), StorageError> { + todo!() + } + + async fn delete_repository + Send>(&self, repository: S, delete_files: bool) -> Result<(), StorageError> { + todo!() + } + + fn get_repository_list(&self) -> Result, StorageError> { + todo!() + } + + fn get_repository>(&self, repository: S) -> Result>, StorageError> { + todo!() + } + + fn remove_repository_for_updating>(&self, repository: S) -> Result>, StorageError> { + todo!() + } + + async fn add_repository_for_updating(&self, repository_arc: Self::Repository) -> Result<(), StorageError> { + todo!() + } + + async fn add_repository_for_updating_removed(&self, repository_arc: Removed>) -> Result<(), StorageError> { + todo!() + } + + async fn save_file(&self, repository: &RepositoryConfig, file: &[u8], location: &str) -> Result { + todo!() + } + + fn write_file_stream + Unpin + Send + Sync + 'static>(&self, repository: &RepositoryConfig, s: S, location: &str) -> Result { + todo!() + } + + async fn delete_file(&self, repository: &RepositoryConfig, location: &str) -> Result<(), StorageError> { + todo!() + } + + async fn get_file_as_response(&self, repository: &RepositoryConfig, location: &str) -> Result { + todo!() + } + + async fn get_file_information(&self, repository: &RepositoryConfig, location: &str) -> Result, StorageError> { + todo!() + } + + async fn get_file(&self, repository: &RepositoryConfig, location: &str) -> Result>, StorageError> { + todo!() + } + async fn get_repository_config( + &self, + repository: &RepositoryConfig, + config_name: &str, + ) -> Result, StorageError> { + match self { + $(DynamicStorage::$name(storage) => storage.get_repository_config(repository, config_name).await,)* + _ => unsafe{ unreachable_unchecked() } + } + } +} + }; +} + +storages!(LocalStorage, LocalStorage, LocalConfig); + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct StorageSaver { + /// The Type of the Storage + pub storage_type: StorageType, + /// The Storage Config + #[serde(flatten)] + pub generic_config: GeneralConfig, + /// Storage Handler Config + pub handler_config: StorageConfig, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct GeneralConfig { + pub id: String, + /// This is created internally by the storage. No need to set this. + #[serde(default = "crate::utils::get_current_time")] + pub created: i64, +} diff --git a/backend/src/storage/models.rs b/backend/src/storage/models.rs index abc5d7f5..0b922ec0 100644 --- a/backend/src/storage/models.rs +++ b/backend/src/storage/models.rs @@ -1,7 +1,11 @@ +use std::collections::HashMap; use std::fmt::{Debug, Display, Formatter}; +use std::sync::Arc; +use crate::repository::handler::Repository; use async_trait::async_trait; use bytes::Bytes; +use lockfree::map::Removed; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -9,20 +13,15 @@ use tokio::sync::RwLockReadGuard; use tokio_stream::Stream; use crate::repository::settings::{RepositoryConfig, RepositoryType}; -use crate::storage::dynamic::DynamicStorage; use crate::storage::error::StorageError; use crate::storage::file::{StorageFile, StorageFileResponse}; use crate::storage::local_storage::LocalStorage; +use crate::storage::DynamicStorage; +use crate::storage::{StorageConfig, StorageSaver}; pub static STORAGE_FILE: &str = "storages.json"; pub static STORAGE_FILE_BAK: &str = "storages.json.bak"; -/// Types of Storages -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum StorageType { - LocalStorage, -} - /// Storage Status #[derive(Debug)] pub enum StorageStatus { @@ -61,104 +60,62 @@ impl Display for StorageStatus { } } -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct StorageSaver { - /// The Type of the Storage - pub storage_type: StorageType, - /// The Storage Config - #[serde(flatten)] - pub generic_config: StorageConfig, - /// Storage Handler Config - pub handler_config: Value, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct StorageConfig { - /// The public name of the storage - pub public_name: String, - /// The internal name of the storage - pub name: String, - /// This is created internally by the storage. No need to set this. - #[serde(default = "crate::utils::get_current_time")] - pub created: i64, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct StorageFactory { - pub storage_type: StorageType, - #[serde(flatten)] - pub generic_config: StorageConfig, - /// Storage Handler Config - #[serde(default)] - pub handler_config: Value, -} - -impl StorageFactory { - pub fn config_for_saving(&self) -> StorageSaver { - StorageSaver { - storage_type: self.storage_type.clone(), - generic_config: self.generic_config.clone(), - handler_config: self.handler_config.clone(), - } - } -} - -impl StorageFactory { - pub async fn build(self) -> Result { - match &self.storage_type { - StorageType::LocalStorage => LocalStorage::new(self).map(DynamicStorage::LocalStorage), - } - } -} - #[async_trait] pub trait Storage: Send + Sync { + type Repository: Repository; /// Initialize the Storage at Storage start. - fn create_new(config: StorageFactory) -> Result + async fn create_new(config: StorageSaver) -> Result where Self: Sized; /// Initialize the Storage at Storage start. - fn new(config: StorageFactory) -> Result + async fn new(config: StorageSaver) -> Result where Self: Sized; // Attempts to Load the Storage - async fn load(&mut self) -> Result<(), StorageError>; + async fn get_repos_to_load(&self) -> Result, StorageError>; + + fn add_repo_loaded + Send>( + &self, + repo: R, + ) -> Result<(), StorageError>; /// Unload the storage fn unload(&mut self) -> Result<(), StorageError>; - /// Returns a StorageSaver - /// I would like this to be a data reference in the future - fn config_for_saving(&self) -> StorageSaver; - fn storage_config(&self) -> &StorageConfig; - /// Returns a Owned copy of the Implementation of Type Config. As a serde_json::Value - fn impl_config(&self) -> Value; - /// Returns the Storage Type - fn storage_type(&self) -> &StorageType; - /// The current status of the Storage - fn status(&self) -> &StorageStatus; + fn storage_config(&self) -> &StorageSaver; /// Creates a new Repository /// Requires just the name and RepositoryType - async fn create_repository( + async fn create_repository + Send>( &self, - name: String, - repository_type: RepositoryType, + repository: R, ) -> Result<(), StorageError>; /// Deletes a Repository /// delete_files rather or not to clean out the Repository Data - async fn delete_repository( + async fn delete_repository + Send>( &self, - repository: &RepositoryConfig, + repository: S, delete_files: bool, ) -> Result<(), StorageError>; /// Gets a Owned Vec of Repositories - async fn get_repositories(&self) -> Result, StorageError>; + fn get_repository_list(&self) -> Result, StorageError>; /// Returns a RwLockReadGuard of the RepositoryConfig - async fn get_repository( + fn get_repository>( &self, - repository: &str, - ) -> Result>, StorageError>; + repository: S, + ) -> Result>, StorageError>; - async fn update_repository(&self, repository: RepositoryConfig) -> Result<(), StorageError>; + fn remove_repository_for_updating>( + &self, + repository: S, + ) -> Result>, StorageError>; + /// Will update all configs for the Repository + async fn add_repository_for_updating( + &self, + repository_arc: Self::Repository, + ) -> Result<(), StorageError>; + async fn add_repository_for_updating_removed( + &self, + repository_arc: Removed>, + ) -> Result<(), StorageError>; /// Saves a File to a location /// Will overwrite any data found async fn save_file( @@ -200,25 +157,10 @@ pub trait Storage: Send + Sync { repository: &RepositoryConfig, location: &str, ) -> Result>, StorageError>; - - /// Locks the Repositories for updating - /// Keeps all config files in .config - async fn update_repository_config( - &self, - repository: &RepositoryConfig, - config_name: &str, - data: &ConfigType, - ) -> Result<(), StorageError>; /// Gets a Repository Config async fn get_repository_config( &self, repository: &RepositoryConfig, config_name: &str, ) -> Result, StorageError>; - /// Delete Repository Config - async fn delete_repository_config( - &self, - repository: &RepositoryConfig, - config_name: &str, - ) -> Result<(), StorageError>; } diff --git a/backend/src/storage/multi/mod.rs b/backend/src/storage/multi/mod.rs index 522cc314..0006a5d2 100644 --- a/backend/src/storage/multi/mod.rs +++ b/backend/src/storage/multi/mod.rs @@ -1,6 +1,10 @@ +use lockfree::map::Map; use std::collections::HashMap; +use std::mem; use std::path::{Path, PathBuf}; +use std::sync::Arc; +use crate::repository::handler::DynamicRepositoryHandler; use log::{error, info}; use tokio::fs; use tokio::fs::{read_to_string, OpenOptions}; @@ -8,31 +12,30 @@ use tokio::io::AsyncWriteExt; use tokio::sync::{RwLock, RwLockReadGuard}; use crate::storage::bad_storage::BadStorage; -use crate::storage::dynamic::DynamicStorage; use crate::storage::error::StorageError; use crate::storage::file::StorageFile; -use crate::storage::models::{ - Storage, StorageFactory, StorageSaver, StorageStatus, STORAGE_FILE, STORAGE_FILE_BAK, -}; + +use crate::storage::models::{Storage, STORAGE_FILE, STORAGE_FILE_BAK}; +use crate::storage::{DynamicStorage, StorageSaver}; pub mod web; async fn load_storages( storages_file: PathBuf, -) -> Result, StorageError> { +) -> Result>, StorageError> { if !storages_file.exists() { - return Ok(HashMap::new()); + return Ok(Map::new()); } let string = read_to_string(&storages_file).await?; - let result: Vec = serde_json::from_str(&string)?; - let mut values: HashMap = HashMap::new(); + let result: Vec = serde_json::from_str(&string)?; + let mut values: Map> = Map::new(); for factory in result { - let name = factory.generic_config.name.clone(); - let storage = match factory.build().await { + let name = factory.generic_config.id.clone(); + let storage = match DynamicStorage::new(factory).await { Ok(value) => value, Err((error, factory)) => DynamicStorage::BadStorage(BadStorage::create(factory, error)), }; - values.insert(name, storage); + values.insert(name, Arc::new(storage)); } Ok(values) } @@ -56,118 +59,90 @@ pub async fn save_storages(storages: &Vec) -> Result<(), StorageEr Ok(()) } #[derive(Debug)] -pub struct MultiStorageController { - pub storages: RwLock>, +pub struct MultiStorageController { + pub storages: Map>, + pub unloaded_storages: Map>, } -impl MultiStorageController { - pub async fn init(storages_file: PathBuf) -> Result { +impl MultiStorageController { + pub async fn init( + storages_file: PathBuf, + ) -> Result, StorageError> { info!("Loading Storages"); let result = load_storages(storages_file).await?; - let controller = MultiStorageController { - storages: RwLock::new(result), + let mut controller = MultiStorageController { + storages: Map::new(), + unloaded_storages: result, }; controller.load_unloaded_storages().await?; Ok(controller) } -} - -impl MultiStorageController { pub async fn get_storage_by_name( &self, name: &str, - ) -> Result>, StorageError> { - let storages = self.storages.read().await; - if !storages.contains_key(name) { - return Ok(None); + ) -> Result>, StorageError> { + let storages = self.storages.get(name); + if let Some(storage) = storages { + Ok(Some(storage.as_ref().1.clone())) + } else { + Ok(None) } - let storage = RwLockReadGuard::map(storages, |storages| { - let storage = storages.get(name).unwrap(); - storage - }); - Ok(Some(storage)) } - pub async fn does_storage_exist(&self, name: &str) -> Result { - let storages = self.storages.read().await; - Ok(storages.contains_key(name)) + pub fn does_storage_exist(&self, name: &str) -> Result { + let storages = self.storages.get(name); + Ok(storages.is_some()) } - pub async fn create_storage<'a>(&self, storage: StorageFactory) -> Result<(), StorageError> { - let mut storages = self.storages.write().await; - let name = storage.generic_config.name.clone(); - - if storages.contains_key(&name) { - return Err(StorageError::StorageAlreadyExist); - } - { - let mut storages_saving = Vec::new(); - for (_, storage) in storages.iter() { - storages_saving.push(storage.config_for_saving()); - } - storages_saving.push(storage.config_for_saving()); - save_storages(&storages_saving).await?; - } - let storage_name = name.clone(); - - let storage_handler = storage.build().await.unwrap(); - storages.insert(storage_name.clone(), storage_handler); - Ok(()) - } /// Attempts to run the storage load on any storages that are unloaded. /// This will include the Error storages - pub async fn load_unloaded_storages<'a>(&self) -> Result<(), StorageError> { - let mut guard = self.storages.write().await; - for (name, storage) in guard.iter_mut() { - match storage.status() { - StorageStatus::Unloaded => { - info!("Loading Storage {}", name); - storage.load().await?; + pub async fn load_unloaded_storages<'a>(&mut self) -> Result<(), StorageError> { + let mut unloaded = mem::take(&mut self.unloaded_storages); + for (name, storage) in unloaded.into_iter() { + match storage.get_repos_to_load().await { + Ok(repositories) => { + for (name, repository) in repositories.into_iter() { + info!("Loading repository {}", name); + let handler = + DynamicRepositoryHandler::new_dyn_storage(storage.clone(), repository) + .await + .map_err(|error| { + error!("Error loading repository {}", name); + }); + if let Ok(handler) = handler { + storage.add_repo_loaded(handler)?; + } + } } - StorageStatus::Error(_) => { - info!("Loading Storage {}", name); - storage.load().await?; + Err(error) => { + error!("Error loading storage {}: {}", name, error); } - _ => {} } + self.storages.insert(name, storage); } Ok(()) } + pub async fn create_storage<'a>(&self, storage: StorageSaver) -> Result<(), StorageError> { + todo!() + } + pub async fn delete_storage(&self, storage: &str) -> Result { - let mut storages = self.storages.write().await; - let option = storages.remove(storage); - if option.is_none() { - return Ok(false); - } - let mut storage = option.unwrap(); - drop(storages); - // Save the new storages - save_storages(self.storage_savers().await.as_ref()).await?; - if let Err(error) = storage.unload() { - error!( - "Storage has been removed config. However, it failed to unload properly {}", - error - ); - } - Ok(true) + todo!() } pub async fn storage_savers(&self) -> Vec { - let storages = self.storages.read().await; - - let mut storages_saving = Vec::new(); - for (_, storage) in storages.iter() { - storages_saving.push(storage.config_for_saving().clone()); - } - storages_saving + todo!() } pub async fn names(&self) -> Vec { - let storages = self.storages.read().await; - storages.keys().cloned().collect() + self.storages + .iter() + .map(|v| v.key().clone()) + .collect::>() } pub async fn storages_as_file_list(&self) -> Result, StorageError> { - let storages = self.storages.read().await; let mut files = Vec::new(); - for (name, storage) in storages.iter() { + for v in self.storages.iter() { + let name = v.0.clone(); + let create = v.1.as_ref().storage_config().generic_config.created; files.push(StorageFile { name: name.clone(), full_path: name.clone(), @@ -175,7 +150,7 @@ impl MultiStorageController { directory: true, file_size: 0, modified: 0, - created: storage.config_for_saving().generic_config.created as u128, + created: create as u128, }); } Ok(files) diff --git a/backend/src/storage/multi/web/admin.rs b/backend/src/storage/multi/web/admin.rs index 73c7e924..a7bc01f4 100644 --- a/backend/src/storage/multi/web/admin.rs +++ b/backend/src/storage/multi/web/admin.rs @@ -7,14 +7,14 @@ use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; use crate::storage::error::StorageError; use crate::storage::models::Storage; -use crate::storage::models::StorageFactory; use crate::storage::multi::MultiStorageController; +use crate::storage::{DynamicStorage, StorageSaver}; use crate::system::permissions::options::CanIDo; use crate::system::user::UserModel; #[get("/storages")] pub async fn get_storages( - storage_handler: web::Data, + storage_handler: web::Data>, database: web::Data, auth: Authentication, ) -> actix_web::Result { @@ -27,8 +27,8 @@ pub async fn get_storages( /// Creates a new storage based on the Storage Factory #[post("/storage/new")] pub async fn new_storage( - storage_handler: web::Data, - new_storage: web::Json, + storage_handler: web::Data>, + new_storage: web::Json, database: web::Data, auth: Authentication, ) -> actix_web::Result { @@ -51,7 +51,7 @@ pub async fn new_storage( /// Delete the storage based on the name #[delete("/storage/{name}")] pub async fn delete_storage( - storage_handler: web::Data, + storage_handler: web::Data>, database: web::Data, auth: Authentication, name: web::Path, @@ -71,7 +71,7 @@ pub async fn delete_storage( #[get("/storage/{name}")] pub async fn get_storage( - storage_handler: web::Data, + storage_handler: web::Data>, name: web::Path, database: web::Data, auth: Authentication, @@ -79,5 +79,5 @@ pub async fn get_storage( let user: UserModel = auth.get_user(&database).await??; user.can_i_edit_repos()?; let storage = crate::helpers::get_storage!(storage_handler, name); - Ok(HttpResponse::Ok().json(storage.config_for_saving())) + Ok(HttpResponse::Ok().json(storage.storage_config())) } diff --git a/backend/src/storage/multi/web/public.rs b/backend/src/storage/multi/web/public.rs index 30b451c8..d587af8f 100644 --- a/backend/src/storage/multi/web/public.rs +++ b/backend/src/storage/multi/web/public.rs @@ -4,6 +4,7 @@ use serde::{Deserialize, Serialize}; use crate::authentication::Authentication; use crate::storage::multi::MultiStorageController; +use crate::storage::DynamicStorage; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct PublicStorageResponse { /// The List of Storages that are available to the current user @@ -13,7 +14,7 @@ pub struct PublicStorageResponse { } #[get("/storages")] pub async fn get_storages_multi( - storage_handler: web::Data, + storage_handler: web::Data>, _database: web::Data, _auth: Authentication, ) -> actix_web::Result { From dee14a94fe8cbc5b7fdc29832f1076b9c0415653 Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Thu, 21 Jul 2022 15:26:36 -0400 Subject: [PATCH 42/76] its "working" again --- backend/src/authentication/middleware.rs | 30 +++---- .../src/authentication/session/basic/mod.rs | 1 - backend/src/authentication/session/mod.rs | 1 - backend/src/bin/nitro_repo_full.rs | 3 +- backend/src/bin/simple_installer.rs | 6 +- backend/src/cli/mod.rs | 2 +- backend/src/helpers.rs | 24 ++++++ backend/src/repository/ci/mod.rs | 16 +++- backend/src/repository/docker/mod.rs | 16 +++- backend/src/repository/handler.rs | 25 +++++- backend/src/repository/maven/hosted.rs | 26 ++++-- backend/src/repository/maven/mod.rs | 20 +++-- backend/src/repository/maven/models.rs | 4 - backend/src/repository/maven/proxy.rs | 34 +++++--- backend/src/repository/maven/staging.rs | 52 +++++++----- backend/src/repository/nitro/dynamic.rs | 22 +++--- .../src/repository/nitro/nitro_repository.rs | 2 +- backend/src/repository/npm/mod.rs | 28 ++++--- backend/src/repository/raw/mod.rs | 16 +++- backend/src/repository/settings/mod.rs | 4 +- backend/src/repository/staging/dynamic.rs | 7 +- backend/src/repository/staging/mod.rs | 7 +- backend/src/repository/web/mod.rs | 2 +- backend/src/repository/web/multi/admin.rs | 45 +++++------ backend/src/repository/web/multi/configs.rs | 8 +- backend/src/repository/web/multi/mod.rs | 7 +- .../repository/web/multi/public/project.rs | 19 ++--- .../web/multi/public/repositories.rs | 21 ++--- .../web/multi/repository_handler.rs | 2 - backend/src/storage/bad_storage.rs | 12 +-- backend/src/storage/local_storage/mod.rs | 52 ++++++------ backend/src/storage/mod.rs | 79 +++++++++++++------ backend/src/storage/models.rs | 19 ++--- backend/src/storage/multi/mod.rs | 13 ++- 34 files changed, 358 insertions(+), 267 deletions(-) diff --git a/backend/src/authentication/middleware.rs b/backend/src/authentication/middleware.rs index 65f28efa..ffd3c64a 100644 --- a/backend/src/authentication/middleware.rs +++ b/backend/src/authentication/middleware.rs @@ -1,9 +1,7 @@ use std::fmt; use std::future::{ready, Ready}; use std::rc::Rc; -use std::time::SystemTime; -use actix_web::cookie::time::OffsetDateTime; use actix_web::cookie::{Cookie, Expiration, SameSite}; use actix_web::http::header::{HeaderValue, AUTHORIZATION, ORIGIN, SET_COOKIE}; use actix_web::http::Method; @@ -185,24 +183,22 @@ where ) } } - } else { - if run_cookies { - // Try to create a new Session for the user. Could be a first request - // Require a Origin Header for request - if let Some(origin) = req.headers().get(ORIGIN) { - trace!( - "Creating a new Session for {}. ", - origin.to_str().unwrap_or("Bad Origin") - ); - let session = session_manager.create_session().await.unwrap(); - (Authentication::Session(session.clone()), Some(session)) - } else { - warn!("A Not Origin Not Authorized Request was made"); - (Authentication::NoIdentification, Option::None) - } + } else if run_cookies { + // Try to create a new Session for the user. Could be a first request + // Require a Origin Header for request + if let Some(origin) = req.headers().get(ORIGIN) { + trace!( + "Creating a new Session for {}. ", + origin.to_str().unwrap_or("Bad Origin") + ); + let session = session_manager.create_session().await.unwrap(); + (Authentication::Session(session.clone()), Some(session)) } else { + warn!("A Not Origin Not Authorized Request was made"); (Authentication::NoIdentification, Option::None) } + } else { + (Authentication::NoIdentification, Option::None) }; // Add the authentication Information for the data req.extensions_mut().insert(authentication); diff --git a/backend/src/authentication/session/basic/mod.rs b/backend/src/authentication/session/basic/mod.rs index 6ffd3d37..95f2f3b8 100644 --- a/backend/src/authentication/session/basic/mod.rs +++ b/backend/src/authentication/session/basic/mod.rs @@ -1,5 +1,4 @@ use std::collections::HashMap; -use std::ops::Add; use async_trait::async_trait; use chrono::Duration; diff --git a/backend/src/authentication/session/mod.rs b/backend/src/authentication/session/mod.rs index b4a57b27..10373e50 100644 --- a/backend/src/authentication/session/mod.rs +++ b/backend/src/authentication/session/mod.rs @@ -5,7 +5,6 @@ use crate::authentication::session::basic::BasicSessionManager; use crate::authentication::session::redis_manager::RedisSessionManager; use crate::settings::models::SessionSettings; use async_trait::async_trait; -use chrono::NaiveDateTime; pub enum SessionManager { BasicSessionManager(BasicSessionManager), diff --git a/backend/src/bin/nitro_repo_full.rs b/backend/src/bin/nitro_repo_full.rs index 23cfccf2..78413d6e 100644 --- a/backend/src/bin/nitro_repo_full.rs +++ b/backend/src/bin/nitro_repo_full.rs @@ -11,8 +11,7 @@ use actix_web::{web, App, HttpServer}; use api::authentication::middleware::HandleSession; use api::authentication::session::SessionManager; use api::cli::handle_cli; -use api::repository::maven::settings::{MavenSettings, MavenType, ProxySettings}; -use api::repository::maven::staging::StageSettings; + use api::settings::load_configs; use api::settings::models::GeneralSettings; use api::storage::local_storage::LocalConfig; diff --git a/backend/src/bin/simple_installer.rs b/backend/src/bin/simple_installer.rs index 7eb09e9c..30bb0573 100644 --- a/backend/src/bin/simple_installer.rs +++ b/backend/src/bin/simple_installer.rs @@ -6,8 +6,8 @@ use api::system::{hash, user}; use api::utils::get_current_time; use clap::{Parser, Subcommand}; use sea_orm::ActiveValue::Set; -use sea_orm::{ConnectOptions, DatabaseConnection, EntityTrait}; -use semver::Op; +use sea_orm::{ConnectOptions, EntityTrait}; + use std::env; use std::fs::OpenOptions; use std::path::Path; @@ -67,7 +67,7 @@ async fn main() { } }; if let Database::Sqlite(sql) = &config { - println!("{}", sql.to_string()); + println!("{}", sql); OpenOptions::new() .create(true) .write(true) diff --git a/backend/src/cli/mod.rs b/backend/src/cli/mod.rs index 99812645..a641117a 100644 --- a/backend/src/cli/mod.rs +++ b/backend/src/cli/mod.rs @@ -14,7 +14,7 @@ struct NitroRepoCLI { } pub async fn handle_cli() -> std::io::Result { - let path = current_dir()?; + let _path = current_dir()?; let parse: NitroRepoCLI = NitroRepoCLI::parse(); if let Some(update) = parse.update { diff --git a/backend/src/helpers.rs b/backend/src/helpers.rs index 4b159a01..879cf84a 100644 --- a/backend/src/helpers.rs +++ b/backend/src/helpers.rs @@ -34,5 +34,29 @@ macro_rules! get_repository { } }; } + +macro_rules! take_repository { + ($storage:ident, $repository:ident) => { + if let Some(repository) = $storage.remove_repository_for_updating($repository) { + match Removed::try_into(repository) { + Ok((name, arc)) => match Arc::try_unwrap(arc) { + Ok(ok) => (name, ok), + Err(v) => { + let arc1 = (*v).clone(); + (name, arc1) + } + }, + Err(v) => { + let (name, arc) = (*v).clone(); + let arc = (*arc).clone(); + (name, arc) + } + } + } else { + return Ok(actix_web::HttpResponse::NotFound().finish().into()); + } + }; +} pub(crate) use get_repository; pub(crate) use get_storage; +pub(crate) use take_repository; diff --git a/backend/src/repository/ci/mod.rs b/backend/src/repository/ci/mod.rs index 24cd24dd..c5760bc1 100644 --- a/backend/src/repository/ci/mod.rs +++ b/backend/src/repository/ci/mod.rs @@ -4,8 +4,7 @@ use crate::repository::settings::RepositoryConfig; use crate::storage::models::Storage; use async_trait::async_trait; use std::sync::Arc; -use tokio::sync::RwLockReadGuard; - +#[derive(Debug)] pub struct CIHandler { config: RepositoryConfig, storage: Arc, @@ -18,13 +17,22 @@ impl CIHandler { Ok(CIHandler { config, storage }) } } - +impl Clone for CIHandler { + fn clone(&self) -> Self { + CIHandler { + config: self.config.clone(), + storage: self.storage.clone(), + } + } +} #[async_trait] impl Repository for CIHandler { fn get_repository(&self) -> &RepositoryConfig { &self.config } - + fn get_mut_config(&mut self) -> &mut RepositoryConfig { + &mut self.config + } fn get_storage(&self) -> &StorageType { &self.storage } diff --git a/backend/src/repository/docker/mod.rs b/backend/src/repository/docker/mod.rs index 3c09a97a..341b7cba 100644 --- a/backend/src/repository/docker/mod.rs +++ b/backend/src/repository/docker/mod.rs @@ -4,8 +4,7 @@ use crate::repository::settings::RepositoryConfig; use crate::storage::models::Storage; use async_trait::async_trait; use std::sync::Arc; -use tokio::sync::RwLockReadGuard; - +#[derive(Debug)] pub struct DockerHandler { config: RepositoryConfig, storage: Arc, @@ -19,12 +18,23 @@ impl DockerHandler { } } +impl Clone for DockerHandler { + fn clone(&self) -> Self { + DockerHandler { + config: self.config.clone(), + storage: self.storage.clone(), + } + } +} + #[async_trait] impl Repository for DockerHandler { fn get_repository(&self) -> &RepositoryConfig { &self.config } - + fn get_mut_config(&mut self) -> &mut RepositoryConfig { + &mut self.config + } fn get_storage(&self) -> &StorageType { &self.storage } diff --git a/backend/src/repository/handler.rs b/backend/src/repository/handler.rs index eb27bfcb..180685c3 100644 --- a/backend/src/repository/handler.rs +++ b/backend/src/repository/handler.rs @@ -4,8 +4,7 @@ use actix_web::web::Bytes; use actix_web::Error; use async_trait::async_trait; use sea_orm::DatabaseConnection; -use std::sync::{Arc, Weak}; -use tokio::sync::RwLockReadGuard; +use std::sync::Arc; use crate::authentication::Authentication; use crate::error::api_error::APIError; @@ -16,8 +15,9 @@ use crate::repository::settings::RepositoryConfig; use crate::storage::models::Storage; use serde::{Deserialize, Serialize}; #[async_trait] -pub trait Repository: Send + Sync { +pub trait Repository: Send + Sync + Clone { fn get_repository(&self) -> &RepositoryConfig; + fn get_mut_config(&mut self) -> &mut RepositoryConfig; fn get_storage(&self) -> &S; /// Handles a get request to a Repo @@ -97,12 +97,21 @@ pub trait Repository: Send + Sync { macro_rules! repository_handler { ($name:ident, $($repository_type:ident,$repository_tt:tt),*) => { - + #[derive(Debug)] pub enum $name { $( $repository_type($repository_tt), )* } + impl< StorageType: Storage> Clone for $name { + fn clone(&self) -> Self { + match self { + $( + $name::$repository_type(repo) => $name::$repository_type((repo).clone()), + )* + } + } + } // Implement From<$repository_tt> for $name $( impl<'a, StorageType: Storage> From<$repository_tt> for $name { @@ -115,6 +124,7 @@ macro_rules! repository_handler { impl Repository for $name { + fn get_repository(&self) -> &RepositoryConfig { match self { $( @@ -122,6 +132,13 @@ macro_rules! repository_handler { )* } } + fn get_mut_config(&mut self) -> &mut RepositoryConfig { + match self { + $( + $name::$repository_type(repository) => repository.get_mut_config(), + )* + } + } fn get_storage(&self) -> &StorageType { match self { $( diff --git a/backend/src/repository/maven/hosted.rs b/backend/src/repository/maven/hosted.rs index 9dfa605d..eef3b093 100644 --- a/backend/src/repository/maven/hosted.rs +++ b/backend/src/repository/maven/hosted.rs @@ -2,8 +2,7 @@ use crate::authentication::Authentication; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; use crate::repository::handler::Repository; -use crate::repository::maven::models::Pom; -use crate::repository::maven::settings::ProxySettings; + use crate::repository::response::RepoResponse; use crate::repository::settings::{Policy, RepositoryConfig, Visibility}; use crate::storage::file::StorageFileResponse; @@ -14,21 +13,34 @@ use actix_web::http::header::HeaderMap; use actix_web::http::StatusCode; use actix_web::web::Bytes; use async_trait::async_trait; -use log::error; -use sea_orm::DatabaseConnection; -use std::sync::{Arc, Weak}; -use tokio::sync::RwLockReadGuard; +use sea_orm::DatabaseConnection; +use std::sync::Arc; +#[derive(Debug)] pub struct HostedMavenRepository { pub config: RepositoryConfig, pub storage: Arc, } + +impl Clone for HostedMavenRepository { + fn clone(&self) -> Self { + HostedMavenRepository { + config: self.config.clone(), + storage: self.storage.clone(), + } + } +} + #[async_trait] impl Repository for HostedMavenRepository { fn get_repository(&self) -> &RepositoryConfig { &self.config } + fn get_mut_config(&mut self) -> &mut RepositoryConfig { + &mut self.config + } + fn get_storage(&self) -> &S { self.storage.as_ref() } @@ -53,7 +65,7 @@ impl Repository for HostedMavenRepository { .await .map_err(InternalError::from)? { - StorageFileResponse::List(list) => { + StorageFileResponse::List(_list) => { /* let files = self.process_storage_files(list, path).await?; Ok(RepoResponse::try_from((files, StatusCode::OK))?)*/ panic!("Not implemented") diff --git a/backend/src/repository/maven/mod.rs b/backend/src/repository/maven/mod.rs index 3ed4292e..4aaa8c17 100644 --- a/backend/src/repository/maven/mod.rs +++ b/backend/src/repository/maven/mod.rs @@ -1,24 +1,22 @@ use actix_web::http::header::HeaderMap; -use actix_web::http::StatusCode; + use actix_web::web::Bytes; use async_trait::async_trait; -use log::error; + use sea_orm::DatabaseConnection; -use std::ops::Deref; -use std::sync::{Arc, Weak}; -use tokio::sync::RwLockReadGuard; + +use std::sync::Arc; use crate::authentication::Authentication; -use crate::error::api_error::APIError; + use crate::error::internal_error::InternalError; use crate::repository::handler::{repository_handler, Repository}; -use crate::repository::maven::models::Pom; + use crate::repository::response::RepoResponse; -use crate::repository::settings::{Policy, RepositoryConfig, Visibility}; -use crate::storage::file::StorageFileResponse; +use crate::repository::settings::RepositoryConfig; + use crate::storage::models::Storage; -use crate::system::permissions::options::CanIDo; -use crate::system::user::UserModel; + use hosted::HostedMavenRepository; use proxy::ProxyMavenRepository; use staging::StagingRepository; diff --git a/backend/src/repository/maven/models.rs b/backend/src/repository/maven/models.rs index 5b3636eb..43a5a042 100644 --- a/backend/src/repository/maven/models.rs +++ b/backend/src/repository/maven/models.rs @@ -1,9 +1,5 @@ -use crate::repository::maven::staging::{DeployRequirement, StageSettings}; use serde::{Deserialize, Serialize}; -use crate::repository::settings::RepositoryConfigType; -use crate::utils::get_current_time; - #[derive(Debug, Serialize, Deserialize, Clone)] pub struct DeployMetadata { #[serde(rename = "groupId")] diff --git a/backend/src/repository/maven/proxy.rs b/backend/src/repository/maven/proxy.rs index b2ad4f31..e0565a9c 100644 --- a/backend/src/repository/maven/proxy.rs +++ b/backend/src/repository/maven/proxy.rs @@ -9,29 +9,39 @@ use crate::storage::models::Storage; use crate::system::permissions::options::CanIDo; use crate::system::user::UserModel; use actix_web::http::header::HeaderMap; -use actix_web::http::StatusCode; + use actix_web::web::Bytes; use actix_web::{Error, HttpResponse}; use async_trait::async_trait; -use bytes::{BufMut, BytesMut}; + use futures::channel::mpsc::unbounded; use futures_util::stream::StreamExt; use futures_util::SinkExt; use sea_orm::DatabaseConnection; -use std::sync::{Arc, Weak}; -use tokio::io::{duplex, AsyncWriteExt}; -use tokio::sync::RwLockReadGuard; +use std::sync::Arc; +#[derive(Debug)] pub struct ProxyMavenRepository { pub config: RepositoryConfig, pub proxy: Vec, pub storage: Arc, } +impl Clone for ProxyMavenRepository { + fn clone(&self) -> Self { + ProxyMavenRepository { + config: self.config.clone(), + storage: self.storage.clone(), + proxy: self.proxy.clone(), + } + } +} #[async_trait] impl Repository for ProxyMavenRepository { fn get_repository(&self) -> &RepositoryConfig { &self.config } - + fn get_mut_config(&mut self) -> &mut RepositoryConfig { + &mut self.config + } fn get_storage(&self) -> &S { self.storage.as_ref() } @@ -39,7 +49,7 @@ impl Repository for ProxyMavenRepository { async fn handle_get( &self, path: &str, - http: &HeaderMap, + _http: &HeaderMap, conn: &DatabaseConnection, authentication: Authentication, ) -> Result { @@ -56,7 +66,7 @@ impl Repository for ProxyMavenRepository { .await .map_err(InternalError::from)? { - StorageFileResponse::List(list) => { + StorageFileResponse::List(_list) => { /* let files = self.process_storage_files(list, path).await?; Ok(RepoResponse::try_from((files, StatusCode::OK))?)*/ panic!("Not implemented") @@ -69,13 +79,13 @@ impl Repository for ProxyMavenRepository { .unwrap(); for proxy in &self.proxy { let url = format!("{}/{}", proxy.proxy_url, path); - let mut response = builder.get(&url).send().await; - if let Ok(mut response) = response { + let response = builder.get(&url).send().await; + if let Ok(response) = response { if response.status().is_success() { let mut stream = response.bytes_stream(); - let (mut server, mut client) = + let (mut server, client) = unbounded::>(); - let (mut file_server, mut file_client) = unbounded::(); + let (mut file_server, file_client) = unbounded::(); actix_web::rt::spawn(async move { while let Some(chunk) = stream.next().await { if let Ok(chunk) = chunk { diff --git a/backend/src/repository/maven/staging.rs b/backend/src/repository/maven/staging.rs index 404e5e0e..7d609b1f 100644 --- a/backend/src/repository/maven/staging.rs +++ b/backend/src/repository/maven/staging.rs @@ -2,11 +2,11 @@ use crate::authentication::Authentication; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; use crate::repository::handler::Repository; -use crate::repository::maven::models::Pom; + use crate::repository::maven::settings::{MavenSettings, MavenType, ProxySettings}; use crate::repository::response::RepoResponse; use crate::repository::settings::{Policy, RepositoryConfig, Visibility}; -use crate::repository::staging::{ProcessingStage, ProjectsToStage, StageHandler}; +use crate::repository::staging::{ProcessingStage, StageHandler}; use crate::storage::file::StorageFileResponse; use crate::storage::models::Storage; use crate::storage::multi::MultiStorageController; @@ -18,17 +18,17 @@ use actix_web::http::StatusCode; use actix_web::web::Bytes; use actix_web::{Error, HttpResponse}; use async_trait::async_trait; -use bytes::{BufMut, BytesMut}; -use futures::channel::mpsc::unbounded; + + use futures_util::stream::StreamExt; use futures_util::SinkExt; use sea_orm::DatabaseConnection; use serde::{Deserialize, Serialize}; -use std::ops::Deref; -use std::path::PathBuf; -use std::sync::{Arc, Weak}; -use tokio::io::{duplex, AsyncWriteExt}; -use tokio::sync::RwLockReadGuard; + + +use std::sync::{Arc}; + + #[derive(Debug, Serialize, Deserialize, Clone)] pub enum StageSettings { @@ -51,6 +51,7 @@ pub enum StageSettings { } #[derive(Debug, Serialize, Deserialize, Clone)] pub enum DeployRequirement {} +#[derive(Debug)] pub struct StagingRepository { pub config: RepositoryConfig, pub storage: Arc, @@ -95,19 +96,34 @@ impl<'a, S: Storage> StagingRepository { impl<'a, S: Storage> StageHandler for StagingRepository { async fn push( &self, - directory: String, - process: ProcessingStage, - storages: Arc>, + _directory: String, + _process: ProcessingStage, + _storages: Arc>, ) -> Result<(), InternalError> { todo!() } } + +impl Clone for StagingRepository { + fn clone(&self) -> Self { + StagingRepository { + config: self.config.clone(), + storage: self.storage.clone(), + stage_to: self.stage_to.clone(), + parent: self.parent.clone(), + deploy_requirement: self.deploy_requirement.clone(), + } + } +} + #[async_trait] impl Repository for StagingRepository { fn get_repository(&self) -> &RepositoryConfig { &self.config } - + fn get_mut_config(&mut self) -> &mut RepositoryConfig { + &mut self.config + } fn get_storage(&self) -> &S { self.storage.as_ref() } @@ -115,7 +131,7 @@ impl Repository for StagingRepository { async fn handle_get( &self, path: &str, - http: &HeaderMap, + _http: &HeaderMap, conn: &DatabaseConnection, authentication: Authentication, ) -> Result { @@ -132,7 +148,7 @@ impl Repository for StagingRepository { .await .map_err(InternalError::from)? { - StorageFileResponse::List(list) => { + StorageFileResponse::List(_list) => { /* let files = self.process_storage_files(list, path).await?; Ok(RepoResponse::try_from((files, StatusCode::OK))?)*/ @@ -145,10 +161,10 @@ impl Repository for StagingRepository { .build() .unwrap(); let url = format!("{}/{}", self.parent.proxy_url, path); - let mut response = builder.get(&url).send().await; - if let Ok(mut response) = response { + let response = builder.get(&url).send().await; + if let Ok(response) = response { if response.status().is_success() { - let mut stream = response.bytes_stream(); + let stream = response.bytes_stream(); return Ok(RepoResponse::HttpResponse( HttpResponse::Ok().streaming(stream), )); diff --git a/backend/src/repository/nitro/dynamic.rs b/backend/src/repository/nitro/dynamic.rs index 914d5c12..fdbc9ded 100644 --- a/backend/src/repository/nitro/dynamic.rs +++ b/backend/src/repository/nitro/dynamic.rs @@ -19,7 +19,7 @@ macro_rules! nitro_repo_handler { async fn get_versions( &self, - project: &str, + _project: &str, ) -> Result, InternalError> { match self { $($v::$name(handler) => handler.get_versions(project).await,)* @@ -30,8 +30,8 @@ macro_rules! nitro_repo_handler { async fn get_project_specific_version( &self, - project: &str, - version: &str, + _project: &str, + _version: &str, ) -> Result, InternalError> { match self { $($v::$name(handler) => handler.get_project_specific_version(project, version).await,)* @@ -40,7 +40,7 @@ macro_rules! nitro_repo_handler { } async fn get_project_latest( &self, - project: &str, + _project: &str, ) -> Result, InternalError> { match self { $($v::$name(handler) => handler.get_project_latest(project).await,)* @@ -48,7 +48,7 @@ macro_rules! nitro_repo_handler { } } - async fn latest_version(&self, project: &str) -> Result, InternalError> { + async fn latest_version(&self, _project: &str) -> Result, InternalError> { match self { $($v::$name(handler) => handler.latest_version(project).await,)* _ => unsafe{ std::hint::unreachable_unchecked() }, @@ -57,8 +57,8 @@ macro_rules! nitro_repo_handler { } async fn process_storage_files( &self, - directory: crate::storage::file::StorageDirectoryResponse, - requested_dir: &str, + _directory: crate::storage::file::StorageDirectoryResponse, + _requested_dir: &str, ) -> Result { match self { $($v::$name(handler) => handler.process_storage_files(directory, requested_dir).await,)* @@ -68,10 +68,10 @@ macro_rules! nitro_repo_handler { } async fn post_deploy( &self, - project_folder: String, - version_folder: String, - model: crate::system::user::database::Model, - version_data: crate::repository::nitro::VersionData, + _project_folder: String, + _version_folder: String, + _model: crate::system::user::database::Model, + _version_data: crate::repository::nitro::VersionData, ) -> Result<(), InternalError> { match self { $($v::$name(handler) => handler.post_deploy(project_folder, version_folder, model, version_data).await,)* diff --git a/backend/src/repository/nitro/nitro_repository.rs b/backend/src/repository/nitro/nitro_repository.rs index e9a636ca..c31e0844 100644 --- a/backend/src/repository/nitro/nitro_repository.rs +++ b/backend/src/repository/nitro/nitro_repository.rs @@ -12,7 +12,7 @@ use crate::repository::nitro::{ VersionData, }; use crate::repository::response::Project; -use crate::repository::settings::RepositoryConfig; + use crate::storage::file::StorageDirectoryResponse; use crate::storage::models::Storage; use crate::system::user::UserModel; diff --git a/backend/src/repository/npm/mod.rs b/backend/src/repository/npm/mod.rs index 665d3b14..ee5fa37a 100644 --- a/backend/src/repository/npm/mod.rs +++ b/backend/src/repository/npm/mod.rs @@ -6,16 +6,15 @@ use actix_web::http::header::HeaderMap; use actix_web::http::StatusCode; use actix_web::web::Bytes; use async_trait::async_trait; -use log::{debug, error, trace}; +use log::{debug, trace}; use regex::Regex; use sea_orm::DatabaseConnection; -use tokio::sync::RwLockReadGuard; use crate::authentication::{verify_login, Authentication}; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; use crate::repository::handler::Repository; -use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; + use crate::repository::npm::models::{Attachment, LoginRequest, LoginResponse, PublishRequest}; use crate::repository::npm::utils::generate_get_response; use crate::repository::response::RepoResponse; @@ -28,12 +27,19 @@ use crate::system::user::UserModel; pub mod error; pub mod models; mod utils; - +#[derive(Debug)] pub struct NPMHandler { config: RepositoryConfig, storage: Arc, } - +impl Clone for NPMHandler { + fn clone(&self) -> Self { + NPMHandler { + config: self.config.clone(), + storage: self.storage.clone(), + } + } +} impl NPMHandler { pub async fn create( repository: RepositoryConfig, @@ -55,7 +61,9 @@ impl Repository for NPMHandler { fn get_repository(&self) -> &RepositoryConfig { &self.config } - + fn get_mut_config(&mut self) -> &mut RepositoryConfig { + &mut self.config + } fn get_storage(&self) -> &StorageType { &self.storage } @@ -108,7 +116,7 @@ impl Repository for NPMHandler { .await .map_err(InternalError::from)? { - StorageFileResponse::List(list) => { + StorageFileResponse::List(_list) => { /* let files = self.process_storage_files(list, path).await?; Ok(RepoResponse::try_from((files, StatusCode::OK))?)*/ @@ -205,12 +213,12 @@ impl Repository for NPMHandler { }; let project_folder = publish_request.name.clone(); - let version_folder = + let _version_folder = format!("{}/{}", &project_folder, &version_data.version); trace!("Project Folder Location {}", project_folder); - let version_for_saving = version_data.clone(); - let user = caller.clone(); + let _version_for_saving = version_data.clone(); + let _user = caller.clone(); /* if let Err(error) = self .post_deploy( project_folder, diff --git a/backend/src/repository/raw/mod.rs b/backend/src/repository/raw/mod.rs index db6f2336..f8429516 100644 --- a/backend/src/repository/raw/mod.rs +++ b/backend/src/repository/raw/mod.rs @@ -4,8 +4,7 @@ use crate::repository::settings::RepositoryConfig; use crate::storage::models::Storage; use async_trait::async_trait; use std::sync::Arc; -use tokio::sync::RwLockReadGuard; - +#[derive(Debug)] pub struct RawHandler { config: RepositoryConfig, storage: Arc, @@ -18,13 +17,22 @@ impl RawHandler { Ok(RawHandler { config, storage }) } } - +impl Clone for RawHandler { + fn clone(&self) -> Self { + RawHandler { + config: self.config.clone(), + storage: self.storage.clone(), + } + } +} #[async_trait] impl Repository for RawHandler { fn get_repository(&self) -> &RepositoryConfig { &self.config } - + fn get_mut_config(&mut self) -> &mut RepositoryConfig { + &mut self.config + } fn get_storage(&self) -> &StorageType { &self.storage } diff --git a/backend/src/repository/settings/mod.rs b/backend/src/repository/settings/mod.rs index 057372b4..ac7a5a39 100644 --- a/backend/src/repository/settings/mod.rs +++ b/backend/src/repository/settings/mod.rs @@ -92,8 +92,8 @@ impl RepositoryConfig { /// This will overwrite the config file. pub async fn save_config( &self, - storage: &StorageType, - config: Option<&Config>, + _storage: &StorageType, + _config: Option<&Config>, ) -> Result<(), InternalError> { panic!("To be replaced"); } diff --git a/backend/src/repository/staging/dynamic.rs b/backend/src/repository/staging/dynamic.rs index 852d83bc..38f2a25e 100644 --- a/backend/src/repository/staging/dynamic.rs +++ b/backend/src/repository/staging/dynamic.rs @@ -1,12 +1,11 @@ use super::super::maven::staging::StagingRepository; use super::{ProcessingStage, StageHandler}; use crate::error::internal_error::InternalError; -use crate::repository::settings::{RepositoryConfig, RepositoryType}; +use crate::repository::settings::RepositoryConfig; use crate::storage::models::Storage; use crate::storage::multi::MultiStorageController; use crate::storage::DynamicStorage; use std::sync::Arc; -use tokio::sync::RwLockReadGuard; macro_rules! gen_dynamic_stage { ($($name: ident, $ty:tt),*) => { @@ -18,8 +17,8 @@ macro_rules! gen_dynamic_stage { } #[inline] pub async fn get_stage_handler( - storage: Arc, - repository_config: RepositoryConfig, + _storage: Arc, + _repository_config: RepositoryConfig, ) -> Result, InternalError> { panic!("Not implemented"); } diff --git a/backend/src/repository/staging/mod.rs b/backend/src/repository/staging/mod.rs index d06a46f4..31f6ed7b 100644 --- a/backend/src/repository/staging/mod.rs +++ b/backend/src/repository/staging/mod.rs @@ -1,16 +1,15 @@ pub mod dynamic; use crate::error::internal_error::InternalError; -use crate::repository::response::RepoResponse; + use crate::repository::settings::RepositoryConfigType; use crate::storage::models::Storage; use crate::storage::multi::MultiStorageController; use crate::storage::DynamicStorage; use async_trait::async_trait; use serde::{Deserialize, Serialize}; -use serde_json::Value; -use std::path::PathBuf; -use std::sync::{Arc, Weak}; + +use std::sync::Arc; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct ProcessingStage { diff --git a/backend/src/repository/web/mod.rs b/backend/src/repository/web/mod.rs index b0f742f2..4077c517 100644 --- a/backend/src/repository/web/mod.rs +++ b/backend/src/repository/web/mod.rs @@ -17,7 +17,7 @@ pub struct RepositoryResponse<'a> { impl<'a> RepositoryResponse<'a> { pub async fn new( - config: &'a RepositoryConfig, + _config: &'a RepositoryConfig, ) -> Result, InternalError> { todo!("create big boi") } diff --git a/backend/src/repository/web/multi/admin.rs b/backend/src/repository/web/multi/admin.rs index 95b19c32..2abf0554 100644 --- a/backend/src/repository/web/multi/admin.rs +++ b/backend/src/repository/web/multi/admin.rs @@ -1,21 +1,23 @@ -use std::ops::Deref; -use actix_web::http::StatusCode; +use std::sync::Arc; + + use actix_web::{delete, get, post, web, HttpResponse}; +use lockfree::map::Removed; use sea_orm::DatabaseConnection; use serde::Deserialize; use crate::authentication::Authentication; -use crate::error::api_error::APIError; + use crate::error::internal_error::InternalError; -use crate::repository::handler::Repository; -use crate::repository::maven::settings::MavenSettings; -use crate::repository::settings::{Policy, RepositoryConfig, Visibility}; -use crate::repository::web::RepositoryResponse; +use crate::repository::handler::{Repository}; + +use crate::repository::settings::{Policy, Visibility}; + use crate::repository::RepositoryType; -use crate::storage::error::StorageError; + use crate::storage::models::Storage; use crate::storage::multi::MultiStorageController; use crate::storage::DynamicStorage; @@ -23,7 +25,7 @@ use crate::system::permissions::options::CanIDo; use crate::system::user::UserModel; use paste::paste; use serde_json::Value; -use tokio::sync::RwLockReadGuard; + /// Get all repositories from the storage #[get("/repositories/{storage_name}")] @@ -48,13 +50,13 @@ pub async fn create_repository( database: web::Data, auth: Authentication, query_params: web::Path<(String, String, RepositoryType)>, - inner_config: web::Json>, + _inner_config: web::Json>, ) -> actix_web::Result { let user: UserModel = auth.get_user(&database).await??; user.can_i_edit_repos()?; - let (storage_name, repository_name, repository_type) = query_params.into_inner(); + let (storage_name, _repository_name, _repository_type) = query_params.into_inner(); - let storage = crate::helpers::get_storage!(storage_handler, storage_name); + let _storage = crate::helpers::get_storage!(storage_handler, storage_name); todo!("Create Repository"); } @@ -72,7 +74,7 @@ pub async fn get_repository( database: web::Data, auth: Authentication, path_params: web::Path<(String, String)>, - query_params: web::Query, + _query_params: web::Query, ) -> actix_web::Result { let user: UserModel = auth.get_user(&database).await??; user.can_i_edit_repos()?; @@ -101,13 +103,14 @@ pub async fn delete_repository( user.can_i_edit_repos()?; let (storage_name, repository_name) = path_params.into_inner(); let storage = crate::helpers::get_storage!(storage_handler, storage_name); - let repository = crate::helpers::get_repository!(storage, repository_name); + let _repository = crate::helpers::get_repository!(storage, repository_name); storage .delete_repository(repository_name, query_params.purge_repository) .await .map_err(InternalError::from)?; Ok(HttpResponse::NoContent().finish()) } + macro_rules! update_repository_core_prop { ($($name:ident,$value_type:tt),*) => { $( @@ -122,15 +125,9 @@ macro_rules! update_repository_core_prop { user.can_i_edit_repos()?; let (storage_name, repository_name, value) = path_params.into_inner(); let storage = crate::helpers::get_storage!(storage_handler, storage_name); - let mut repository = crate::helpers::get_repository!(storage, repository_name) - .deref() - .clone(); - repository.$name = value; - - storage - .update_repository(repository) - .await - .map_err(InternalError::from)?; + let (name, mut repository) = crate::helpers::take_repository!(storage, repository_name); + repository.get_mut_config().$name = value; + storage.add_repository_for_updating(name, repository).expect("Failed to add repository for updating"); Ok(HttpResponse::NoContent().finish()) } @@ -146,4 +143,4 @@ macro_rules! update_repository_core_prop { } }; } -//update_repository_core_prop!(visibility, Visibility, active, bool, policy, Policy); +update_repository_core_prop!(visibility, Visibility, active, bool, policy, Policy); diff --git a/backend/src/repository/web/multi/configs.rs b/backend/src/repository/web/multi/configs.rs index 0392889c..496ebcbe 100644 --- a/backend/src/repository/web/multi/configs.rs +++ b/backend/src/repository/web/multi/configs.rs @@ -100,7 +100,7 @@ macro_rules! define_repository_config_handlers_group { }; } -pub(crate) use define_repository_config_delete; -pub(crate) use define_repository_config_get; -pub(crate) use define_repository_config_handlers_group; -pub(crate) use define_repository_config_set; + + + + diff --git a/backend/src/repository/web/multi/mod.rs b/backend/src/repository/web/multi/mod.rs index 35b0925a..910fef32 100644 --- a/backend/src/repository/web/multi/mod.rs +++ b/backend/src/repository/web/multi/mod.rs @@ -28,14 +28,11 @@ pub fn init_admin(cfg: &mut web::ServiceConfig) { .service(admin::get_repositories) .service(admin::create_repository) .service(admin::delete_repository); - //cfg.configure(admin::register_core_updates); + cfg.configure(admin::register_core_updates); } pub mod configs_impls { - use super::configs::define_repository_config_handlers_group; - use crate::repository::settings::badge::BadgeSettings; - use crate::repository::settings::frontend::Frontend; - use crate::repository::settings::repository_page::RepositoryPage; + // define_repository_config_handlers_group!( // "badge", // BadgeSettings, diff --git a/backend/src/repository/web/multi/public/project.rs b/backend/src/repository/web/multi/public/project.rs index 65d38661..7664165b 100644 --- a/backend/src/repository/web/multi/public/project.rs +++ b/backend/src/repository/web/multi/public/project.rs @@ -1,25 +1,20 @@ -use actix_web::{get, web, HttpResponse}; -use comrak::Arena; -use log::warn; +use actix_web::{web, HttpResponse}; + use sea_orm::DatabaseConnection; -use serde::{Deserialize, Serialize}; -use std::ops::Deref; use crate::authentication::Authentication; -use crate::error::internal_error::InternalError; + use crate::repository::handler::Repository; -use crate::repository::settings::repository_page::{PageType, RepositoryPage}; -use crate::repository::settings::{RepositoryConfig, Visibility}; +use crate::repository::settings::Visibility; use crate::storage::models::Storage; use crate::storage::multi::MultiStorageController; use crate::storage::DynamicStorage; -use crate::system::permissions::options::{CanIDo, MissingPermission}; +use crate::system::permissions::options::CanIDo; use crate::system::user::UserModel; use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; -use crate::repository::nitro::{ProjectRequest, VersionData}; -use crate::repository::settings::RepositoryType; +use crate::repository::nitro::ProjectRequest; pub async fn get_project( storage_handler: web::Data>, @@ -51,7 +46,7 @@ pub async fn get_project( repository.get_project_latest(project.as_str()).await? }; if let Some(value) = value { - return Ok(HttpResponse::Ok().json(value)); + Ok(HttpResponse::Ok().json(value)) } else { Ok(HttpResponse::NotFound().finish()) } diff --git a/backend/src/repository/web/multi/public/repositories.rs b/backend/src/repository/web/multi/public/repositories.rs index 3bfed6f5..a18081ab 100644 --- a/backend/src/repository/web/multi/public/repositories.rs +++ b/backend/src/repository/web/multi/public/repositories.rs @@ -3,18 +3,17 @@ use comrak::Arena; use log::warn; use sea_orm::DatabaseConnection; use serde::{Deserialize, Serialize}; -use std::ops::Deref; use crate::authentication::Authentication; -use crate::error::internal_error::InternalError; + use crate::repository::handler::Repository; use crate::repository::settings::repository_page::{PageType, RepositoryPage}; -use crate::repository::settings::{RepositoryConfig, RepositoryType, Visibility}; +use crate::repository::settings::{RepositoryType, Visibility}; use crate::storage::models::Storage; use crate::storage::multi::MultiStorageController; use crate::storage::DynamicStorage; -use crate::system::permissions::options::{CanIDo, MissingPermission}; +use crate::system::permissions::options::CanIDo; use crate::system::user::UserModel; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct PublicRepositoryResponse { @@ -39,21 +38,15 @@ pub async fn get_repositories( .into_iter() .filter(|repo| { if !repo.visibility.eq(&Visibility::Public) { - match CanIDo::can_read_from(&caller, &repo) { - Ok(ok) => { - if ok.is_none() { - return true; - } else { - return false; - } - } + match CanIDo::can_read_from(&caller, repo) { + Ok(ok) => ok.is_none(), Err(error) => { warn!("{}", error); - return false; + false } } } else { - return true; + true } }) .map(|repo| PublicRepositoryResponse { diff --git a/backend/src/repository/web/multi/repository_handler.rs b/backend/src/repository/web/multi/repository_handler.rs index b4797068..6f3ef590 100644 --- a/backend/src/repository/web/multi/repository_handler.rs +++ b/backend/src/repository/web/multi/repository_handler.rs @@ -2,10 +2,8 @@ use actix_web::web::Bytes; use actix_web::{web, HttpRequest}; use sea_orm::DatabaseConnection; use serde::Deserialize; -use std::ops::Deref; use crate::authentication::Authentication; -use crate::error::api_error::APIError; use crate::repository::handler::Repository; use crate::repository::response::RepoResponse; diff --git a/backend/src/storage/bad_storage.rs b/backend/src/storage/bad_storage.rs index 8a2d8aef..91f36ed1 100644 --- a/backend/src/storage/bad_storage.rs +++ b/backend/src/storage/bad_storage.rs @@ -1,15 +1,5 @@ -use async_trait::async_trait; -use bytes::Bytes; -use futures::Stream; -use log::warn; -use serde::de::DeserializeOwned; -use serde::Serialize; -use serde_json::Value; -use tokio::sync::RwLockReadGuard; - -use crate::repository::settings::{RepositoryConfig, RepositoryType}; use crate::storage::error::StorageError; -use crate::storage::file::{StorageFile, StorageFileResponse}; + use crate::storage::models::StorageStatus; use crate::storage::StorageSaver; diff --git a/backend/src/storage/local_storage/mod.rs b/backend/src/storage/local_storage/mod.rs index 6a3d8f29..eadabbf9 100644 --- a/backend/src/storage/local_storage/mod.rs +++ b/backend/src/storage/local_storage/mod.rs @@ -8,24 +8,23 @@ use async_trait::async_trait; use bytes::Bytes; use futures::Stream; use lockfree::map::{Map, Removed}; -use log::{debug, trace, warn}; +use log::{debug, trace}; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; -use serde_json::Value; -use tokio::fs::{create_dir_all, read_to_string, remove_dir, remove_file, OpenOptions}; + +use tokio::fs::{create_dir_all, read_to_string, remove_file, OpenOptions}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; -use tokio::sync::{RwLock, RwLockReadGuard}; + use tokio_stream::StreamExt; -use crate::repository::settings::{RepositoryConfig, RepositoryType}; -use crate::repository::REPOSITORY_CONF_FOLDER; +use crate::repository::settings::RepositoryConfig; + use crate::storage::error::StorageError; -use crate::storage::error::StorageError::RepositoryMissing; + use crate::storage::file::{StorageDirectoryResponse, StorageFile, StorageFileResponse}; use crate::storage::models::{Storage, StorageStatus}; use crate::storage::{DynamicStorage, StorageConfig, StorageSaver, STORAGE_CONFIG}; -use crate::utils::get_current_time; #[derive(Debug)] pub struct LocalStorage { @@ -101,7 +100,7 @@ impl LocalStorage { impl Storage for LocalStorage { type Repository = DynamicRepositoryHandler; - async fn create_new(config: StorageSaver) -> Result + async fn create_new(_config: StorageSaver) -> Result where Self: Sized, { @@ -117,7 +116,7 @@ impl Storage for LocalStorage { } else { unsafe { unreachable_unchecked() } }; - let mut storage = LocalStorage { + let storage = LocalStorage { config: v, storage_config: config, status: StorageStatus::Unloaded, @@ -156,15 +155,15 @@ impl Storage for LocalStorage { async fn create_repository + Send>( &self, - repository: R, + _repository: R, ) -> Result<(), StorageError> { todo!() } async fn delete_repository + Send>( &self, - repository: S, - delete_files: bool, + _repository: S, + _delete_files: bool, ) -> Result<(), StorageError> { todo!() } @@ -177,28 +176,27 @@ impl Storage for LocalStorage { &self, repository: S, ) -> Result>, StorageError> { - todo!() + let option = self + .repositories + .get(repository.as_ref()) + .and_then(|v| Some(v.val().clone())); + Ok(option) } fn remove_repository_for_updating>( &self, repository: S, - ) -> Result>, StorageError> { - todo!() + ) -> Option>> { + self.repositories.remove(repository.as_ref()) } - async fn add_repository_for_updating( + fn add_repository_for_updating( &self, + name: String, repository_arc: Self::Repository, ) -> Result<(), StorageError> { - todo!() - } - - async fn add_repository_for_updating_removed( - &self, - repository_arc: Removed>, - ) -> Result<(), StorageError> { - todo!() + self.repositories.insert(name, Arc::new(repository_arc)); + Ok(()) } async fn save_file( @@ -230,14 +228,14 @@ impl Storage for LocalStorage { fn write_file_stream + Unpin + Send + Sync + 'static>( &self, repository: &RepositoryConfig, - mut s: S, + s: S, location: &str, ) -> Result { let file_location = self.get_repository_folder(&repository.name).join(location); trace!("Saving File {:?}", &file_location); std::fs::create_dir_all(file_location.parent().ok_or(StorageError::ParentIssue)?)?; - let exists = if file_location.exists() { true } else { false }; + let exists = file_location.exists(); let existss = exists; tokio::spawn(async move { let mut s = s; diff --git a/backend/src/storage/mod.rs b/backend/src/storage/mod.rs index 92b9544e..cf8f0711 100644 --- a/backend/src/storage/mod.rs +++ b/backend/src/storage/mod.rs @@ -4,14 +4,13 @@ use futures::Stream; use lockfree::map::Removed; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; -use serde_json::Value; + use std::sync::Arc; -use tokio::sync::RwLockReadGuard; -use crate::repository::settings::{RepositoryConfig, RepositoryType}; +use crate::repository::settings::RepositoryConfig; use crate::storage::error::StorageError; use crate::storage::file::{StorageFile, StorageFileResponse}; -use crate::storage::models::{Storage, StorageStatus}; +use crate::storage::models::Storage; pub mod bad_storage; pub mod error; @@ -48,7 +47,7 @@ impl Storage for DynamicStorage{ async fn create_new(config: StorageSaver) -> Result where Self: Sized { match config.storage_type.clone() { $(StorageType::$name => { - let factory = config.clone(); + let _factory = config.clone(); $ty::create_new(config).await.map(|storage| DynamicStorage::$name(storage)) })* } @@ -57,7 +56,7 @@ impl Storage for DynamicStorage{ async fn new(config: StorageSaver) -> Result where Self: Sized { match config.storage_type.clone() { $(StorageType::$name => { - let factory = config.clone(); + let _factory = config.clone(); $ty::new(config).await.map(|storage| DynamicStorage::$name(storage)) })* } @@ -91,55 +90,87 @@ impl Storage for DynamicStorage{ } async fn create_repository + Send>(&self, repository: R) -> Result<(), StorageError> { - todo!() + match self { + $(DynamicStorage::$name(storage) => storage.create_repository(repository).await,)* + _ => unsafe{ unreachable_unchecked() } + } } async fn delete_repository + Send>(&self, repository: S, delete_files: bool) -> Result<(), StorageError> { - todo!() + match self { + $(DynamicStorage::$name(storage) => storage.delete_repository(repository,delete_files).await,)* + _ => unsafe{ unreachable_unchecked() } + } } fn get_repository_list(&self) -> Result, StorageError> { - todo!() + match self { + $(DynamicStorage::$name(storage) => storage.get_repository_list(),)* + _ => unsafe{ unreachable_unchecked() } + } } fn get_repository>(&self, repository: S) -> Result>, StorageError> { - todo!() - } - - fn remove_repository_for_updating>(&self, repository: S) -> Result>, StorageError> { - todo!() + match self { + $(DynamicStorage::$name(storage) => storage.get_repository(repository),)* + _ => unsafe{ unreachable_unchecked() } + } } - async fn add_repository_for_updating(&self, repository_arc: Self::Repository) -> Result<(), StorageError> { - todo!() + fn remove_repository_for_updating>(&self, repository: S) -> Option>> { + match self { + $(DynamicStorage::$name(storage) => storage.remove_repository_for_updating(repository),)* + _ => unsafe{ unreachable_unchecked() } + } } - async fn add_repository_for_updating_removed(&self, repository_arc: Removed>) -> Result<(), StorageError> { - todo!() + fn add_repository_for_updating(&self,name: String, repository_arc: Self::Repository) -> Result<(), StorageError> { + match self { + $(DynamicStorage::$name(storage) => storage.add_repository_for_updating(name, repository_arc),)* + _ => unsafe{ unreachable_unchecked() } + } } async fn save_file(&self, repository: &RepositoryConfig, file: &[u8], location: &str) -> Result { - todo!() + match self { + $(DynamicStorage::$name(storage) => storage.save_file(repository,file,location).await,)* + _ => unsafe{ unreachable_unchecked() } + } } fn write_file_stream + Unpin + Send + Sync + 'static>(&self, repository: &RepositoryConfig, s: S, location: &str) -> Result { - todo!() + match self { + $(DynamicStorage::$name(storage) => storage.write_file_stream(repository,s,location),)* + _ => unsafe{ unreachable_unchecked() } + } } async fn delete_file(&self, repository: &RepositoryConfig, location: &str) -> Result<(), StorageError> { - todo!() + match self { + $(DynamicStorage::$name(storage) => storage.delete_file(repository,location).await,)* + _ => unsafe{ unreachable_unchecked() } + } } async fn get_file_as_response(&self, repository: &RepositoryConfig, location: &str) -> Result { - todo!() + match self { + $(DynamicStorage::$name(storage) => storage.get_file_as_response(repository,location).await,)* + _ => unsafe{ unreachable_unchecked() } + } } async fn get_file_information(&self, repository: &RepositoryConfig, location: &str) -> Result, StorageError> { - todo!() + match self { + $(DynamicStorage::$name(storage) => storage.get_file_information(repository,location).await,)* + _ => unsafe{ unreachable_unchecked() } + } } async fn get_file(&self, repository: &RepositoryConfig, location: &str) -> Result>, StorageError> { - todo!() + match self { + $(DynamicStorage::$name(storage) => storage.get_file(repository,location).await,)* + _ => unsafe{ unreachable_unchecked() } + } } async fn get_repository_config( &self, diff --git a/backend/src/storage/models.rs b/backend/src/storage/models.rs index 0b922ec0..2e739220 100644 --- a/backend/src/storage/models.rs +++ b/backend/src/storage/models.rs @@ -7,17 +7,15 @@ use async_trait::async_trait; use bytes::Bytes; use lockfree::map::Removed; use serde::de::DeserializeOwned; -use serde::{Deserialize, Serialize}; -use serde_json::Value; -use tokio::sync::RwLockReadGuard; + use tokio_stream::Stream; -use crate::repository::settings::{RepositoryConfig, RepositoryType}; +use crate::repository::settings::RepositoryConfig; use crate::storage::error::StorageError; use crate::storage::file::{StorageFile, StorageFileResponse}; -use crate::storage::local_storage::LocalStorage; + use crate::storage::DynamicStorage; -use crate::storage::{StorageConfig, StorageSaver}; +use crate::storage::StorageSaver; pub static STORAGE_FILE: &str = "storages.json"; pub static STORAGE_FILE_BAK: &str = "storages.json.bak"; @@ -106,16 +104,13 @@ pub trait Storage: Send + Sync { fn remove_repository_for_updating>( &self, repository: S, - ) -> Result>, StorageError>; + ) -> Option>>; /// Will update all configs for the Repository - async fn add_repository_for_updating( + fn add_repository_for_updating( &self, + name: String, repository_arc: Self::Repository, ) -> Result<(), StorageError>; - async fn add_repository_for_updating_removed( - &self, - repository_arc: Removed>, - ) -> Result<(), StorageError>; /// Saves a File to a location /// Will overwrite any data found async fn save_file( diff --git a/backend/src/storage/multi/mod.rs b/backend/src/storage/multi/mod.rs index 0006a5d2..dc7c75de 100644 --- a/backend/src/storage/multi/mod.rs +++ b/backend/src/storage/multi/mod.rs @@ -1,5 +1,5 @@ use lockfree::map::Map; -use std::collections::HashMap; + use std::mem; use std::path::{Path, PathBuf}; use std::sync::Arc; @@ -9,7 +9,6 @@ use log::{error, info}; use tokio::fs; use tokio::fs::{read_to_string, OpenOptions}; use tokio::io::AsyncWriteExt; -use tokio::sync::{RwLock, RwLockReadGuard}; use crate::storage::bad_storage::BadStorage; use crate::storage::error::StorageError; @@ -28,7 +27,7 @@ async fn load_storages( } let string = read_to_string(&storages_file).await?; let result: Vec = serde_json::from_str(&string)?; - let mut values: Map> = Map::new(); + let values: Map> = Map::new(); for factory in result { let name = factory.generic_config.id.clone(); let storage = match DynamicStorage::new(factory).await { @@ -96,7 +95,7 @@ impl MultiStorageController { /// Attempts to run the storage load on any storages that are unloaded. /// This will include the Error storages pub async fn load_unloaded_storages<'a>(&mut self) -> Result<(), StorageError> { - let mut unloaded = mem::take(&mut self.unloaded_storages); + let unloaded = mem::take(&mut self.unloaded_storages); for (name, storage) in unloaded.into_iter() { match storage.get_repos_to_load().await { Ok(repositories) => { @@ -105,7 +104,7 @@ impl MultiStorageController { let handler = DynamicRepositoryHandler::new_dyn_storage(storage.clone(), repository) .await - .map_err(|error| { + .map_err(|_error| { error!("Error loading repository {}", name); }); if let Ok(handler) = handler { @@ -122,11 +121,11 @@ impl MultiStorageController { Ok(()) } - pub async fn create_storage<'a>(&self, storage: StorageSaver) -> Result<(), StorageError> { + pub async fn create_storage<'a>(&self, _storage: StorageSaver) -> Result<(), StorageError> { todo!() } - pub async fn delete_storage(&self, storage: &str) -> Result { + pub async fn delete_storage(&self, _storage: &str) -> Result { todo!() } pub async fn storage_savers(&self) -> Vec { From a38dbb8abbf7da561d3f1664e04fa9a1848149ba Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Thu, 21 Jul 2022 19:08:51 -0400 Subject: [PATCH 43/76] Setting Handlers --- backend/src/repository/handler.rs | 93 +++++++++++++++++++++--- backend/src/repository/maven/hosted.rs | 38 +++++++++- backend/src/repository/maven/mod.rs | 73 ++++++++++++------- backend/src/repository/maven/proxy.rs | 44 ++++++++++- backend/src/repository/maven/settings.rs | 34 +++------ backend/src/repository/maven/staging.rs | 67 ++++++----------- backend/src/repository/nitro/dynamic.rs | 24 +++--- backend/src/repository/settings/mod.rs | 47 ++++++++++++ backend/src/repository/staging/mod.rs | 4 + 9 files changed, 299 insertions(+), 125 deletions(-) diff --git a/backend/src/repository/handler.rs b/backend/src/repository/handler.rs index 180685c3..8c41b5a4 100644 --- a/backend/src/repository/handler.rs +++ b/backend/src/repository/handler.rs @@ -265,7 +265,7 @@ macro_rules! dynamic_repository_handler { } impl DynamicRepositoryHandler{ - #[inline] + #[inline] pub async fn new_dyn_storage( storage: Arc, repository_config: RepositoryConfig, @@ -288,16 +288,85 @@ macro_rules! dynamic_repository_handler { }; } -// NPM, -// NPMHandler, -// Docker, -// DockerHandler, -// CI, -// CIHandler, -// Raw, -// RawHandler - +use crate::repository::ci::CIHandler; +use crate::repository::docker::DockerHandler; use crate::repository::maven::MavenHandler; -dynamic_repository_handler!(Maven, MavenHandler); +use crate::repository::npm::NPMHandler; +use crate::repository::raw::RawHandler; +dynamic_repository_handler!( + Maven, + MavenHandler, + NPM, + NPMHandler, + Docker, + DockerHandler, + CI, + CIHandler, + Raw, + RawHandler +); use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; -crate::repository::nitro::dynamic::nitro_repo_handler!(DynamicRepositoryHandler,); +crate::repository::nitro::dynamic::nitro_repo_handler!( + DynamicRepositoryHandler, + Maven, + MavenHandler +); +macro_rules! repository_config_group { + ($handler:tt,$config:path,$($repository:ident),*) => { + impl crate::repository::settings::RepositoryConfigHandler<$config> + for $handler + { + fn supports_config(&self) -> bool { + match self { + $( + $handler::$repository(handler) => crate::repository::settings::RepositoryConfigHandler::<$config>::supports_config(handler), + )* + _ => unsafe { + core::hint::unreachable_unchecked(); + } + } + } + fn update(&mut self, mut config: $config) -> Result<(), InternalError> { + match self { + $( + $handler::$repository(handler) => crate::repository::settings::RepositoryConfigHandler::<$config>::update(handler, config), + )* + _ => unsafe { + core::hint::unreachable_unchecked(); + } + } + } + fn get(&self) -> &$config { + match self { + $( + $handler::$repository(handler) => crate::repository::settings::RepositoryConfigHandler::<$config>::get(handler), + )* + _ => unsafe { + core::hint::unreachable_unchecked(); + } + } + } + fn get_mut(&mut self) -> &mut $config { + match self { + $( + $handler::$repository(handler) => crate::repository::settings::RepositoryConfigHandler::<$config>::get_mut(handler), + )* + _ => unsafe { + core::hint::unreachable_unchecked(); + } + } + } + } + }; +} +pub(crate) use repository_config_group; +repository_config_group!( + DynamicRepositoryHandler, + crate::repository::settings::badge::BadgeSettings, + Maven +); +repository_config_group!( + DynamicRepositoryHandler, + crate::repository::settings::frontend::Frontend, + Maven +); diff --git a/backend/src/repository/maven/hosted.rs b/backend/src/repository/maven/hosted.rs index eef3b093..23b81d1b 100644 --- a/backend/src/repository/maven/hosted.rs +++ b/backend/src/repository/maven/hosted.rs @@ -4,7 +4,7 @@ use crate::error::internal_error::InternalError; use crate::repository::handler::Repository; use crate::repository::response::RepoResponse; -use crate::repository::settings::{Policy, RepositoryConfig, Visibility}; +use crate::repository::settings::{Policy, RepositoryConfig, RepositoryConfigType, Visibility}; use crate::storage::file::StorageFileResponse; use crate::storage::models::Storage; use crate::system::permissions::options::CanIDo; @@ -14,19 +14,55 @@ use actix_web::http::StatusCode; use actix_web::web::Bytes; use async_trait::async_trait; +use crate::repository::settings::badge::BadgeSettings; +use crate::repository::settings::frontend::Frontend; use sea_orm::DatabaseConnection; +use serde::{Deserialize, Serialize}; use std::sync::Arc; + #[derive(Debug)] pub struct HostedMavenRepository { pub config: RepositoryConfig, pub storage: Arc, + pub badge: BadgeSettings, + pub frontend: Frontend, } +crate::repository::settings::define_config_handler!( + badge, + HostedMavenRepository, + BadgeSettings +); +crate::repository::settings::define_config_handler!( + frontend, + HostedMavenRepository, + Frontend +); impl Clone for HostedMavenRepository { fn clone(&self) -> Self { HostedMavenRepository { config: self.config.clone(), storage: self.storage.clone(), + badge: self.badge.clone(), + frontend: self.frontend.clone(), + } + } +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct MavenHosted { + pub allow_pushing: bool, +} +impl RepositoryConfigType for MavenHosted { + fn config_name() -> &'static str { + "maven_hosted.json" + } +} + +impl Default for MavenHosted { + fn default() -> Self { + MavenHosted { + allow_pushing: true, } } } diff --git a/backend/src/repository/maven/mod.rs b/backend/src/repository/maven/mod.rs index 4aaa8c17..4583822d 100644 --- a/backend/src/repository/maven/mod.rs +++ b/backend/src/repository/maven/mod.rs @@ -1,25 +1,28 @@ -use actix_web::http::header::HeaderMap; +use std::sync::Arc; +use actix_web::http::header::HeaderMap; use actix_web::web::Bytes; +use actix_web::Error; use async_trait::async_trait; - use sea_orm::DatabaseConnection; -use std::sync::Arc; +use hosted::HostedMavenRepository; +use proxy::ProxyMavenRepository; +use settings::{MavenSettings, MavenType}; +use staging::StagingRepository; use crate::authentication::Authentication; - use crate::error::internal_error::InternalError; -use crate::repository::handler::{repository_handler, Repository}; - +use crate::repository::handler::{repository_config_group, repository_handler, Repository}; +use crate::repository::maven::proxy::MavenProxySettings; +use crate::repository::maven::settings::ProxySettings; +use crate::repository::maven::staging::{MavenStagingConfig, StageSettings}; use crate::repository::response::RepoResponse; +use crate::repository::settings::badge::BadgeSettings; +use crate::repository::settings::frontend::Frontend; use crate::repository::settings::RepositoryConfig; - use crate::storage::models::Storage; -use hosted::HostedMavenRepository; -use proxy::ProxyMavenRepository; -use staging::StagingRepository; pub mod error; pub mod hosted; pub mod models; @@ -28,9 +31,6 @@ pub mod settings; pub mod staging; mod utils; -use actix_web::Error; -use settings::{MavenSettings, MavenType}; - repository_handler!( MavenHandler, Hosted, @@ -40,37 +40,49 @@ repository_handler!( Staging, StagingRepository ); +use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; +crate::repository::nitro::dynamic::nitro_repo_handler!(MavenHandler,); impl MavenHandler { pub async fn create( repository: RepositoryConfig, storage: Arc, ) -> Result, InternalError> { + // TODO bring other settings from the configs let result = repository.get_config::(&storage).await?; if let Some(config) = result { match config.repository_type { - MavenType::Hosted { .. } => Ok(HostedMavenRepository { + MavenType::Hosted => Ok(HostedMavenRepository { config: repository, storage, + badge: Default::default(), + frontend: Default::default(), } .into()), - MavenType::Proxy { proxies } => Ok(ProxyMavenRepository { - config: repository, - proxy: proxies, - storage, + MavenType::Proxy => { + let settings = repository + .get_config::(&storage) + .await? + .ok_or(InternalError::Error("Proxy settings not found".to_string()))?; + Ok(ProxyMavenRepository { + config: repository, + proxy: settings, + badge: Default::default(), + frontend: Default::default(), + storage, + } + .into()) } - .into()), - MavenType::Staging { - stage_to, - pre_stage_requirements, - parent, - } => { + MavenType::Staging => { + let settings = repository + .get_config::(&storage) + .await? + .ok_or(InternalError::Error("Stage settings not found".to_string()))?; + let staging = StagingRepository { config: repository, - stage_to, storage, - deploy_requirement: pre_stage_requirements, - parent, + stage_settings: settings, }; Ok(staging.into()) } @@ -79,8 +91,15 @@ impl MavenHandler { Ok(HostedMavenRepository { config: repository, storage, + badge: Default::default(), + frontend: Default::default(), } .into()) } } } + +repository_config_group!(MavenHandler, MavenStagingConfig, Staging); +repository_config_group!(MavenHandler, MavenProxySettings, Proxy); +repository_config_group!(MavenHandler, BadgeSettings, Hosted, Proxy); +repository_config_group!(MavenHandler, Frontend, Hosted, Proxy); diff --git a/backend/src/repository/maven/proxy.rs b/backend/src/repository/maven/proxy.rs index e0565a9c..64a77871 100644 --- a/backend/src/repository/maven/proxy.rs +++ b/backend/src/repository/maven/proxy.rs @@ -1,9 +1,9 @@ use crate::authentication::Authentication; use crate::error::internal_error::InternalError; use crate::repository::handler::Repository; -use crate::repository::maven::settings::ProxySettings; +use crate::repository::maven::settings::{LoginSettings, ProxySettings}; use crate::repository::response::RepoResponse; -use crate::repository::settings::{RepositoryConfig, Visibility}; +use crate::repository::settings::{RepositoryConfig, RepositoryConfigType, Visibility}; use crate::storage::file::StorageFileResponse; use crate::storage::models::Storage; use crate::system::permissions::options::CanIDo; @@ -14,26 +14,62 @@ use actix_web::web::Bytes; use actix_web::{Error, HttpResponse}; use async_trait::async_trait; +use crate::repository::settings::badge::BadgeSettings; +use crate::repository::settings::frontend::Frontend; +use crate::storage::DynamicStorage; use futures::channel::mpsc::unbounded; use futures_util::stream::StreamExt; use futures_util::SinkExt; use sea_orm::DatabaseConnection; +use serde::{Deserialize, Serialize}; use std::sync::Arc; #[derive(Debug)] pub struct ProxyMavenRepository { pub config: RepositoryConfig, - pub proxy: Vec, + pub proxy: MavenProxySettings, + pub badge: BadgeSettings, + pub frontend: Frontend, + pub storage: Arc, } + impl Clone for ProxyMavenRepository { fn clone(&self) -> Self { ProxyMavenRepository { config: self.config.clone(), storage: self.storage.clone(), proxy: self.proxy.clone(), + badge: self.badge.clone(), + frontend: self.frontend.clone(), } } } +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct MavenProxySettings { + proxies: Vec, +} +impl RepositoryConfigType for MavenProxySettings { + fn config_name() -> &'static str { + "maven_proxy.json" + } +} +crate::repository::settings::define_config_handler!( + proxy, + ProxyMavenRepository, + MavenProxySettings +); + +crate::repository::settings::define_config_handler!( + badge, + ProxyMavenRepository, + BadgeSettings +); +crate::repository::settings::define_config_handler!( + frontend, + ProxyMavenRepository, + Frontend +); + #[async_trait] impl Repository for ProxyMavenRepository { fn get_repository(&self) -> &RepositoryConfig { @@ -77,7 +113,7 @@ impl Repository for ProxyMavenRepository { .user_agent("Nitro Repo Proxy Service") .build() .unwrap(); - for proxy in &self.proxy { + for proxy in &self.proxy.proxies { let url = format!("{}/{}", proxy.proxy_url, path); let response = builder.get(&url).send().await; if let Ok(response) = response { diff --git a/backend/src/repository/maven/settings.rs b/backend/src/repository/maven/settings.rs index 37476d71..7def3dcb 100644 --- a/backend/src/repository/maven/settings.rs +++ b/backend/src/repository/maven/settings.rs @@ -6,30 +6,22 @@ use serde::{Deserialize, Serialize}; pub struct MavenSettings { pub repository_type: MavenType, } +impl RepositoryConfigType for MavenSettings { + fn config_name() -> &'static str { + "maven.json" + } +} -#[derive(Debug, Serialize, Deserialize, Clone)] -#[serde(tag = "page_type", content = "content")] +#[derive(Debug, Serialize, Deserialize, Clone, Default)] pub enum MavenType { + #[default] /// Hosted on the Storage Only - Hosted { allow_pushing: bool }, + Hosted, /// An intermediary repository for intake of new artifacts. Pushes the artifacts to other repositories - Staging { - /// This is a parent that nothing is actually pushed it. It just allows for data retrieval. - parent: ProxySettings, - stage_to: Vec, - pre_stage_requirements: Vec, - }, + Staging, /// Uses Remote Proxies to get the artifacts. /// Uses the storage to hold a backup of the artifacts. - Proxy { proxies: Vec }, -} - -impl Default for MavenType { - fn default() -> Self { - MavenType::Hosted { - allow_pushing: true, - } - } + Proxy, } #[derive(Debug, Serialize, Deserialize, Clone, Default)] @@ -43,9 +35,3 @@ pub struct LoginSettings { pub username: String, pub password: String, } - -impl RepositoryConfigType for MavenSettings { - fn config_name() -> &'static str { - "maven.json" - } -} diff --git a/backend/src/repository/maven/staging.rs b/backend/src/repository/maven/staging.rs index 7d609b1f..17b0c902 100644 --- a/backend/src/repository/maven/staging.rs +++ b/backend/src/repository/maven/staging.rs @@ -5,7 +5,7 @@ use crate::repository::handler::Repository; use crate::repository::maven::settings::{MavenSettings, MavenType, ProxySettings}; use crate::repository::response::RepoResponse; -use crate::repository::settings::{Policy, RepositoryConfig, Visibility}; +use crate::repository::settings::{Policy, RepositoryConfig, RepositoryConfigType, Visibility}; use crate::repository::staging::{ProcessingStage, StageHandler}; use crate::storage::file::StorageFileResponse; use crate::storage::models::Storage; @@ -19,16 +19,25 @@ use actix_web::web::Bytes; use actix_web::{Error, HttpResponse}; use async_trait::async_trait; - use futures_util::stream::StreamExt; use futures_util::SinkExt; use sea_orm::DatabaseConnection; use serde::{Deserialize, Serialize}; +use std::sync::Arc; +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct MavenStagingConfig { + /// This is a parent that nothing is actually pushed it. It just allows for data retrieval. + parent: ProxySettings, + stage_to: Vec, + pre_stage_requirements: Vec, +} -use std::sync::{Arc}; - - +impl RepositoryConfigType for MavenStagingConfig { + fn config_name() -> &'static str { + "maven_staging.json" + } +} #[derive(Debug, Serialize, Deserialize, Clone)] pub enum StageSettings { @@ -55,43 +64,13 @@ pub enum DeployRequirement {} pub struct StagingRepository { pub config: RepositoryConfig, pub storage: Arc, - pub stage_to: Vec, - pub parent: ProxySettings, - pub deploy_requirement: Vec, + pub stage_settings: MavenStagingConfig, } - -impl<'a, S: Storage> StagingRepository { - pub async fn create( - repository: RepositoryConfig, - storage: Arc, - ) -> Result, InternalError> { - let result = repository.get_config::(&storage).await?; - if let Some(config) = result { - match config.repository_type { - MavenType::Staging { - stage_to, - pre_stage_requirements, - parent, - } => { - let staging = StagingRepository { - config: repository, - stage_to, - storage, - deploy_requirement: pre_stage_requirements, - parent, - }; - Ok(staging.into()) - } - _ => { - panic!("Staging Repository can only be used with Staging Repository Type"); - } - } - } else { - panic!("Staging Repository can only be used with Staging Repository Type"); - } - } -} - +crate::repository::settings::define_config_handler!( + stage_settings, + StagingRepository, + MavenStagingConfig +); #[async_trait] impl<'a, S: Storage> StageHandler for StagingRepository { async fn push( @@ -109,9 +88,7 @@ impl Clone for StagingRepository { StagingRepository { config: self.config.clone(), storage: self.storage.clone(), - stage_to: self.stage_to.clone(), - parent: self.parent.clone(), - deploy_requirement: self.deploy_requirement.clone(), + stage_settings: self.stage_settings.clone(), } } } @@ -160,7 +137,7 @@ impl Repository for StagingRepository { .user_agent("Nitro Repo Staging Service") .build() .unwrap(); - let url = format!("{}/{}", self.parent.proxy_url, path); + let url = format!("{}/{}", self.stage_settings.parent.proxy_url, path); let response = builder.get(&url).send().await; if let Ok(response) = response { if response.status().is_success() { diff --git a/backend/src/repository/nitro/dynamic.rs b/backend/src/repository/nitro/dynamic.rs index fdbc9ded..ec18fea7 100644 --- a/backend/src/repository/nitro/dynamic.rs +++ b/backend/src/repository/nitro/dynamic.rs @@ -4,7 +4,7 @@ macro_rules! nitro_repo_handler { ($v:ident, $($name: ident, $ty:tt),*) => { #[async_trait::async_trait] - impl<'a, StorageType: Storage> NitroRepositoryHandler + impl<'a, StorageType: Storage> crate::repository::nitro::nitro_repository::NitroRepositoryHandler for $v { fn parse_project_to_directory>(_value: S) -> String { @@ -19,7 +19,7 @@ macro_rules! nitro_repo_handler { async fn get_versions( &self, - _project: &str, + project: &str, ) -> Result, InternalError> { match self { $($v::$name(handler) => handler.get_versions(project).await,)* @@ -30,8 +30,8 @@ macro_rules! nitro_repo_handler { async fn get_project_specific_version( &self, - _project: &str, - _version: &str, + project: &str, + version: &str, ) -> Result, InternalError> { match self { $($v::$name(handler) => handler.get_project_specific_version(project, version).await,)* @@ -40,7 +40,7 @@ macro_rules! nitro_repo_handler { } async fn get_project_latest( &self, - _project: &str, + project: &str, ) -> Result, InternalError> { match self { $($v::$name(handler) => handler.get_project_latest(project).await,)* @@ -48,7 +48,7 @@ macro_rules! nitro_repo_handler { } } - async fn latest_version(&self, _project: &str) -> Result, InternalError> { + async fn latest_version(&self, project: &str) -> Result, InternalError> { match self { $($v::$name(handler) => handler.latest_version(project).await,)* _ => unsafe{ std::hint::unreachable_unchecked() }, @@ -57,8 +57,8 @@ macro_rules! nitro_repo_handler { } async fn process_storage_files( &self, - _directory: crate::storage::file::StorageDirectoryResponse, - _requested_dir: &str, + directory: crate::storage::file::StorageDirectoryResponse, + requested_dir: &str, ) -> Result { match self { $($v::$name(handler) => handler.process_storage_files(directory, requested_dir).await,)* @@ -68,10 +68,10 @@ macro_rules! nitro_repo_handler { } async fn post_deploy( &self, - _project_folder: String, - _version_folder: String, - _model: crate::system::user::database::Model, - _version_data: crate::repository::nitro::VersionData, + project_folder: String, + version_folder: String, + model: crate::system::user::database::Model, + version_data: crate::repository::nitro::VersionData, ) -> Result<(), InternalError> { match self { $($v::$name(handler) => handler.post_deploy(project_folder, version_folder, model, version_data).await,)* diff --git a/backend/src/repository/settings/mod.rs b/backend/src/repository/settings/mod.rs index ac7a5a39..10eaeb60 100644 --- a/backend/src/repository/settings/mod.rs +++ b/backend/src/repository/settings/mod.rs @@ -106,3 +106,50 @@ pub trait RepositoryConfigType: Send + Sync + Clone + Debug + Serialize + Deseri serde_json::from_slice(slice) } } + +pub trait RepositoryConfigHandler { + fn supports_config(&self) -> bool { + true + } + + fn update(&mut self, config: Config) -> Result<(), InternalError>; + + fn get(&self) -> &Config; + + fn get_mut(&mut self) -> &mut Config; +} +macro_rules! define_config_handler { + ($name:ident, $handler:ty, $config:ty, $check:ident) => { + impl crate::repository::settings::RepositoryConfigHandler<$config> + for $handler + { + fn update(&mut self, mut config: $config) -> Result<(), InternalError> { + self.$name = $check(config)?; + Ok(()) + } + fn get(&self) -> &$config { + &self.$name + } + fn get_mut(&mut self) -> &mut $config { + &mut self.$name + } + } + }; + ($name:ident, $handler:ty, $config:ident) => { + impl crate::repository::settings::RepositoryConfigHandler<$config> + for $handler + { + fn update(&mut self, mut config: $config) -> Result<(), InternalError> { + self.$name = config; + Ok(()) + } + fn get(&self) -> &$config { + &self.$name + } + fn get_mut(&mut self) -> &mut $config { + &mut self.$name + } + } + }; +} +pub(crate) use define_config_handler; diff --git a/backend/src/repository/staging/mod.rs b/backend/src/repository/staging/mod.rs index 31f6ed7b..a8c5b181 100644 --- a/backend/src/repository/staging/mod.rs +++ b/backend/src/repository/staging/mod.rs @@ -26,6 +26,10 @@ impl RepositoryConfigType for ProcessingStage { } #[async_trait] pub trait StageHandler { + fn staging_repository(&self) -> bool { + true + } + async fn push( &self, directory: String, From 4576fd21d5c19e84738b9dc08e5ef4c4ee3195f1 Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Fri, 22 Jul 2022 09:48:33 -0400 Subject: [PATCH 44/76] Repository Loading is Complete --- backend/src/helpers.rs | 4 +- backend/src/repository/handler.rs | 36 +++---- backend/src/repository/maven/hosted.rs | 13 ++- backend/src/repository/maven/mod.rs | 4 +- backend/src/repository/maven/proxy.rs | 4 +- backend/src/repository/maven/staging.rs | 4 +- backend/src/repository/nitro/dynamic.rs | 20 +++- .../src/repository/nitro/nitro_repository.rs | 2 + backend/src/repository/settings/mod.rs | 1 + backend/src/repository/web/multi/configs.rs | 99 +++++++------------ backend/src/repository/web/multi/mod.rs | 11 --- 11 files changed, 99 insertions(+), 99 deletions(-) diff --git a/backend/src/helpers.rs b/backend/src/helpers.rs index 879cf84a..e98acf06 100644 --- a/backend/src/helpers.rs +++ b/backend/src/helpers.rs @@ -38,8 +38,8 @@ macro_rules! get_repository { macro_rules! take_repository { ($storage:ident, $repository:ident) => { if let Some(repository) = $storage.remove_repository_for_updating($repository) { - match Removed::try_into(repository) { - Ok((name, arc)) => match Arc::try_unwrap(arc) { + match lockfree::map::Removed::try_into(repository) { + Ok((name, arc)) => match std::sync::Arc::try_unwrap(arc) { Ok(ok) => (name, ok), Err(v) => { let arc1 = (*v).clone(); diff --git a/backend/src/repository/handler.rs b/backend/src/repository/handler.rs index 8c41b5a4..2bc5e211 100644 --- a/backend/src/repository/handler.rs +++ b/backend/src/repository/handler.rs @@ -19,6 +19,10 @@ pub trait Repository: Send + Sync + Clone { fn get_repository(&self) -> &RepositoryConfig; fn get_mut_config(&mut self) -> &mut RepositoryConfig; fn get_storage(&self) -> &S; + #[inline(always)] + fn features(&self) -> Vec<&'static str> { + vec![] + } /// Handles a get request to a Repo async fn handle_get( @@ -146,6 +150,14 @@ macro_rules! repository_handler { )* } } + #[inline(always)] + fn features(&self) -> Vec<&'static str> { + match self { + $( + $name::$repository_type(repository) => repository.features(), + )* + } + } async fn handle_get( &self, @@ -305,12 +317,7 @@ dynamic_repository_handler!( Raw, RawHandler ); -use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; -crate::repository::nitro::dynamic::nitro_repo_handler!( - DynamicRepositoryHandler, - Maven, - MavenHandler -); + macro_rules! repository_config_group { ($handler:tt,$config:path,$($repository:ident),*) => { impl crate::repository::settings::RepositoryConfigHandler<$config> @@ -321,9 +328,7 @@ macro_rules! repository_config_group { $( $handler::$repository(handler) => crate::repository::settings::RepositoryConfigHandler::<$config>::supports_config(handler), )* - _ => unsafe { - core::hint::unreachable_unchecked(); - } + _ => false, } } fn update(&mut self, mut config: $config) -> Result<(), InternalError> { @@ -360,13 +365,10 @@ macro_rules! repository_config_group { }; } pub(crate) use repository_config_group; -repository_config_group!( - DynamicRepositoryHandler, - crate::repository::settings::badge::BadgeSettings, - Maven -); -repository_config_group!( + +use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; +crate::repository::nitro::dynamic::main_nitro_handler!( DynamicRepositoryHandler, - crate::repository::settings::frontend::Frontend, - Maven + Maven, + MavenHandler ); diff --git a/backend/src/repository/maven/hosted.rs b/backend/src/repository/maven/hosted.rs index 23b81d1b..7a52f26b 100644 --- a/backend/src/repository/maven/hosted.rs +++ b/backend/src/repository/maven/hosted.rs @@ -14,8 +14,10 @@ use actix_web::http::StatusCode; use actix_web::web::Bytes; use async_trait::async_trait; +use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; use crate::repository::settings::badge::BadgeSettings; use crate::repository::settings::frontend::Frontend; +use actix_web::Error; use sea_orm::DatabaseConnection; use serde::{Deserialize, Serialize}; use std::sync::Arc; @@ -80,7 +82,10 @@ impl Repository for HostedMavenRepository { fn get_storage(&self) -> &S { self.storage.as_ref() } - + #[inline(always)] + fn features(&self) -> Vec<&'static str> { + vec!["badge", "frontend", "hosted"] + } async fn handle_get( &self, path: &str, @@ -174,3 +179,9 @@ impl Repository for HostedMavenRepository { )) } } +impl NitroRepositoryHandler for HostedMavenRepository { + #[inline(always)] + fn parse_project_to_directory>(value: V) -> String { + value.into().replace('.', "/").replace(':', "/") + } +} diff --git a/backend/src/repository/maven/mod.rs b/backend/src/repository/maven/mod.rs index 4583822d..7ba31711 100644 --- a/backend/src/repository/maven/mod.rs +++ b/backend/src/repository/maven/mod.rs @@ -41,7 +41,7 @@ repository_handler!( StagingRepository ); use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; -crate::repository::nitro::dynamic::nitro_repo_handler!(MavenHandler,); +crate::repository::nitro::dynamic::nitro_repo_handler!(MavenHandler, Hosted, HostedMavenRepository); impl MavenHandler { pub async fn create( @@ -101,5 +101,3 @@ impl MavenHandler { repository_config_group!(MavenHandler, MavenStagingConfig, Staging); repository_config_group!(MavenHandler, MavenProxySettings, Proxy); -repository_config_group!(MavenHandler, BadgeSettings, Hosted, Proxy); -repository_config_group!(MavenHandler, Frontend, Hosted, Proxy); diff --git a/backend/src/repository/maven/proxy.rs b/backend/src/repository/maven/proxy.rs index 64a77871..66b818bb 100644 --- a/backend/src/repository/maven/proxy.rs +++ b/backend/src/repository/maven/proxy.rs @@ -81,7 +81,9 @@ impl Repository for ProxyMavenRepository { fn get_storage(&self) -> &S { self.storage.as_ref() } - + fn features(&self) -> Vec<&'static str> { + vec!["badge", "frontend", "proxy"] + } async fn handle_get( &self, path: &str, diff --git a/backend/src/repository/maven/staging.rs b/backend/src/repository/maven/staging.rs index 17b0c902..aaea9244 100644 --- a/backend/src/repository/maven/staging.rs +++ b/backend/src/repository/maven/staging.rs @@ -104,7 +104,9 @@ impl Repository for StagingRepository { fn get_storage(&self) -> &S { self.storage.as_ref() } - + fn features(&self) -> Vec<&'static str> { + vec!["proxy"] + } async fn handle_get( &self, path: &str, diff --git a/backend/src/repository/nitro/dynamic.rs b/backend/src/repository/nitro/dynamic.rs index ec18fea7..7c4fda0f 100644 --- a/backend/src/repository/nitro/dynamic.rs +++ b/backend/src/repository/nitro/dynamic.rs @@ -3,13 +3,18 @@ /// Array of the Repository Types macro_rules! nitro_repo_handler { ($v:ident, $($name: ident, $ty:tt),*) => { + // Configs that only nitro repositories can have + crate::repository::handler::repository_config_group!($v, crate::repository::settings::badge::BadgeSettings, $($name),*); + crate::repository::handler::repository_config_group!($v, crate::repository::settings::frontend::Frontend, $($name),*); + #[async_trait::async_trait] impl<'a, StorageType: Storage> crate::repository::nitro::nitro_repository::NitroRepositoryHandler for $v { fn parse_project_to_directory>(_value: S) -> String { - panic!("Parse Should be implemented in the Dynamic Nitro Repository Handler"); + unsafe{ std::hint::unreachable_unchecked() } } + #[inline(always)] fn supports_nitro(&self) -> bool { match self { $($v::$name(handler) => handler.supports_nitro(),)* @@ -24,7 +29,6 @@ macro_rules! nitro_repo_handler { match self { $($v::$name(handler) => handler.get_versions(project).await,)* _ => unsafe{ std::hint::unreachable_unchecked() }, - } } @@ -83,3 +87,15 @@ macro_rules! nitro_repo_handler { }; } pub(crate) use nitro_repo_handler; + +macro_rules! main_nitro_handler { + ($v:ident, $($name: ident, $ty:tt),*) => { + crate::repository::nitro::dynamic::nitro_repo_handler!($v, $($name, $ty),*); + pub mod nitro_configs{ + crate::repository::web::multi::configs::define_repository_config_handlers_group!("badge", crate::repository::settings::badge::BadgeSettings, $($name),*); + crate::repository::web::multi::configs::define_repository_config_handlers_group!("frontend", crate::repository::settings::frontend::Frontend, $($name),*); + } + + }; +} +pub(crate) use main_nitro_handler; diff --git a/backend/src/repository/nitro/nitro_repository.rs b/backend/src/repository/nitro/nitro_repository.rs index c31e0844..6f098f85 100644 --- a/backend/src/repository/nitro/nitro_repository.rs +++ b/backend/src/repository/nitro/nitro_repository.rs @@ -19,9 +19,11 @@ use crate::system::user::UserModel; #[async_trait] pub trait NitroRepositoryHandler: Repository { + #[inline(always)] fn supports_nitro(&self) -> bool { true } + #[inline(always)] fn parse_project_to_directory>(value: S) -> String; /// Handles a List of versions request async fn get_versions( diff --git a/backend/src/repository/settings/mod.rs b/backend/src/repository/settings/mod.rs index 10eaeb60..7b7a010c 100644 --- a/backend/src/repository/settings/mod.rs +++ b/backend/src/repository/settings/mod.rs @@ -108,6 +108,7 @@ pub trait RepositoryConfigType: Send + Sync + Clone + Debug + Serialize + Deseri } pub trait RepositoryConfigHandler { + #[inline(always)] fn supports_config(&self) -> bool { true } diff --git a/backend/src/repository/web/multi/configs.rs b/backend/src/repository/web/multi/configs.rs index 496ebcbe..e0d3fcfb 100644 --- a/backend/src/repository/web/multi/configs.rs +++ b/backend/src/repository/web/multi/configs.rs @@ -1,37 +1,39 @@ macro_rules! define_repository_config_get { - ($value:literal,$ty:tt ) => { + ($value:literal,$ty:path, $($repo:ident),*) => { paste::paste! { pub async fn []( - storage_handler: actix_web::web::Data>, + storage_handler: actix_web::web::Data>, database: actix_web::web::Data, auth: crate::authentication::Authentication, path_params: actix_web::web::Path<(String, String)>, ) -> actix_web::Result { use crate::storage::models::Storage; -use crate::system::permissions::options::CanIDo; + use crate::system::permissions::options::CanIDo; let user: crate::system::user::UserModel = auth.get_user(&database).await??; user.can_i_edit_repos()?; let (storage_name, repository_name) = path_params.into_inner(); let storage = crate::helpers::get_storage!(storage_handler, storage_name); let repository = crate::helpers::get_repository!(storage, repository_name); - let config = repository - .get_config::<$ty, crate::storage::DynamicStorage>(&storage) - .await - .map_err(crate::error::internal_error::InternalError::from)?; - if let Some(config) = config { - Ok(actix_web::HttpResponse::Ok().json(config)) - } else { - Ok(actix_web::HttpResponse::NotFound().finish()) + match repository.as_ref() { + $( + crate::repository::handler::DynamicRepositoryHandler::$repo(repository) => { + let value = crate::repository::settings::RepositoryConfigHandler::<$ty>::get(repository); + Ok(actix_web::HttpResponse::Ok().json(value)) + } + )* + _ => { + return Ok(actix_web::HttpResponse::BadRequest().body("Repository type not supported".to_string())); + } } } } }; } macro_rules! define_repository_config_set { - ($value:literal,$ty:tt ) => { + ($value:literal,$ty:path, $($repo:ident),* ) => { paste::paste! { pub async fn []( - storage_handler: actix_web::web::Data>, + storage_handler: actix_web::web::Data>, database: actix_web::web::Data, auth: crate::authentication::Authentication, path_params: actix_web::web::Path<(String, String)>, @@ -43,64 +45,39 @@ use crate::system::permissions::options::CanIDo; user.can_i_edit_repos()?; let (storage_name, repository_name) = path_params.into_inner(); let storage = crate::helpers::get_storage!(storage_handler, storage_name); - let repository = crate::helpers::get_repository!(storage, repository_name); - let body = body.into_inner(); - repository - .save_config::<$ty, crate::storage::DynamicStorage>(&storage,Some(&body)) - .await - .map_err(crate::error::internal_error::InternalError::from)?; - Ok(actix_web::HttpResponse::NoContent().finish()) - } - } - }; -} -macro_rules! define_repository_config_delete { - ($value:literal,$ty:tt ) => { - paste::paste! { - pub async fn []( - storage_handler: actix_web::web::Data>, - database: actix_web::web::Data, - auth: crate::authentication::Authentication, - path_params: actix_web::web::Path<(String, String)>, - ) -> actix_web::Result { - use crate::storage::models::Storage; - use crate::system::permissions::options::CanIDo; - let user: crate::system::user::UserModel = auth.get_user(&database).await??; - user.can_i_edit_repos()?; - let (storage_name, repository_name) = path_params.into_inner(); - let storage = crate::helpers::get_storage!(storage_handler, storage_name); - let repository = crate::helpers::get_repository!(storage, repository_name); - repository - .save_config::<$ty, crate::storage::DynamicStorage>(&storage, None) - .await - .map_err(crate::error::internal_error::InternalError::from)?; - Ok(actix_web::HttpResponse::NoContent().finish()) + let (name,mut repository) = crate::helpers::take_repository!(storage, repository_name); + let body = body.into_inner(); + match repository { + $( + crate::repository::handler::DynamicRepositoryHandler::$repo(ref mut repository) => { + crate::repository::settings::RepositoryConfigHandler::<$ty>::update( repository, body); + } + )* + repository => { + storage.add_repository_for_updating(name, repository).expect("Failed to add repository for updating"); + return Ok(actix_web::HttpResponse::BadRequest().body("Repository type not supported".to_string())); + } } + storage.add_repository_for_updating(name, repository).expect("Failed to add repository for updating"); + Ok(actix_web::HttpResponse::NoContent().finish()) } + } }; } - +pub(crate) use define_repository_config_get; +pub(crate) use define_repository_config_set; macro_rules! define_repository_config_handlers_group { - ($($value:literal, $ty:tt),*) => { - $( - crate::repository::web::multi::configs::define_repository_config_get!($value, $ty); - crate::repository::web::multi::configs::define_repository_config_set!($value, $ty); - crate::repository::web::multi::configs::define_repository_config_delete!($value, $ty); - )* - pub fn init_repository_configs(cfg: &mut actix_web::web::ServiceConfig) { - $( + ($value:literal, $ty:path, $($repo:ident),* ) => { + crate::repository::web::multi::configs::define_repository_config_get!($value, $ty, $($repo),*); + crate::repository::web::multi::configs::define_repository_config_set!($value, $ty, $($repo),*); paste::paste! { + pub fn [](cfg: &mut actix_web::web::ServiceConfig) { cfg.service(actix_web::web::resource([concat!("/repositories/{storage}/{repository}/config/", $value)]) .route(actix_web::web::get().to([])) - .route(actix_web::web::put().to([])) - .route(actix_web::web::delete().to([]))); + .route(actix_web::web::put().to([]))); } - )* } }; } - - - - +pub(crate) use define_repository_config_handlers_group; diff --git a/backend/src/repository/web/multi/mod.rs b/backend/src/repository/web/multi/mod.rs index 910fef32..29afdbcf 100644 --- a/backend/src/repository/web/multi/mod.rs +++ b/backend/src/repository/web/multi/mod.rs @@ -30,14 +30,3 @@ pub fn init_admin(cfg: &mut web::ServiceConfig) { .service(admin::delete_repository); cfg.configure(admin::register_core_updates); } - -pub mod configs_impls { - - // define_repository_config_handlers_group!( - // "badge", - // BadgeSettings, - // "frontend", - // Frontend, - // RepositoryPage - // ); -} From 55aea486a77b66b587b7e7bf383bf5a1e510e039 Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Fri, 22 Jul 2022 10:56:33 -0400 Subject: [PATCH 45/76] Fix Directory Response. Hopefully didnt break Linux --- backend/src/repository/maven/hosted.rs | 13 +++++++------ backend/src/repository/maven/models.rs | 5 +++-- backend/src/repository/maven/proxy.rs | 16 ++++++++++++---- backend/src/storage/file.rs | 16 ++++++++-------- backend/src/storage/local_storage/mod.rs | 8 +++++++- backend/src/storage/multi/mod.rs | 6 +++--- 6 files changed, 40 insertions(+), 24 deletions(-) diff --git a/backend/src/repository/maven/hosted.rs b/backend/src/repository/maven/hosted.rs index 7a52f26b..e544a95e 100644 --- a/backend/src/repository/maven/hosted.rs +++ b/backend/src/repository/maven/hosted.rs @@ -14,10 +14,12 @@ use actix_web::http::StatusCode; use actix_web::web::Bytes; use async_trait::async_trait; +use crate::repository::maven::models::Pom; use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; use crate::repository::settings::badge::BadgeSettings; use crate::repository::settings::frontend::Frontend; use actix_web::Error; +use log::error; use sea_orm::DatabaseConnection; use serde::{Deserialize, Serialize}; use std::sync::Arc; @@ -106,10 +108,9 @@ impl Repository for HostedMavenRepository { .await .map_err(InternalError::from)? { - StorageFileResponse::List(_list) => { - /* let files = self.process_storage_files(list, path).await?; - Ok(RepoResponse::try_from((files, StatusCode::OK))?)*/ - panic!("Not implemented") + StorageFileResponse::List(list) => { + let files = self.process_storage_files(list, path).await?; + Ok(RepoResponse::try_from((files, StatusCode::OK))?) } value => Ok(RepoResponse::FileResponse(value)), } @@ -153,7 +154,7 @@ impl Repository for HostedMavenRepository { .map_err(InternalError::from)?; // Post Deploy Handler - /* if path.ends_with(".pom") { + if path.ends_with(".pom") { let vec = bytes.as_ref().to_vec(); let result = String::from_utf8(vec).map_err(APIError::bad_request)?; let pom: Pom = serde_xml_rs::from_str(&result).map_err(APIError::bad_request)?; @@ -166,7 +167,7 @@ impl Repository for HostedMavenRepository { { error!("Unable to complete post processing Tasks {}", error); } - }*/ + } // Everything was ok Ok(RepoResponse::PUTResponse( exists, diff --git a/backend/src/repository/maven/models.rs b/backend/src/repository/maven/models.rs index 43a5a042..afb46aec 100644 --- a/backend/src/repository/maven/models.rs +++ b/backend/src/repository/maven/models.rs @@ -1,3 +1,5 @@ +use crate::repository::nitro::VersionData; +use crate::utils::get_current_time; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize, Clone)] @@ -39,7 +41,7 @@ pub struct Pom { pub url: Option, pub scm: Option, } -/* + impl Into for Pom { fn into(self) -> VersionData { VersionData { @@ -52,4 +54,3 @@ impl Into for Pom { } } } -*/ diff --git a/backend/src/repository/maven/proxy.rs b/backend/src/repository/maven/proxy.rs index 66b818bb..b71685cc 100644 --- a/backend/src/repository/maven/proxy.rs +++ b/backend/src/repository/maven/proxy.rs @@ -14,15 +14,18 @@ use actix_web::web::Bytes; use actix_web::{Error, HttpResponse}; use async_trait::async_trait; +use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; use crate::repository::settings::badge::BadgeSettings; use crate::repository::settings::frontend::Frontend; use crate::storage::DynamicStorage; +use actix_web::http::StatusCode; use futures::channel::mpsc::unbounded; use futures_util::stream::StreamExt; use futures_util::SinkExt; use sea_orm::DatabaseConnection; use serde::{Deserialize, Serialize}; use std::sync::Arc; + #[derive(Debug)] pub struct ProxyMavenRepository { pub config: RepositoryConfig, @@ -104,10 +107,9 @@ impl Repository for ProxyMavenRepository { .await .map_err(InternalError::from)? { - StorageFileResponse::List(_list) => { - /* let files = self.process_storage_files(list, path).await?; - Ok(RepoResponse::try_from((files, StatusCode::OK))?)*/ - panic!("Not implemented") + StorageFileResponse::List(list) => { + let files = self.process_storage_files(list, path).await?; + Ok(RepoResponse::try_from((files, StatusCode::OK))?) } StorageFileResponse::NotFound => { @@ -148,3 +150,9 @@ impl Repository for ProxyMavenRepository { } } } +impl NitroRepositoryHandler for ProxyMavenRepository { + #[inline(always)] + fn parse_project_to_directory>(value: V) -> String { + value.into().replace('.', "/").replace(':', "/") + } +} diff --git a/backend/src/storage/file.rs b/backend/src/storage/file.rs index af42daf1..3a8df968 100644 --- a/backend/src/storage/file.rs +++ b/backend/src/storage/file.rs @@ -7,9 +7,9 @@ use actix_web::body::BoxBody; use actix_web::http::header::ACCEPT; use actix_web::http::{Method, StatusCode}; use actix_web::{HttpRequest, HttpResponse, Responder, ResponseError}; -use log::{as_error, error}; +use log::{as_error, error, trace}; use serde::Serialize; -use tokio::fs::OpenOptions; +use tokio::fs::{metadata, OpenOptions}; use crate::error::api_error::APIError; use crate::storage::error::StorageError; @@ -22,12 +22,12 @@ pub struct StorageFile { pub mime: String, pub directory: bool, pub file_size: u64, - pub modified: u128, - pub created: u128, + pub modified: u64, + pub created: u64, } impl StorageFile { - fn meta_data(metadata: Metadata) -> (u128, u128, u64, bool) { + fn meta_data(metadata: Metadata) -> (u64, u64, u64, bool) { let created = metadata .created() .unwrap_or_else(|error| { @@ -48,7 +48,7 @@ impl StorageFile { }; let directory = metadata.file_type().is_dir(); let size = metadata.len(); - (created, modified, size, directory) + (created as u64, modified as u64, size, directory) } pub async fn create_from_entry>( relative_path: S, @@ -76,8 +76,8 @@ impl StorageFile { relative_path: S, file_location: &PathBuf, ) -> Result { - let file = OpenOptions::new().read(true).open(&file_location).await?; - let metadata = file.metadata().await?; + let metadata = metadata(file_location).await?; + trace!("Parsing MetaData"); let (created, modified, file_size, directory) = Self::meta_data(metadata); let mime = mime_guess::from_path(file_location) diff --git a/backend/src/storage/local_storage/mod.rs b/backend/src/storage/local_storage/mod.rs index eadabbf9..3a4b9804 100644 --- a/backend/src/storage/local_storage/mod.rs +++ b/backend/src/storage/local_storage/mod.rs @@ -277,7 +277,11 @@ impl Storage for LocalStorage { repository: &RepositoryConfig, location: &str, ) -> Result { - let file_location = self.get_repository_folder(&repository.name).join(location); + let file_location = self + .get_repository_folder(&repository.name) + .join(location) + .canonicalize()?; + trace!("Getting File {}", &file_location.display()); if !file_location.exists() { return Ok(StorageFileResponse::NotFound); } @@ -295,7 +299,9 @@ impl Storage for LocalStorage { trace!("Directory Listing at {:?}", &path); let directory = StorageFile::create(&path, &file_location).await?; //Using STD because Into Iterator is missing + trace!("Meta Data {:?}", &directory); let dir = std::fs::read_dir(&file_location)?; + trace!("Dir Read {:?}", &dir); let mut files = Vec::new(); for x in dir { let entry = x?; diff --git a/backend/src/storage/multi/mod.rs b/backend/src/storage/multi/mod.rs index dc7c75de..a1606e7e 100644 --- a/backend/src/storage/multi/mod.rs +++ b/backend/src/storage/multi/mod.rs @@ -104,8 +104,8 @@ impl MultiStorageController { let handler = DynamicRepositoryHandler::new_dyn_storage(storage.clone(), repository) .await - .map_err(|_error| { - error!("Error loading repository {}", name); + .map_err(|error| { + error!("Error loading repository {}. Error {}", name, error); }); if let Ok(handler) = handler { storage.add_repo_loaded(handler)?; @@ -149,7 +149,7 @@ impl MultiStorageController { directory: true, file_size: 0, modified: 0, - created: create as u128, + created: create as u64, }); } Ok(files) From ae3faa404b777973e1ddb5f7dac3cd1795a3b627 Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Fri, 22 Jul 2022 11:05:56 -0400 Subject: [PATCH 46/76] Clippy Error --- backend/src/repository/nitro/nitro_repository.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/repository/nitro/nitro_repository.rs b/backend/src/repository/nitro/nitro_repository.rs index 6f098f85..4be30323 100644 --- a/backend/src/repository/nitro/nitro_repository.rs +++ b/backend/src/repository/nitro/nitro_repository.rs @@ -23,7 +23,6 @@ pub trait NitroRepositoryHandler: Repository fn supports_nitro(&self) -> bool { true } - #[inline(always)] fn parse_project_to_directory>(value: S) -> String; /// Handles a List of versions request async fn get_versions( From ef08f97ef94f71ff0992234a8f10539114b8d330 Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Fri, 22 Jul 2022 12:39:40 -0400 Subject: [PATCH 47/76] Pushing to a Git is possible now --- backend/src/repository/handler.rs | 2 + backend/src/repository/maven/mod.rs | 1 + backend/src/repository/maven/staging.rs | 127 ++++++++++++++++-- backend/src/repository/staging/dynamic.rs | 40 ++---- backend/src/repository/staging/mod.rs | 1 - backend/src/repository/web/multi/mod.rs | 4 + .../web/multi/repository_handler.rs | 23 +++- backend/src/storage/file.rs | 1 + 8 files changed, 161 insertions(+), 38 deletions(-) diff --git a/backend/src/repository/handler.rs b/backend/src/repository/handler.rs index 2bc5e211..35570029 100644 --- a/backend/src/repository/handler.rs +++ b/backend/src/repository/handler.rs @@ -372,3 +372,5 @@ crate::repository::nitro::dynamic::main_nitro_handler!( Maven, MavenHandler ); + +crate::repository::staging::dynamic::gen_dynamic_stage!(DynamicRepositoryHandler, Maven); diff --git a/backend/src/repository/maven/mod.rs b/backend/src/repository/maven/mod.rs index 7ba31711..ffbf95cc 100644 --- a/backend/src/repository/maven/mod.rs +++ b/backend/src/repository/maven/mod.rs @@ -42,6 +42,7 @@ repository_handler!( ); use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; crate::repository::nitro::dynamic::nitro_repo_handler!(MavenHandler, Hosted, HostedMavenRepository); +crate::repository::staging::dynamic::gen_dynamic_stage!(MavenHandler, Staging); impl MavenHandler { pub async fn create( diff --git a/backend/src/repository/maven/staging.rs b/backend/src/repository/maven/staging.rs index aaea9244..3bf8ad91 100644 --- a/backend/src/repository/maven/staging.rs +++ b/backend/src/repository/maven/staging.rs @@ -2,6 +2,8 @@ use crate::authentication::Authentication; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; use crate::repository::handler::Repository; +use std::path::Path; +use std::{fs, io}; use crate::repository::maven::settings::{MavenSettings, MavenType, ProxySettings}; use crate::repository::response::RepoResponse; @@ -24,7 +26,13 @@ use futures_util::SinkExt; use sea_orm::DatabaseConnection; use serde::{Deserialize, Serialize}; +use git2::PushOptions; +use log::trace; use std::sync::Arc; +use tempfile::tempdir; +use tokio::fs::create_dir_all; +use tokio::process::Command; + #[derive(Debug, Serialize, Deserialize, Clone)] pub struct MavenStagingConfig { /// This is a parent that nothing is actually pushed it. It just allows for data retrieval. @@ -75,12 +83,116 @@ crate::repository::settings::define_config_handler!( impl<'a, S: Storage> StageHandler for StagingRepository { async fn push( &self, - _directory: String, - _process: ProcessingStage, - _storages: Arc>, + directory: String, + storages: Arc>, ) -> Result<(), InternalError> { - todo!() + for stage in self.stage_settings.stage_to.iter() { + match stage { + StageSettings::InternalRepository { .. } => {} + StageSettings::GitPush { + git_branch, + git_url, + git_password, + git_username, + } => { + // Clone all data + let branch = git_branch.clone(); + let url = git_url.clone(); + let password = git_password.clone(); + let username = git_username.clone(); + let repository = self.get_repository().clone(); + let storage = storages + .get_storage_by_name(&self.config.storage) + .await + .unwrap() + .unwrap(); + let directory = directory.clone(); + actix_web::rt::spawn(async move { + stage_to_git( + username, password, url, branch, directory, storage, repository, + ) + .await; + }); + } + StageSettings::ExternalRepository { .. } => {} + } + } + Ok(()) + } +} + +pub async fn stage_to_git( + username: String, + password: String, + url: String, + branch: String, + directory: String, + storage: Arc, + repository: RepositoryConfig, +) { + let dir = tempdir().unwrap(); + trace!("Cloning {} to {}", url, dir.path().display()); + let git = git2::Repository::clone(&url, dir.path()).unwrap(); + match storage.as_ref() { + DynamicStorage::LocalStorage(local) => { + let buf = local + .get_repository_folder(&repository.name) + .join(&directory); + let x = git.workdir().unwrap().join(&directory); + fs::create_dir_all(&x).unwrap(); + copy_dir_all(&buf, &x).unwrap(); + } + _ => { + todo!("Support other storage types"); + } } + Command::new("git") + .arg("add") + .arg("*") + .current_dir(dir.path()) + .status() + .await; + Command::new("git") + .arg("commit") + .arg("-m") + .arg("Staging") + .current_dir(dir.path()) + .status() + .await; + let mut options = PushOptions::new(); + let mut callbacks = git2::RemoteCallbacks::new(); + callbacks.credentials(|_, _, _| { + let user = username.clone(); + let pass = password.clone(); + git2::Cred::userpass_plaintext(&user, &pass) + }); + options.remote_callbacks(callbacks); + + git.find_remote("origin") + .unwrap() + .push(&["refs/heads/main"], Some(&mut options)) + .unwrap(); +} +fn copy_dir_all(src: impl AsRef, dst: impl AsRef) -> io::Result<()> { + trace!( + "Copying {} to {}", + src.as_ref().display(), + dst.as_ref().display() + ); + fs::create_dir_all(&dst)?; + for entry in fs::read_dir(src)? { + let entry = entry?; + let ty = entry.file_type()?; + if ty.is_dir() { + copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?; + } else { + let tof = dst.as_ref().join(entry.file_name()); + let srcf = entry.path(); + trace!("Copying {} to {}", srcf.display(), tof.display()); + fs::copy(srcf, tof)?; + } + } + Ok(()) } impl Clone for StagingRepository { @@ -127,12 +239,7 @@ impl Repository for StagingRepository { .await .map_err(InternalError::from)? { - StorageFileResponse::List(_list) => { - /* - let files = self.process_storage_files(list, path).await?; - Ok(RepoResponse::try_from((files, StatusCode::OK))?)*/ - panic!("Not implemented") - } + StorageFileResponse::List(list) => Ok(RepoResponse::try_from((list, StatusCode::OK))?), StorageFileResponse::NotFound => { let builder = reqwest::ClientBuilder::new() diff --git a/backend/src/repository/staging/dynamic.rs b/backend/src/repository/staging/dynamic.rs index 38f2a25e..3b1c800d 100644 --- a/backend/src/repository/staging/dynamic.rs +++ b/backend/src/repository/staging/dynamic.rs @@ -8,42 +8,30 @@ use crate::storage::DynamicStorage; use std::sync::Arc; macro_rules! gen_dynamic_stage { - ($($name: ident, $ty:tt),*) => { - - pub enum DynamicStageHandler { - $( - $name($ty), - )* - } - #[inline] - pub async fn get_stage_handler( - _storage: Arc, - _repository_config: RepositoryConfig, - ) -> Result, InternalError> { - panic!("Not implemented"); - } + ($v:ident,$($name:ident),*) => { #[async_trait::async_trait] - impl StageHandler - for DynamicStageHandler{ + impl crate::repository::staging::StageHandler for $v{ + fn staging_repository(&self) -> bool { + match self { + $( + $v::$name(handler) => handler.staging_repository(), + )* + _ => false, + } + } async fn push( &self, directory: String, - process: ProcessingStage, - storages: Arc>, + storages: Arc>, ) -> Result<(), InternalError>{ match self { $( - DynamicStageHandler::$name(handler) => handler.push(directory, process, storages).await, + $v::$name(handler) => handler.push(directory, storages).await, )* + _ => unsafe{ std::hint::unreachable_unchecked() }, } } } }; } -pub enum StageHandlerResult { - Supported(DynamicStageHandler), - /// it is a teapot! [Teapot](https://http.cat/418) - Unsupported(RepositoryConfig), -} - -gen_dynamic_stage!(Maven, StagingRepository); +pub(crate) use gen_dynamic_stage; diff --git a/backend/src/repository/staging/mod.rs b/backend/src/repository/staging/mod.rs index a8c5b181..c4451477 100644 --- a/backend/src/repository/staging/mod.rs +++ b/backend/src/repository/staging/mod.rs @@ -33,7 +33,6 @@ pub trait StageHandler { async fn push( &self, directory: String, - process: ProcessingStage, storages: Arc>, ) -> Result<(), InternalError>; } diff --git a/backend/src/repository/web/multi/mod.rs b/backend/src/repository/web/multi/mod.rs index 29afdbcf..6b36d8e1 100644 --- a/backend/src/repository/web/multi/mod.rs +++ b/backend/src/repository/web/multi/mod.rs @@ -20,6 +20,10 @@ pub fn init_repository_handlers(cfg: &mut web::ServiceConfig) { .route(web::head().to(repository_handler::head_repository)) .route(web::patch().to(repository_handler::patch_repository)) .route(web::post().to(repository_handler::post_repository)), + ) + .service( + web::resource("/stage/repositories/{storage}/{repository}/{file:.*}") + .route(web::put().to(repository_handler::stage_repository)), ); } diff --git a/backend/src/repository/web/multi/repository_handler.rs b/backend/src/repository/web/multi/repository_handler.rs index 6f3ef590..21c069ac 100644 --- a/backend/src/repository/web/multi/repository_handler.rs +++ b/backend/src/repository/web/multi/repository_handler.rs @@ -1,5 +1,5 @@ use actix_web::web::Bytes; -use actix_web::{web, HttpRequest}; +use actix_web::{web, HttpRequest, HttpResponse}; use sea_orm::DatabaseConnection; use serde::Deserialize; @@ -7,9 +7,12 @@ use crate::authentication::Authentication; use crate::repository::handler::Repository; use crate::repository::response::RepoResponse; +use crate::repository::staging::StageHandler; use crate::storage::models::Storage; use crate::storage::multi::MultiStorageController; use crate::storage::DynamicStorage; +use crate::system::permissions::options::CanIDo; +use crate::system::user::UserModel; #[derive(Deserialize, Clone)] pub struct GetPath { pub storage: String, @@ -22,6 +25,7 @@ impl GetPath { (self.storage, self.repository, self.file) } } + pub async fn get_repository( pool: web::Data, storages: web::Data>, @@ -52,6 +56,23 @@ pub async fn put_repository( .handle_put(&file, r.headers(), pool.get_ref(), auth, bytes) .await } +pub async fn stage_repository( + pool: web::Data, + storages: web::Data>, + authentication: Authentication, + path: web::Path, +) -> actix_web::Result { + let (storage_name, repository_name, file) = path.into_inner().into_inner(); + let storage = crate::helpers::get_storage!(storages, storage_name); + let repository = crate::helpers::get_repository!(storage, repository_name); + if !repository.staging_repository() { + return Ok(HttpResponse::BadRequest().finish().into()); + } + let caller: UserModel = authentication.get_user(pool.as_ref()).await??; + if let Some(_value) = caller.can_deploy_to(&repository.get_repository())? {} + repository.push(file, storages.into_inner()).await?; + Ok(HttpResponse::NoContent().finish().into()) +} pub async fn head_repository( pool: web::Data, diff --git a/backend/src/storage/file.rs b/backend/src/storage/file.rs index 3a8df968..eb954bd6 100644 --- a/backend/src/storage/file.rs +++ b/backend/src/storage/file.rs @@ -101,6 +101,7 @@ impl StorageFile { Ok(file) } } +#[derive(Serialize, Clone, Debug)] pub struct StorageDirectoryResponse { pub files: Vec, pub directory: StorageFile, From 30feea12d0aad7a57f598824fba44b99e257ea04 Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Fri, 22 Jul 2022 15:24:27 -0400 Subject: [PATCH 48/76] Pushing to an external is possible now --- .../src/repository/maven/staging/external.rs | 56 ++++++++ backend/src/repository/maven/staging/git.rs | 115 ++++++++++++++++ .../maven/{staging.rs => staging/mod.rs} | 126 +++++++----------- backend/src/repository/settings/mod.rs | 6 +- backend/src/repository/staging/dynamic.rs | 3 +- backend/src/repository/staging/mod.rs | 2 + .../web/multi/repository_handler.rs | 2 +- backend/src/storage/local_storage/mod.rs | 26 ++++ backend/src/storage/mod.rs | 14 ++ backend/src/storage/models.rs | 7 + backend/src/storage/path.rs | 49 +++++++ 11 files changed, 324 insertions(+), 82 deletions(-) create mode 100644 backend/src/repository/maven/staging/external.rs create mode 100644 backend/src/repository/maven/staging/git.rs rename backend/src/repository/maven/{staging.rs => staging/mod.rs} (76%) create mode 100644 backend/src/storage/path.rs diff --git a/backend/src/repository/maven/staging/external.rs b/backend/src/repository/maven/staging/external.rs new file mode 100644 index 00000000..a48ce9f8 --- /dev/null +++ b/backend/src/repository/maven/staging/external.rs @@ -0,0 +1,56 @@ +use crate::repository::settings::RepositoryConfig; +use crate::storage::models::Storage; +use crate::storage::DynamicStorage; +use crate::system::user::UserModel; +use log::{trace, warn}; +use reqwest::header::{HeaderMap, USER_AGENT}; +use reqwest::Client; +use std::sync::Arc; + +pub async fn stage_to_external( + username: String, + password: String, + url: String, + directory: String, + storage: Arc, + repository: RepositoryConfig, + model: UserModel, +) -> anyhow::Result<()> { + let string = base64::encode(format!("{}:{}", username, password)); + let mut map = HeaderMap::new(); + map.insert( + "Authorization", + format!("Basic {}", string).parse().unwrap(), + ); + map.insert(USER_AGENT, "Nitro Repository Staging Service".parse()?); + let result = reqwest::ClientBuilder::new().default_headers(map).build()?; + for x in storage + .list_files(&repository.name, directory.clone()) + .await? + { + if x.is_dir { + warn!("Skipping directory {}", x.name); + continue; + } + let file_path = format!("{}/{}", directory, x.name); + let data = storage.get_file(&repository, &file_path).await?; + let full_url = format!("{}/{}", url, file_path); + trace!("Staging {:?} to {}", x, full_url); + if let Some(v) = data { + result.put(&full_url).body(v).send().await?; + } + } + let mut v = directory + .split("/") + .map(|v| v.to_string()) + .collect::>(); + v.pop(); + v.push("maven-metadata.xml".to_string()); + let path = v.join("/"); + let full_url = format!("{}/{}", url, path); + let data = storage.get_file(&repository, &path).await?; + if let Some(v) = data { + result.put(&full_url).body(v).send().await?; + } + Ok(()) +} diff --git a/backend/src/repository/maven/staging/git.rs b/backend/src/repository/maven/staging/git.rs new file mode 100644 index 00000000..f8f35e27 --- /dev/null +++ b/backend/src/repository/maven/staging/git.rs @@ -0,0 +1,115 @@ +use crate::repository::maven::models::Pom; +use crate::repository::settings::RepositoryConfig; +use crate::storage::DynamicStorage; +use crate::system::user::database::Model as UserModel; +use git2::PushOptions; +use log::{error, trace}; +use std::path::Path; +use std::sync::Arc; +use std::{fs, io}; +use tempfile::tempdir; + +pub async fn stage_to_git( + username: String, + password: String, + url: String, + branch: String, + directory: String, + storage: Arc, + repository: RepositoryConfig, + model: UserModel, +) -> anyhow::Result<()> { + let dir = tempdir()?; + trace!("Cloning {} to {}", url, dir.path().display()); + let git = git2::Repository::clone(&url, dir.path())?; + let working_directory = git.workdir().unwrap().join(&directory); + + match storage.as_ref() { + DynamicStorage::LocalStorage(local) => { + let buf = local + .get_repository_folder(&repository.name) + .join(&directory); + fs::create_dir_all(&working_directory)?; + copy_dir_all(&buf, &working_directory)?; + if let Some(v) = buf.parent() { + let maven = v.join("maven-metadata.xml"); + if maven.exists() { + fs::copy( + maven, + working_directory + .parent() + .unwrap() + .join("maven-metadata.xml"), + )?; + } + } + } + _ => { + todo!("Support other storage types"); + } + } + let mut index = git.index()?; + index.add_all(["*"].iter(), git2::IndexAddOption::DEFAULT, None)?; + index.write().expect("Failed to write index"); + let v = index.write_tree()?; + let tree = git.find_tree(v).unwrap(); + let sig = git2::Signature::now(model.name.as_str(), model.email.as_str())?; + let me = git.signature()?; + let parent_commit = git.head()?.peel_to_commit()?; + let mut commit_name = "Released".to_string(); + for entry in fs::read_dir(working_directory).expect("Failed to read dir") { + let entry = entry.expect("Failed to get entry"); + if entry.file_name().to_str().unwrap().ends_with("pom") { + let pom: Result = + serde_xml_rs::from_reader(fs::OpenOptions::new().read(true).open(entry.path())?); + match pom { + Ok(ok) => { + commit_name = format!("{} {} - Nitro Repo", ok.artifact_id, ok.version); + break; + } + Err(error) => { + error!("Failed to parse pom: {}", error); + } + } + } + } + + git.commit( + Some("HEAD"), + &sig, + &me, + commit_name.as_str(), + &tree, + &[&parent_commit], + )?; + let mut options = PushOptions::new(); + let mut callbacks = git2::RemoteCallbacks::new(); + callbacks.credentials(|_, _, _| git2::Cred::userpass_plaintext(&username, &password)); + options.remote_callbacks(callbacks); + + git.find_remote("origin")? + .push(&[format!("refs/heads/{}", branch)], Some(&mut options))?; + Ok(()) +} + +fn copy_dir_all(src: impl AsRef, dst: impl AsRef) -> io::Result<()> { + trace!( + "Copying {} to {}", + src.as_ref().display(), + dst.as_ref().display() + ); + fs::create_dir_all(&dst)?; + for entry in fs::read_dir(src)? { + let entry = entry?; + let ty = entry.file_type()?; + if ty.is_dir() { + copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?; + } else { + let tof = dst.as_ref().join(entry.file_name()); + let srcf = entry.path(); + trace!("Copying {} to {}", srcf.display(), tof.display()); + fs::copy(srcf, tof)?; + } + } + Ok(()) +} diff --git a/backend/src/repository/maven/staging.rs b/backend/src/repository/maven/staging/mod.rs similarity index 76% rename from backend/src/repository/maven/staging.rs rename to backend/src/repository/maven/staging/mod.rs index 3bf8ad91..f3ac85e1 100644 --- a/backend/src/repository/maven/staging.rs +++ b/backend/src/repository/maven/staging/mod.rs @@ -26,13 +26,17 @@ use futures_util::SinkExt; use sea_orm::DatabaseConnection; use serde::{Deserialize, Serialize}; +use crate::repository::maven::models::Pom; use git2::PushOptions; -use log::trace; +use log::{error, info, trace}; use std::sync::Arc; use tempfile::tempdir; use tokio::fs::create_dir_all; use tokio::process::Command; +mod external; +mod git; + #[derive(Debug, Serialize, Deserialize, Clone)] pub struct MavenStagingConfig { /// This is a parent that nothing is actually pushed it. It just allows for data retrieval. @@ -85,6 +89,7 @@ impl<'a, S: Storage> StageHandler for StagingRepository { &self, directory: String, storages: Arc>, + model: UserModel, ) -> Result<(), InternalError> { for stage in self.stage_settings.stage_to.iter() { match stage { @@ -107,94 +112,57 @@ impl<'a, S: Storage> StageHandler for StagingRepository { .unwrap() .unwrap(); let directory = directory.clone(); + let user = model.clone(); actix_web::rt::spawn(async move { - stage_to_git( - username, password, url, branch, directory, storage, repository, + info!("Triggering Git Stage"); + if let Err(error) = git::stage_to_git( + username, password, url, branch, directory, storage, repository, user, ) - .await; + .await + { + error!("Failed to stage to git. The rest of the stages do continue to matter. "); + error!("{}", error); + // Trigger Webhooks + } + }); + } + StageSettings::ExternalRepository { + username, + repository, + password, + } => { + let url = repository.clone(); + let repository = repository.clone(); + let username = username.clone(); + let password = password.clone(); + let repository = self.get_repository().clone(); + let storage = storages + .get_storage_by_name(&self.config.storage) + .await + .unwrap() + .unwrap(); + let directory = directory.clone(); + let user = model.clone(); + + actix_web::rt::spawn(async move { + info!("Triggering External Stage"); + if let Err(error) = external::stage_to_external( + username, password, url, directory, storage, repository, user, + ) + .await + { + error!("Failed to stage to external. The rest of the stages do continue to matter. "); + error!("{}", error); + // Trigger Webhooks + } }); } - StageSettings::ExternalRepository { .. } => {} } } Ok(()) } } -pub async fn stage_to_git( - username: String, - password: String, - url: String, - branch: String, - directory: String, - storage: Arc, - repository: RepositoryConfig, -) { - let dir = tempdir().unwrap(); - trace!("Cloning {} to {}", url, dir.path().display()); - let git = git2::Repository::clone(&url, dir.path()).unwrap(); - match storage.as_ref() { - DynamicStorage::LocalStorage(local) => { - let buf = local - .get_repository_folder(&repository.name) - .join(&directory); - let x = git.workdir().unwrap().join(&directory); - fs::create_dir_all(&x).unwrap(); - copy_dir_all(&buf, &x).unwrap(); - } - _ => { - todo!("Support other storage types"); - } - } - Command::new("git") - .arg("add") - .arg("*") - .current_dir(dir.path()) - .status() - .await; - Command::new("git") - .arg("commit") - .arg("-m") - .arg("Staging") - .current_dir(dir.path()) - .status() - .await; - let mut options = PushOptions::new(); - let mut callbacks = git2::RemoteCallbacks::new(); - callbacks.credentials(|_, _, _| { - let user = username.clone(); - let pass = password.clone(); - git2::Cred::userpass_plaintext(&user, &pass) - }); - options.remote_callbacks(callbacks); - - git.find_remote("origin") - .unwrap() - .push(&["refs/heads/main"], Some(&mut options)) - .unwrap(); -} -fn copy_dir_all(src: impl AsRef, dst: impl AsRef) -> io::Result<()> { - trace!( - "Copying {} to {}", - src.as_ref().display(), - dst.as_ref().display() - ); - fs::create_dir_all(&dst)?; - for entry in fs::read_dir(src)? { - let entry = entry?; - let ty = entry.file_type()?; - if ty.is_dir() { - copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?; - } else { - let tof = dst.as_ref().join(entry.file_name()); - let srcf = entry.path(); - trace!("Copying {} to {}", srcf.display(), tof.display()); - fs::copy(srcf, tof)?; - } - } - Ok(()) -} - impl Clone for StagingRepository { fn clone(&self) -> Self { StagingRepository { diff --git a/backend/src/repository/settings/mod.rs b/backend/src/repository/settings/mod.rs index 7b7a010c..39b36494 100644 --- a/backend/src/repository/settings/mod.rs +++ b/backend/src/repository/settings/mod.rs @@ -64,7 +64,11 @@ pub struct RepositoryConfig { /// When it was created pub created: i64, } - +impl AsRef for RepositoryConfig { + fn as_ref(&self) -> &str { + &self.name + } +} impl RepositoryConfig { /// Gets the Config File /// # Arguments diff --git a/backend/src/repository/staging/dynamic.rs b/backend/src/repository/staging/dynamic.rs index 3b1c800d..a75bce71 100644 --- a/backend/src/repository/staging/dynamic.rs +++ b/backend/src/repository/staging/dynamic.rs @@ -23,10 +23,11 @@ macro_rules! gen_dynamic_stage { &self, directory: String, storages: Arc>, + user: crate::system::user::UserModel, ) -> Result<(), InternalError>{ match self { $( - $v::$name(handler) => handler.push(directory, storages).await, + $v::$name(handler) => handler.push(directory, storages, user).await, )* _ => unsafe{ std::hint::unreachable_unchecked() }, } diff --git a/backend/src/repository/staging/mod.rs b/backend/src/repository/staging/mod.rs index c4451477..fe0d69f6 100644 --- a/backend/src/repository/staging/mod.rs +++ b/backend/src/repository/staging/mod.rs @@ -9,6 +9,7 @@ use crate::storage::DynamicStorage; use async_trait::async_trait; use serde::{Deserialize, Serialize}; +use crate::system::user::UserModel; use std::sync::Arc; #[derive(Debug, Serialize, Deserialize, Clone)] @@ -34,5 +35,6 @@ pub trait StageHandler { &self, directory: String, storages: Arc>, + user: UserModel, ) -> Result<(), InternalError>; } diff --git a/backend/src/repository/web/multi/repository_handler.rs b/backend/src/repository/web/multi/repository_handler.rs index 21c069ac..7f421fd5 100644 --- a/backend/src/repository/web/multi/repository_handler.rs +++ b/backend/src/repository/web/multi/repository_handler.rs @@ -70,7 +70,7 @@ pub async fn stage_repository( } let caller: UserModel = authentication.get_user(pool.as_ref()).await??; if let Some(_value) = caller.can_deploy_to(&repository.get_repository())? {} - repository.push(file, storages.into_inner()).await?; + repository.push(file, storages.into_inner(), caller).await?; Ok(HttpResponse::NoContent().finish().into()) } diff --git a/backend/src/storage/local_storage/mod.rs b/backend/src/storage/local_storage/mod.rs index 3a4b9804..2019a998 100644 --- a/backend/src/storage/local_storage/mod.rs +++ b/backend/src/storage/local_storage/mod.rs @@ -24,6 +24,7 @@ use crate::storage::error::StorageError; use crate::storage::file::{StorageDirectoryResponse, StorageFile, StorageFileResponse}; use crate::storage::models::{Storage, StorageStatus}; +use crate::storage::path::{StoragePath, SystemStorageFile}; use crate::storage::{DynamicStorage, StorageConfig, StorageSaver, STORAGE_CONFIG}; #[derive(Debug)] @@ -373,4 +374,29 @@ impl Storage for LocalStorage { .map(Some) } } + + async fn list_files + Send, SP: Into + Send>( + &self, + repository: S, + path: SP, + ) -> Result, StorageError> { + let path = path.into(); + let system_path = path + .clone() + .join_system(self.get_repository_folder(repository.as_ref())); + let dir = std::fs::read_dir(&system_path)?; + let mut files = Vec::new(); + for value in dir { + let entry = value?; + + files.push(SystemStorageFile { + name: entry + .file_name() + .into_string() + .expect("Failed to get file name"), + is_dir: entry.path().is_dir(), + }); + } + Ok(files) + } } diff --git a/backend/src/storage/mod.rs b/backend/src/storage/mod.rs index cf8f0711..80a8b393 100644 --- a/backend/src/storage/mod.rs +++ b/backend/src/storage/mod.rs @@ -18,6 +18,9 @@ pub mod file; pub mod local_storage; pub mod models; pub mod multi; +pub mod path; +use path::StoragePath; +use path::SystemStorageFile; pub static STORAGES_CONFIG: &str = "storages.nitro_repo"; pub static STORAGE_CONFIG: &str = "storage.nitro_repo"; use crate::repository::handler::DynamicRepositoryHandler; @@ -182,6 +185,17 @@ impl Storage for DynamicStorage{ _ => unsafe{ unreachable_unchecked() } } } + + async fn list_files+ Send, SP: Into+ Send>( + &self, + repository: S, + path: SP, + ) -> Result, StorageError>{ + match self { + $(DynamicStorage::$name(storage) => storage.list_files(repository, path).await,)* + _ => unsafe{ unreachable_unchecked() } + } + } } }; } diff --git a/backend/src/storage/models.rs b/backend/src/storage/models.rs index 2e739220..666dedc3 100644 --- a/backend/src/storage/models.rs +++ b/backend/src/storage/models.rs @@ -14,6 +14,7 @@ use crate::repository::settings::RepositoryConfig; use crate::storage::error::StorageError; use crate::storage::file::{StorageFile, StorageFileResponse}; +use crate::storage::path::{StoragePath, SystemStorageFile}; use crate::storage::DynamicStorage; use crate::storage::StorageSaver; @@ -158,4 +159,10 @@ pub trait Storage: Send + Sync { repository: &RepositoryConfig, config_name: &str, ) -> Result, StorageError>; + + async fn list_files + Send, SP: Into + Send>( + &self, + repository: S, + path: SP, + ) -> Result, StorageError>; } diff --git a/backend/src/storage/path.rs b/backend/src/storage/path.rs new file mode 100644 index 00000000..f3a72817 --- /dev/null +++ b/backend/src/storage/path.rs @@ -0,0 +1,49 @@ +use std::path::{Path, PathBuf}; +use std::str::FromStr; + +#[derive(Debug, Clone)] +pub struct StoragePath { + segments: Vec, +} +impl StoragePath { + pub fn new() -> Self { + Self { segments: vec![] } + } + pub fn join>(&mut self, segment: S) { + self.segments.push(segment.into()); + } + pub fn join_new>(&self, s: S) -> Self { + let mut path = self.clone(); + path.join(s); + path + } + pub fn join_system>(mut self, path: P) -> PathBuf { + let mut path: PathBuf = path.into(); + for x in self.segments { + path = path.join(x.as_str()) + } + path + } +} +impl From for StoragePath { + fn from(v: String) -> Self { + Self { + segments: v.split("/").map(|s| s.to_string()).collect(), + } + } +} +impl FromStr for StoragePath { + type Err = (); + + fn from_str(s: &str) -> Result { + Ok(Self { + segments: s.split("/").map(|s| s.to_string()).collect(), + }) + } +} + +#[derive(Debug, Clone)] +pub struct SystemStorageFile { + pub name: String, + pub is_dir: bool, +} From 4b969d95530f93d21a91f491c7a337bc164c45ef Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Wed, 27 Jul 2022 14:52:04 -0400 Subject: [PATCH 49/76] Started to work on the authentication API and the cli --- .gitignore | 6 +- .../src/authentication/auth_token/database.rs | 2 +- backend/src/authentication/auth_token/mod.rs | 1 + .../src/authentication/auth_token/web/mod.rs | 82 +++++++++++++++++++ backend/src/bin/nitro_repo_full.rs | 3 +- nrc/Cargo.toml | 20 +++++ nrc/README.md | 32 ++++++++ nrc/src/add.rs | 77 +++++++++++++++++ nrc/src/api/mod.rs | 51 ++++++++++++ nrc/src/configs/mod.rs | 44 ++++++++++ nrc/src/configs/user.rs | 24 ++++++ nrc/src/instances.rs | 38 +++++++++ nrc/src/main.rs | 46 +++++++++++ 13 files changed, 422 insertions(+), 4 deletions(-) create mode 100644 backend/src/authentication/auth_token/web/mod.rs create mode 100644 nrc/Cargo.toml create mode 100644 nrc/README.md create mode 100644 nrc/src/add.rs create mode 100644 nrc/src/api/mod.rs create mode 100644 nrc/src/configs/mod.rs create mode 100644 nrc/src/configs/user.rs create mode 100644 nrc/src/instances.rs create mode 100644 nrc/src/main.rs diff --git a/.gitignore b/.gitignore index 19d044e5..2ce42ec1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ backend/target backend/test -test/ +nrc/target + +backend/test/ *.iml .idea log @@ -20,4 +22,4 @@ docs/docs/.vitepress/dist/ *.log *.env* *.tar.gz -test/ \ No newline at end of file +backend/test/ \ No newline at end of file diff --git a/backend/src/authentication/auth_token/database.rs b/backend/src/authentication/auth_token/database.rs index bbff3fee..d4ba69fd 100644 --- a/backend/src/authentication/auth_token/database.rs +++ b/backend/src/authentication/auth_token/database.rs @@ -64,7 +64,7 @@ impl sea_orm::sea_query::ValueType for TokenProperties { #[sea_orm(table_name = "auth_tokens")] pub struct Model { #[sea_orm(primary_key)] - pub id: i64, + pub id: Uuid, pub token: String, pub expiration: i64, pub properties: TokenProperties, diff --git a/backend/src/authentication/auth_token/mod.rs b/backend/src/authentication/auth_token/mod.rs index 2b283371..39df6caa 100644 --- a/backend/src/authentication/auth_token/mod.rs +++ b/backend/src/authentication/auth_token/mod.rs @@ -1,4 +1,5 @@ pub mod database; +pub mod web; use crate::authentication::auth_token::database::TokenProperties; use crate::error::internal_error::InternalError; diff --git a/backend/src/authentication/auth_token/web/mod.rs b/backend/src/authentication/auth_token/web/mod.rs new file mode 100644 index 00000000..592de000 --- /dev/null +++ b/backend/src/authentication/auth_token/web/mod.rs @@ -0,0 +1,82 @@ +use crate::authentication::auth_token::database::TokenProperties; +use crate::authentication::auth_token::{generate_token, token_expiration}; +use crate::authentication::{verify_login, Authentication}; +use crate::system::user::UserModel; +use crate::utils::get_current_time; +use actix_web::http::StatusCode; +use actix_web::web; +use actix_web::{delete, get, post, HttpRequest, HttpResponse}; +use chrono::Duration; +use log::error; +use sea_orm::ActiveValue::Set; +use sea_orm::EntityTrait; +use sea_orm::{DatabaseConnection, IntoActiveModel}; +use serde::{Deserialize, Serialize}; +use serde_json::json; +use uuid::Uuid; +pub fn authentication_router(cfg: &mut web::ServiceConfig) { + cfg.service(create_token); +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct TokenAPISecure { + pub username: String, + pub password: String, +} +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct NewTokenRequest { + pub token_name: Option, +} +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct NewTokenResponse { + pub token: String, + pub token_id: Uuid, + pub expiration: i64, +} + +#[get("/token/list")] +pub async fn list_tokens( + database: web::Data, + login: web::Json, +) -> actix_web::Result { + Ok(HttpResponse::NoContent().finish()) +} +#[post("/token/create")] +pub async fn create_token( + connection: web::Data, + login: web::Json, + new_token: web::Query, +) -> actix_web::Result { + let login = login.into_inner(); + let user: UserModel = verify_login(login.username, login.password, &connection).await??; + let uuid = Uuid::new_v4(); + let string = generate_token(); + let i = token_expiration(Duration::days(31).num_milliseconds()); + let v = super::AuthTokenModel { + id: uuid.clone(), + token: string.clone(), + expiration: i, + properties: TokenProperties { + description: new_token.token_name.clone(), + }, + created: get_current_time(), + user_id: user.id, + }; + super::AuthTokenEntity::insert(v.into_active_model()) + .exec(connection.as_ref()) + .await; + Ok(HttpResponse::Ok().json(NewTokenResponse { + token: string, + token_id: uuid, + expiration: i, + })) +} + +#[delete("/token/{id}")] +pub async fn delete_token( + database: web::Data, + auth: Authentication, +) -> actix_web::Result { + let user: UserModel = auth.get_user(&database).await??; + Ok(HttpResponse::NoContent().finish()) +} diff --git a/backend/src/bin/nitro_repo_full.rs b/backend/src/bin/nitro_repo_full.rs index 78413d6e..9b692dba 100644 --- a/backend/src/bin/nitro_repo_full.rs +++ b/backend/src/bin/nitro_repo_full.rs @@ -18,7 +18,7 @@ use api::storage::local_storage::LocalConfig; use api::storage::multi::MultiStorageController; use api::storage::{GeneralConfig, StorageConfig, StorageSaver, StorageType}; use api::utils::load_logger; -use api::{frontend, repository, storage, system, NitroRepo}; +use api::{authentication, frontend, repository, storage, system, NitroRepo}; use log::info; use semver::Version; use tokio::fs::read_to_string; @@ -109,6 +109,7 @@ async fn main() -> std::io::Result<()> { .wrap(DefaultHeaders::new().add(("Content-Type", "application/json"))) .configure(system::web::init_public_routes) .configure(system::web::user_routes) + .configure(authentication::auth_token::web::authentication_router) .service( web::scope("/admin") .configure(system::web::init_user_manager_routes) diff --git a/nrc/Cargo.toml b/nrc/Cargo.toml new file mode 100644 index 00000000..6515693c --- /dev/null +++ b/nrc/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "nrc" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = { version = "3.2.12", features = ["derive"] } +serde = { version = "1.0.139", features = ["derive"] } +serde_json = "1.0.82" +toml = "0.5.9" +tokio = { version = "1.20.0", features = ["full"] } +reqwest = { version = "0.11.11", features = ["stream", "json"] } +bytes = "1.2.0" +uuid = { version = "1.1.2", features = ["serde"] } +anyhow = { version = "1.0.58" } +style-term = "1.0.0" +inquire = "0.3.0-alpha.2" +directories = "4.0.1" \ No newline at end of file diff --git a/nrc/README.md b/nrc/README.md new file mode 100644 index 00000000..061d4b32 --- /dev/null +++ b/nrc/README.md @@ -0,0 +1,32 @@ +# Nitro Repository CLI + + +## Commands + +### Login +Adds an instance of a Nitro Repository to your local configuration. +``` +nrc login --url --token +``` + +### Maven + +#### `stage` + +### Admin +List Storages +``` +nrc admin --storage list +``` +Show Storage Details +``` +nrc admin --storage +``` +``` +nrc admin --storage new --id --type LocalStorage --path +``` + +Show Repository Details +``` +nrc admin --repository / +``` diff --git a/nrc/src/add.rs b/nrc/src/add.rs new file mode 100644 index 00000000..871aa6b6 --- /dev/null +++ b/nrc/src/add.rs @@ -0,0 +1,77 @@ +use crate::configs::user::RepositoryInstance; +use crate::configs::{get_user_config, save_user_config}; +use crate::Parser; +use inquire::{error::InquireResult, min_length, Confirm, MultiSelect, Password, Select, Text}; +use serde::{Deserialize, Serialize}; +use serde_json::json; +use style_term::DefaultColor::{Green, Red}; +use style_term::{Color, EightBitColor, StyleString}; +use uuid::Uuid; + +#[derive(Debug, Parser)] +pub struct AddInstance { + /// The URL for the Nitro Repository Instance + url: String, + name: String, +} +#[derive(Deserialize, Clone, Debug)] +pub struct NewTokenResponse { + pub token: String, + pub token_id: Uuid, + pub expiration: i64, +} + +impl AddInstance { + pub async fn execute(self) -> anyhow::Result<()> { + let username = Text::new("Username").prompt()?; + let password = Text::new("Password").prompt()?; + let reqwest = reqwest::ClientBuilder::new() + .user_agent("Nitro Repository CLI") + .build() + .unwrap(); + let value = json! ({ + "username": username, + "password": password, + }); + let url = if self.url.ends_with("/") { + self.url.trim_end_matches("/").to_string() + } else { + self.url + }; + println!("{}", url); + let response = reqwest + .post(format!("{}/api/token/create", url)) + .json(&value) + .send() + .await?; + if response.status().is_success() { + let response = response.json::().await?; + println!( + "{}", + format!( + "Token: {}; Token ID {}", + &response.token, &response.token_id + ) + .style() + .text_color(Green) + ); + let mut user_config = get_user_config()?; + let repository = RepositoryInstance { + url, + token: response.token.clone(), + name: self.name.clone(), + token_uuid: response.token_id, + expiration: response.expiration, + }; + user_config.repositories.insert(self.name, repository); + save_user_config(&user_config)?; + } else { + println!( + "{}, Error: {}", + "Failed to add instance".style().text_color(Red), + response.status() + ); + } + Ok(()) + } +} diff --git a/nrc/src/api/mod.rs b/nrc/src/api/mod.rs new file mode 100644 index 00000000..3eb3ed97 --- /dev/null +++ b/nrc/src/api/mod.rs @@ -0,0 +1,51 @@ +use reqwest::header::{HeaderValue, AUTHORIZATION}; +use reqwest::Client; +use serde::{Deserialize, Serialize}; +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct User { + pub id: i64, + pub name: String, + pub username: String, + pub email: String, + pub permissions: UserPermissions, + pub created: i64, +} +impl User { + pub async fn me( + client: &Client, + url: impl AsRef, + auth: &impl Auth, + ) -> anyhow::Result> { + let response = client + .get(format!("{}/api/me", url.as_ref())) + .header(AUTHORIZATION, auth.get_as_header()) + .send() + .await?; + if response.status().is_success() { + let user = response.json::().await?; + Ok(Some(user)) + } else if response.status().eq(&reqwest::StatusCode::UNAUTHORIZED) { + Ok(None) + } else { + Err(anyhow::anyhow!("Failed to get user {}", response.status())) + } + } +} +#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Default)] +pub struct UserPermissions { + pub disabled: bool, + pub admin: bool, + pub user_manager: bool, + pub repository_manager: bool, + pub deployer: Option, + pub viewer: Option, +} + +#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] +pub struct RepositoryPermission { + pub permissions: Vec, +} + +pub trait Auth { + fn get_as_header(&self) -> HeaderValue; +} diff --git a/nrc/src/configs/mod.rs b/nrc/src/configs/mod.rs new file mode 100644 index 00000000..93d0d1ea --- /dev/null +++ b/nrc/src/configs/mod.rs @@ -0,0 +1,44 @@ +use crate::configs::user::UserConfig; +use std::fs::{read_to_string, OpenOptions}; +use std::io::Write; +use tokio::fs::remove_file; + +pub mod user; + +pub fn get_user_config() -> anyhow::Result { + let dir = directories::UserDirs::new() + .unwrap() + .home_dir() + .join(".nrc"); + if !dir.exists() { + std::fs::create_dir_all(&dir)?; + } + let buf = dir.join("config.toml"); + return if !buf.exists() { + let config = UserConfig::default(); + let content = toml::to_string_pretty(&config)?; + OpenOptions::new() + .write(true) + .create(true) + .open(&buf)? + .write_all(content.as_bytes())?; + Ok(config) + } else { + let string = read_to_string(&buf)?; + let config = toml::from_str::(&string)?; + Ok(config) + }; +} + +pub fn save_user_config(config: &UserConfig) -> anyhow::Result<()> { + let file = directories::UserDirs::new() + .unwrap() + .home_dir() + .join(".nrc") + .join("config.toml"); + let mut file = OpenOptions::new().write(true).append(false).open(&file)?; + let content = toml::to_string_pretty(config)?; + + file.write_all(content.as_bytes())?; + Ok(()) +} diff --git a/nrc/src/configs/user.rs b/nrc/src/configs/user.rs new file mode 100644 index 00000000..4757ef86 --- /dev/null +++ b/nrc/src/configs/user.rs @@ -0,0 +1,24 @@ +use crate::api::Auth; +use reqwest::header::HeaderValue; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use uuid::Uuid; + +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +pub struct UserConfig { + #[serde(default)] + pub repositories: HashMap, +} +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct RepositoryInstance { + pub url: String, + pub token: String, + pub name: String, + pub token_uuid: Uuid, + pub expiration: i64, +} +impl Auth for RepositoryInstance { + fn get_as_header(&self) -> HeaderValue { + HeaderValue::from_str(&format!("Bearer {}", self.token)).unwrap() + } +} diff --git a/nrc/src/instances.rs b/nrc/src/instances.rs new file mode 100644 index 00000000..a37bb348 --- /dev/null +++ b/nrc/src/instances.rs @@ -0,0 +1,38 @@ +use crate::api::User; +use crate::configs::user::RepositoryInstance; +use crate::configs::{get_user_config, save_user_config}; +use crate::Parser; +use inquire::{error::InquireResult, min_length, Confirm, MultiSelect, Password, Select, Text}; +use serde::{Deserialize, Serialize}; +use serde_json::json; +use style_term::DefaultColor::{Green, Red}; +use style_term::{Color, EightBitColor, StyleString}; +use uuid::Uuid; + +#[derive(Debug, Parser)] +pub struct Instances { + #[clap(default_value = "false")] + pub skip_login: bool, +} + +impl Instances { + pub async fn execute(self) -> anyhow::Result<()> { + let result = get_user_config()?; + let reqwest = reqwest::ClientBuilder::new() + .user_agent("Nitro Repository CLI") + .build() + .unwrap(); + for (name, instance) in result.repositories { + println!("{}: {}", name, instance.url); + + let option = User::me(&reqwest, instance.url.clone(), &instance).await?; + if let Some(v) = option { + println!("{}", format!("{}", v.username).style().text_color(Green)); + } else { + //TODO remove the instance + println!("{}", "No user found.".style().text_color(Red)); + } + } + Ok(()) + } +} diff --git a/nrc/src/main.rs b/nrc/src/main.rs new file mode 100644 index 00000000..4ddbc3c3 --- /dev/null +++ b/nrc/src/main.rs @@ -0,0 +1,46 @@ +pub mod add; +pub mod api; +pub mod configs; +pub mod instances; + +use crate::add::AddInstance; +use crate::instances::Instances; +use clap::{Parser, Subcommand}; +use std::ffi::OsString; + +#[derive(Debug, Parser)] +#[clap(name = "nrc")] +#[clap(about = "Nitro Repository CLI", long_about = None)] +struct NitroRepositoryCLI { + #[clap(subcommand)] + command: Commands, +} + +#[derive(Debug, Subcommand)] +enum Commands { + /// Adds a Nitro Repository Instance + #[clap(arg_required_else_help = true)] + Login(AddInstance), + Instances(Instances), + #[clap(external_subcommand)] + External(Vec), +} +#[tokio::main] +async fn main() { + let args = NitroRepositoryCLI::parse(); + match args.command { + Commands::Login(login) => { + if let Err(error) = login.execute().await { + println!("{:?}", error); + } + } + Commands::Instances(instances) => { + if let Err(error) = instances.execute().await { + println!("{:?}", error); + } + } + Commands::External(args) => { + println!("{:?}", args); + } + } +} From 5e7793425703c2cfd0477687bb53dfa0c830eeb0 Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Thu, 28 Jul 2022 11:42:29 -0400 Subject: [PATCH 50/76] Depend Updates --- frontend/package-lock.json | 346 ++++++++++++++++++------------------- frontend/package.json | 25 ++- 2 files changed, 176 insertions(+), 195 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 983ef304..c9f9732b 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8,18 +8,17 @@ "name": "site", "version": "1.0.2", "dependencies": { - "@kyvg/vue3-notification": "^2.3.5", + "@kyvg/vue3-notification": "^2.3.6", "@types/webpack-env": "^1.17.0", "@uppy/drag-drop": "^2.1.1", "@uppy/vue": "^0.4.8", "axios": "^0.27.2", "boxicons": "^2.1.2", - "core-js": "^3.23.4", + "core-js": "^3.24.0", "equal-vue": "^0.79.3", "fast-xml-parser": "^4.0.9", - "pinia": "^2.0.16", + "pinia": "^2.0.17", "prismjs": "^1.28.0", - "simple-icons": "^7.4.0", "ts-results": "^3.3.0", "vite-plugin-ejs": "^1.5.0", "vue": "^3.2.37", @@ -29,28 +28,28 @@ "vue-final-modal": "^3.4.3", "vue-meta": "3.0.0-alpha.10", "vue-prism-editor": "^2.0.0-alpha.2", - "vue-router": "^4.1.2", + "vue-router": "^4.1.3", "vue3-cookies": "^1.0.6", - "vue3-simple-icons": "^7.4.0-beta.2" + "vue3-simple-icons": "^7.5.0-beta.1" }, "devDependencies": { "@types/prismjs": "^1.26.0", - "@typescript-eslint/eslint-plugin": "5.30.6", - "@typescript-eslint/parser": "5.30.6", - "@vitejs/plugin-vue": "^3.0.0", + "@typescript-eslint/eslint-plugin": "5.31.0", + "@typescript-eslint/parser": "5.31.0", + "@vitejs/plugin-vue": "^3.0.1", "@vue/compiler-sfc": "^3.2.37", "@vue/eslint-config-prettier": "7.0.0", "@vue/eslint-config-typescript": "11.0.0", "autoprefixer": "^10.4.7", "eslint": "8.20.0", "eslint-plugin-prettier": "4.2.1", - "eslint-plugin-vue": "9.2.0", + "eslint-plugin-vue": "9.3.0", "prettier": "2.7.1", - "sass": "^1.53.0", + "sass": "^1.54.0", "tailwindcss": "^3.1.6", "typescript": "^4.7.4", - "unplugin-vue-components": "^0.21.1", - "vite": "^3.0.0" + "unplugin-vue-components": "^0.21.2", + "vite": "^3.0.3" } }, "../nitro_repo-api-wrapper": { @@ -139,9 +138,9 @@ "dev": true }, "node_modules/@kyvg/vue3-notification": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@kyvg/vue3-notification/-/vue3-notification-2.3.5.tgz", - "integrity": "sha512-OsRDjCGLXOfUZu9dEyxWJuXkCrpQT7o0ZgdFeKYkcqG9MWY544DTZ7hpPIDFoSI9DlK/GS2NSwAb+/R7DABhzQ==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@kyvg/vue3-notification/-/vue3-notification-2.3.6.tgz", + "integrity": "sha512-uQcVOrJIyEYoXLctgJqlj2YPhCaZ80mXgF1xgQZwshqeneNgG08WE8Iw9U3IH8OgUITkRGII0YopdXwLeOXb3w==", "peerDependencies": { "vue": "^3.0.0" } @@ -223,14 +222,14 @@ "integrity": "sha512-eHSaNYEyxRA5IAG0Ym/yCyf86niZUIF/TpWKofQI/CVfh5HsMEUyfE2kwFxha4ow0s5g0LfISQxpDKjbRDrizw==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.30.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.6.tgz", - "integrity": "sha512-J4zYMIhgrx4MgnZrSDD7sEnQp7FmhKNOaqaOpaoQ/SfdMfRB/0yvK74hTnvH+VQxndZynqs5/Hn4t+2/j9bADg==", + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.31.0.tgz", + "integrity": "sha512-VKW4JPHzG5yhYQrQ1AzXgVgX8ZAJEvCz0QI6mLRX4tf7rnFfh5D8SKm0Pq6w5PyNfAWJk6sv313+nEt3ohWMBQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.30.6", - "@typescript-eslint/type-utils": "5.30.6", - "@typescript-eslint/utils": "5.30.6", + "@typescript-eslint/scope-manager": "5.31.0", + "@typescript-eslint/type-utils": "5.31.0", + "@typescript-eslint/utils": "5.31.0", "debug": "^4.3.4", "functional-red-black-tree": "^1.0.1", "ignore": "^5.2.0", @@ -256,14 +255,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.30.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.6.tgz", - "integrity": "sha512-gfF9lZjT0p2ZSdxO70Xbw8w9sPPJGfAdjK7WikEjB3fcUI/yr9maUVEdqigBjKincUYNKOmf7QBMiTf719kbrA==", + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.31.0.tgz", + "integrity": "sha512-UStjQiZ9OFTFReTrN+iGrC6O/ko9LVDhreEK5S3edmXgR396JGq7CoX2TWIptqt/ESzU2iRKXAHfSF2WJFcWHw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.30.6", - "@typescript-eslint/types": "5.30.6", - "@typescript-eslint/typescript-estree": "5.30.6", + "@typescript-eslint/scope-manager": "5.31.0", + "@typescript-eslint/types": "5.31.0", + "@typescript-eslint/typescript-estree": "5.31.0", "debug": "^4.3.4" }, "engines": { @@ -283,13 +282,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.30.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.6.tgz", - "integrity": "sha512-Hkq5PhLgtVoW1obkqYH0i4iELctEKixkhWLPTYs55doGUKCASvkjOXOd/pisVeLdO24ZX9D6yymJ/twqpJiG3g==", + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.31.0.tgz", + "integrity": "sha512-8jfEzBYDBG88rcXFxajdVavGxb5/XKXyvWgvD8Qix3EEJLCFIdVloJw+r9ww0wbyNLOTYyBsR+4ALNGdlalLLg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.30.6", - "@typescript-eslint/visitor-keys": "5.30.6" + "@typescript-eslint/types": "5.31.0", + "@typescript-eslint/visitor-keys": "5.31.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -300,12 +299,12 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.30.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.30.6.tgz", - "integrity": "sha512-GFVVzs2j0QPpM+NTDMXtNmJKlF842lkZKDSanIxf+ArJsGeZUIaeT4jGg+gAgHt7AcQSFwW7htzF/rbAh2jaVA==", + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.31.0.tgz", + "integrity": "sha512-7ZYqFbvEvYXFn9ax02GsPcEOmuWNg+14HIf4q+oUuLnMbpJ6eHAivCg7tZMVwzrIuzX3QCeAOqKoyMZCv5xe+w==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "5.30.6", + "@typescript-eslint/utils": "5.31.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -326,9 +325,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.30.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.6.tgz", - "integrity": "sha512-HdnP8HioL1F7CwVmT4RaaMX57RrfqsOMclZc08wGMiDYJBsLGBM7JwXM4cZJmbWLzIR/pXg1kkrBBVpxTOwfUg==", + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.31.0.tgz", + "integrity": "sha512-/f/rMaEseux+I4wmR6mfpM2wvtNZb1p9hAV77hWfuKc3pmaANp5dLAZSiE3/8oXTYTt3uV9KW5yZKJsMievp6g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -339,13 +338,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.30.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.6.tgz", - "integrity": "sha512-Z7TgPoeYUm06smfEfYF0RBkpF8csMyVnqQbLYiGgmUSTaSXTP57bt8f0UFXstbGxKIreTwQCujtaH0LY9w9B+A==", + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.31.0.tgz", + "integrity": "sha512-3S625TMcARX71wBc2qubHaoUwMEn+l9TCsaIzYI/ET31Xm2c9YQ+zhGgpydjorwQO9pLfR/6peTzS/0G3J/hDw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.30.6", - "@typescript-eslint/visitor-keys": "5.30.6", + "@typescript-eslint/types": "5.31.0", + "@typescript-eslint/visitor-keys": "5.31.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -366,15 +365,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.30.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.30.6.tgz", - "integrity": "sha512-xFBLc/esUbLOJLk9jKv0E9gD/OH966M40aY9jJ8GiqpSkP2xOV908cokJqqhVd85WoIvHVHYXxSFE4cCSDzVvA==", + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.31.0.tgz", + "integrity": "sha512-kcVPdQS6VIpVTQ7QnGNKMFtdJdvnStkqS5LeALr4rcwx11G6OWb2HB17NMPnlRHvaZP38hL9iK8DdE9Fne7NYg==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.30.6", - "@typescript-eslint/types": "5.30.6", - "@typescript-eslint/typescript-estree": "5.30.6", + "@typescript-eslint/scope-manager": "5.31.0", + "@typescript-eslint/types": "5.31.0", + "@typescript-eslint/typescript-estree": "5.31.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, @@ -390,12 +389,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.30.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.6.tgz", - "integrity": "sha512-41OiCjdL2mCaSDi2SvYbzFLlqqlm5v1ZW9Ym55wXKL/Rx6OOB1IbuFGo71Fj6Xy90gJDFTlgOS+vbmtGHPTQQA==", + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.31.0.tgz", + "integrity": "sha512-ZK0jVxSjS4gnPirpVjXHz7mgdOsZUHzNYSfTw2yPa3agfbt9YfqaBiBZFSSxeBWnpWkzCxTfUpnzA3Vily/CSg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.30.6", + "@typescript-eslint/types": "5.31.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -564,12 +563,12 @@ } }, "node_modules/@vitejs/plugin-vue": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-3.0.0.tgz", - "integrity": "sha512-yWP34ArFh/jAeNUDkkLz/kVRLjf5ppJiq4L36f64Cp6dIrMQeYZGDP9xxdemlXfZR9ylN9JgHUl3GzfqOtgYDg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-3.0.1.tgz", + "integrity": "sha512-Ll9JgxG7ONIz/XZv3dssfoMUDu9qAnlJ+km+pBA0teYSXzwPCIzS/e1bmwNYl5dcQGs677D21amgfYAnzMl17A==", "dev": true, "engines": { - "node": ">=14.18.0" + "node": "^14.18.0 || >=16.0.0" }, "peerDependencies": { "vite": "^3.0.0", @@ -623,9 +622,9 @@ } }, "node_modules/@vue/devtools-api": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.2.0.tgz", - "integrity": "sha512-pF1G4wky+hkifDiZSWn8xfuLOJI1ZXtuambpBEYaf7Xaf6zC/pM29rvAGpd3qaGXnr4BAXU1Pxz/VfvBGwexGA==" + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.2.1.tgz", + "integrity": "sha512-OEgAMeQXvCoJ+1x8WyQuVZzFo0wcyCmUR3baRVLmKBo1LmYZWMlRiXlux5jd0fqVJu6PfDbOrZItVqUEzLobeQ==" }, "node_modules/@vue/eslint-config-prettier": { "version": "7.0.0", @@ -1273,9 +1272,9 @@ } }, "node_modules/core-js": { - "version": "3.23.4", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.23.4.tgz", - "integrity": "sha512-vjsKqRc1RyAJC3Ye2kYqgfdThb3zYnx9CrqoCcjMOENMtQPC7ZViBvlDxwYU/2z2NI/IPuiXw5mT4hWhddqjzQ==", + "version": "3.24.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.24.0.tgz", + "integrity": "sha512-IeOyT8A6iK37Ep4kZDD423mpi6JfPRoPUdQwEWYiGolvn4o6j2diaRzNfDfpTdu3a5qMbrGUzKUpYpRY8jXCkQ==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -1955,9 +1954,9 @@ } }, "node_modules/eslint-plugin-vue": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.2.0.tgz", - "integrity": "sha512-W2hc+NUXoce8sZtWgZ45miQTy6jNyuSdub5aZ1IBune4JDeAyzucYX0TzkrQ1jMO52sNUDYlCIHDoaNePe0p5g==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.3.0.tgz", + "integrity": "sha512-iscKKkBZgm6fGZwFt6poRoWC0Wy2dQOlwUPW++CiPoQiw1enctV2Hj5DBzzjJZfyqs+FAXhgzL4q0Ww03AgSmQ==", "dev": true, "dependencies": { "eslint-utils": "^3.0.0", @@ -3094,11 +3093,11 @@ } }, "node_modules/pinia": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.16.tgz", - "integrity": "sha512-9/LMVO+/epny1NBfC77vnps4g3JRezxhhoF1xLUk8mZkUIxVnwfEAIRiAX8mYBTD/KCwZqnDMqXc8w3eU0FQGg==", + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.17.tgz", + "integrity": "sha512-AtwLwEWQgIjofjgeFT+nxbnK5lT2QwQjaHNEDqpsi2AiCwf/NY78uWTeHUyEhiiJy8+sBmw0ujgQMoQbWiZDfA==", "dependencies": { - "@vue/devtools-api": "^6.1.4", + "@vue/devtools-api": "^6.2.1", "vue-demi": "*" }, "funding": { @@ -3626,9 +3625,9 @@ } }, "node_modules/sass": { - "version": "1.53.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.53.0.tgz", - "integrity": "sha512-zb/oMirbKhUgRQ0/GFz8TSAwRq2IlR29vOUJZOx0l8sV+CkHUfHa4u5nqrG+1VceZp7Jfj59SVW9ogdhTvJDcQ==", + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.54.0.tgz", + "integrity": "sha512-C4zp79GCXZfK0yoHZg+GxF818/aclhp9F48XBu/+bm9vXEVAYov9iU3FBVRMq3Hx3OA4jfKL+p2K9180mEh0xQ==", "dev": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", @@ -3698,18 +3697,6 @@ "node": ">=8" } }, - "node_modules/simple-icons": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/simple-icons/-/simple-icons-7.4.0.tgz", - "integrity": "sha512-sUp30aZ1TvM1uIXtdRKX3yX5y2sN9I1AJlA5UkVSCX3pYZgd38HaZBxGVcxYijv+Qy8p+jzkYsJAZ+ao3Js7Mg==", - "engines": { - "node": ">=0.12.18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/simple-icons" - } - }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -3994,9 +3981,9 @@ } }, "node_modules/unplugin-vue-components": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-0.21.1.tgz", - "integrity": "sha512-8MhIT323q1EUu7rz6NfQeiHqDrZKtygy6s9jzcQAuuZUM2T38SHlPT5YJjBOZmM0Bau6YuNTKfBBX4iHzeusaQ==", + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-0.21.2.tgz", + "integrity": "sha512-HBU+EuesDj/HRs7EtYH7gBACljVhqLylltrCLModRmCToIIrrNvMh54aylUt4AD4qiwylgOx4Vgb9sBlrIcRDw==", "dev": true, "dependencies": { "@antfu/utils": "^0.5.2", @@ -4004,11 +3991,11 @@ "chokidar": "^3.5.3", "debug": "^4.3.4", "fast-glob": "^3.2.11", - "local-pkg": "^0.4.1", + "local-pkg": "^0.4.2", "magic-string": "^0.26.2", "minimatch": "^5.1.0", "resolve": "^1.22.1", - "unplugin": "^0.7.1" + "unplugin": "^0.7.2" }, "engines": { "node": ">=14" @@ -4112,9 +4099,9 @@ "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" }, "node_modules/vite": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.0.0.tgz", - "integrity": "sha512-M7phQhY3+fRZa0H+1WzI6N+/onruwPTBTMvaj7TzgZ0v2TE+N2sdLKxJOfOv9CckDWt5C4HmyQP81xB4dwRKzA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.0.3.tgz", + "integrity": "sha512-sDIpIcl3mv1NUaSzZwiXGEy1ZoWwwC2vkxUHY6yiDacR6zf//ZFuBJrozO62gedpE43pmxnLATNR5IYUdAEkMQ==", "dev": true, "dependencies": { "esbuild": "^0.14.47", @@ -4126,7 +4113,7 @@ "vite": "bin/vite.js" }, "engines": { - "node": ">=14.18.0" + "node": "^14.18.0 || >=16.0.0" }, "optionalDependencies": { "fsevents": "~2.3.2" @@ -4268,9 +4255,9 @@ } }, "node_modules/vue-router": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.2.tgz", - "integrity": "sha512-5BP1qXFncVRwgV/XnqzsKApdMjQPqWIpoUBdL1ynz8HyLxIX/UDAx7Ql2BjmA5CXT/p61JfZvkpiFWFpaqcfag==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.3.tgz", + "integrity": "sha512-XvK81bcYglKiayT7/vYAg/f36ExPC4t90R/HIpzrZ5x+17BOWptXLCrEPufGgZeuq68ww4ekSIMBZY1qdUdfjA==", "dependencies": { "@vue/devtools-api": "^6.1.4" }, @@ -4290,9 +4277,9 @@ } }, "node_modules/vue3-simple-icons": { - "version": "7.4.0-beta.2", - "resolved": "https://registry.npmjs.org/vue3-simple-icons/-/vue3-simple-icons-7.4.0-beta.2.tgz", - "integrity": "sha512-3Y66vlEaQ638kFcqXgv2FqMPC3E0G4BxyqQ8cCS7iya/Uijp/l9uTTXRDWiK1gB09sSnaqXW72VStCN8bw+IwQ==", + "version": "7.5.0-beta.1", + "resolved": "https://registry.npmjs.org/vue3-simple-icons/-/vue3-simple-icons-7.5.0-beta.1.tgz", + "integrity": "sha512-ODA85cY3Wj8WDQNfj6oP6J2ZWmJUc+536YxzXlmkX0IsmmtKY3u+zxfWdD34Q4KdvH0IaxLHUktNSa2ydUU4ww==", "dependencies": { "vue": "^3.0.0" } @@ -4506,9 +4493,9 @@ "dev": true }, "@kyvg/vue3-notification": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@kyvg/vue3-notification/-/vue3-notification-2.3.5.tgz", - "integrity": "sha512-OsRDjCGLXOfUZu9dEyxWJuXkCrpQT7o0ZgdFeKYkcqG9MWY544DTZ7hpPIDFoSI9DlK/GS2NSwAb+/R7DABhzQ==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@kyvg/vue3-notification/-/vue3-notification-2.3.6.tgz", + "integrity": "sha512-uQcVOrJIyEYoXLctgJqlj2YPhCaZ80mXgF1xgQZwshqeneNgG08WE8Iw9U3IH8OgUITkRGII0YopdXwLeOXb3w==", "requires": {} }, "@nodelib/fs.scandir": { @@ -4576,14 +4563,14 @@ "integrity": "sha512-eHSaNYEyxRA5IAG0Ym/yCyf86niZUIF/TpWKofQI/CVfh5HsMEUyfE2kwFxha4ow0s5g0LfISQxpDKjbRDrizw==" }, "@typescript-eslint/eslint-plugin": { - "version": "5.30.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.6.tgz", - "integrity": "sha512-J4zYMIhgrx4MgnZrSDD7sEnQp7FmhKNOaqaOpaoQ/SfdMfRB/0yvK74hTnvH+VQxndZynqs5/Hn4t+2/j9bADg==", + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.31.0.tgz", + "integrity": "sha512-VKW4JPHzG5yhYQrQ1AzXgVgX8ZAJEvCz0QI6mLRX4tf7rnFfh5D8SKm0Pq6w5PyNfAWJk6sv313+nEt3ohWMBQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.30.6", - "@typescript-eslint/type-utils": "5.30.6", - "@typescript-eslint/utils": "5.30.6", + "@typescript-eslint/scope-manager": "5.31.0", + "@typescript-eslint/type-utils": "5.31.0", + "@typescript-eslint/utils": "5.31.0", "debug": "^4.3.4", "functional-red-black-tree": "^1.0.1", "ignore": "^5.2.0", @@ -4593,52 +4580,52 @@ } }, "@typescript-eslint/parser": { - "version": "5.30.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.6.tgz", - "integrity": "sha512-gfF9lZjT0p2ZSdxO70Xbw8w9sPPJGfAdjK7WikEjB3fcUI/yr9maUVEdqigBjKincUYNKOmf7QBMiTf719kbrA==", + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.31.0.tgz", + "integrity": "sha512-UStjQiZ9OFTFReTrN+iGrC6O/ko9LVDhreEK5S3edmXgR396JGq7CoX2TWIptqt/ESzU2iRKXAHfSF2WJFcWHw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.30.6", - "@typescript-eslint/types": "5.30.6", - "@typescript-eslint/typescript-estree": "5.30.6", + "@typescript-eslint/scope-manager": "5.31.0", + "@typescript-eslint/types": "5.31.0", + "@typescript-eslint/typescript-estree": "5.31.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.30.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.6.tgz", - "integrity": "sha512-Hkq5PhLgtVoW1obkqYH0i4iELctEKixkhWLPTYs55doGUKCASvkjOXOd/pisVeLdO24ZX9D6yymJ/twqpJiG3g==", + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.31.0.tgz", + "integrity": "sha512-8jfEzBYDBG88rcXFxajdVavGxb5/XKXyvWgvD8Qix3EEJLCFIdVloJw+r9ww0wbyNLOTYyBsR+4ALNGdlalLLg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.30.6", - "@typescript-eslint/visitor-keys": "5.30.6" + "@typescript-eslint/types": "5.31.0", + "@typescript-eslint/visitor-keys": "5.31.0" } }, "@typescript-eslint/type-utils": { - "version": "5.30.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.30.6.tgz", - "integrity": "sha512-GFVVzs2j0QPpM+NTDMXtNmJKlF842lkZKDSanIxf+ArJsGeZUIaeT4jGg+gAgHt7AcQSFwW7htzF/rbAh2jaVA==", + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.31.0.tgz", + "integrity": "sha512-7ZYqFbvEvYXFn9ax02GsPcEOmuWNg+14HIf4q+oUuLnMbpJ6eHAivCg7tZMVwzrIuzX3QCeAOqKoyMZCv5xe+w==", "dev": true, "requires": { - "@typescript-eslint/utils": "5.30.6", + "@typescript-eslint/utils": "5.31.0", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.30.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.6.tgz", - "integrity": "sha512-HdnP8HioL1F7CwVmT4RaaMX57RrfqsOMclZc08wGMiDYJBsLGBM7JwXM4cZJmbWLzIR/pXg1kkrBBVpxTOwfUg==", + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.31.0.tgz", + "integrity": "sha512-/f/rMaEseux+I4wmR6mfpM2wvtNZb1p9hAV77hWfuKc3pmaANp5dLAZSiE3/8oXTYTt3uV9KW5yZKJsMievp6g==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.30.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.6.tgz", - "integrity": "sha512-Z7TgPoeYUm06smfEfYF0RBkpF8csMyVnqQbLYiGgmUSTaSXTP57bt8f0UFXstbGxKIreTwQCujtaH0LY9w9B+A==", + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.31.0.tgz", + "integrity": "sha512-3S625TMcARX71wBc2qubHaoUwMEn+l9TCsaIzYI/ET31Xm2c9YQ+zhGgpydjorwQO9pLfR/6peTzS/0G3J/hDw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.30.6", - "@typescript-eslint/visitor-keys": "5.30.6", + "@typescript-eslint/types": "5.31.0", + "@typescript-eslint/visitor-keys": "5.31.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -4647,26 +4634,26 @@ } }, "@typescript-eslint/utils": { - "version": "5.30.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.30.6.tgz", - "integrity": "sha512-xFBLc/esUbLOJLk9jKv0E9gD/OH966M40aY9jJ8GiqpSkP2xOV908cokJqqhVd85WoIvHVHYXxSFE4cCSDzVvA==", + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.31.0.tgz", + "integrity": "sha512-kcVPdQS6VIpVTQ7QnGNKMFtdJdvnStkqS5LeALr4rcwx11G6OWb2HB17NMPnlRHvaZP38hL9iK8DdE9Fne7NYg==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.30.6", - "@typescript-eslint/types": "5.30.6", - "@typescript-eslint/typescript-estree": "5.30.6", + "@typescript-eslint/scope-manager": "5.31.0", + "@typescript-eslint/types": "5.31.0", + "@typescript-eslint/typescript-estree": "5.31.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" } }, "@typescript-eslint/visitor-keys": { - "version": "5.30.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.6.tgz", - "integrity": "sha512-41OiCjdL2mCaSDi2SvYbzFLlqqlm5v1ZW9Ym55wXKL/Rx6OOB1IbuFGo71Fj6Xy90gJDFTlgOS+vbmtGHPTQQA==", + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.31.0.tgz", + "integrity": "sha512-ZK0jVxSjS4gnPirpVjXHz7mgdOsZUHzNYSfTw2yPa3agfbt9YfqaBiBZFSSxeBWnpWkzCxTfUpnzA3Vily/CSg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.30.6", + "@typescript-eslint/types": "5.31.0", "eslint-visitor-keys": "^3.3.0" } }, @@ -4800,9 +4787,9 @@ } }, "@vitejs/plugin-vue": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-3.0.0.tgz", - "integrity": "sha512-yWP34ArFh/jAeNUDkkLz/kVRLjf5ppJiq4L36f64Cp6dIrMQeYZGDP9xxdemlXfZR9ylN9JgHUl3GzfqOtgYDg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-3.0.1.tgz", + "integrity": "sha512-Ll9JgxG7ONIz/XZv3dssfoMUDu9qAnlJ+km+pBA0teYSXzwPCIzS/e1bmwNYl5dcQGs677D21amgfYAnzMl17A==", "dev": true, "requires": {} }, @@ -4853,9 +4840,9 @@ } }, "@vue/devtools-api": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.2.0.tgz", - "integrity": "sha512-pF1G4wky+hkifDiZSWn8xfuLOJI1ZXtuambpBEYaf7Xaf6zC/pM29rvAGpd3qaGXnr4BAXU1Pxz/VfvBGwexGA==" + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.2.1.tgz", + "integrity": "sha512-OEgAMeQXvCoJ+1x8WyQuVZzFo0wcyCmUR3baRVLmKBo1LmYZWMlRiXlux5jd0fqVJu6PfDbOrZItVqUEzLobeQ==" }, "@vue/eslint-config-prettier": { "version": "7.0.0", @@ -5300,9 +5287,9 @@ "optional": true }, "core-js": { - "version": "3.23.4", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.23.4.tgz", - "integrity": "sha512-vjsKqRc1RyAJC3Ye2kYqgfdThb3zYnx9CrqoCcjMOENMtQPC7ZViBvlDxwYU/2z2NI/IPuiXw5mT4hWhddqjzQ==" + "version": "3.24.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.24.0.tgz", + "integrity": "sha512-IeOyT8A6iK37Ep4kZDD423mpi6JfPRoPUdQwEWYiGolvn4o6j2diaRzNfDfpTdu3a5qMbrGUzKUpYpRY8jXCkQ==" }, "cross-spawn": { "version": "7.0.3", @@ -5732,9 +5719,9 @@ } }, "eslint-plugin-vue": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.2.0.tgz", - "integrity": "sha512-W2hc+NUXoce8sZtWgZ45miQTy6jNyuSdub5aZ1IBune4JDeAyzucYX0TzkrQ1jMO52sNUDYlCIHDoaNePe0p5g==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.3.0.tgz", + "integrity": "sha512-iscKKkBZgm6fGZwFt6poRoWC0Wy2dQOlwUPW++CiPoQiw1enctV2Hj5DBzzjJZfyqs+FAXhgzL4q0Ww03AgSmQ==", "dev": true, "requires": { "eslint-utils": "^3.0.0", @@ -6590,11 +6577,11 @@ "dev": true }, "pinia": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.16.tgz", - "integrity": "sha512-9/LMVO+/epny1NBfC77vnps4g3JRezxhhoF1xLUk8mZkUIxVnwfEAIRiAX8mYBTD/KCwZqnDMqXc8w3eU0FQGg==", + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.17.tgz", + "integrity": "sha512-AtwLwEWQgIjofjgeFT+nxbnK5lT2QwQjaHNEDqpsi2AiCwf/NY78uWTeHUyEhiiJy8+sBmw0ujgQMoQbWiZDfA==", "requires": { - "@vue/devtools-api": "^6.1.4", + "@vue/devtools-api": "^6.2.1", "vue-demi": "*" }, "dependencies": { @@ -6908,9 +6895,9 @@ } }, "sass": { - "version": "1.53.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.53.0.tgz", - "integrity": "sha512-zb/oMirbKhUgRQ0/GFz8TSAwRq2IlR29vOUJZOx0l8sV+CkHUfHa4u5nqrG+1VceZp7Jfj59SVW9ogdhTvJDcQ==", + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.54.0.tgz", + "integrity": "sha512-C4zp79GCXZfK0yoHZg+GxF818/aclhp9F48XBu/+bm9vXEVAYov9iU3FBVRMq3Hx3OA4jfKL+p2K9180mEh0xQ==", "dev": true, "requires": { "chokidar": ">=3.0.0 <4.0.0", @@ -6962,11 +6949,6 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, - "simple-icons": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/simple-icons/-/simple-icons-7.4.0.tgz", - "integrity": "sha512-sUp30aZ1TvM1uIXtdRKX3yX5y2sN9I1AJlA5UkVSCX3pYZgd38HaZBxGVcxYijv+Qy8p+jzkYsJAZ+ao3Js7Mg==" - }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -7163,9 +7145,9 @@ } }, "unplugin-vue-components": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-0.21.1.tgz", - "integrity": "sha512-8MhIT323q1EUu7rz6NfQeiHqDrZKtygy6s9jzcQAuuZUM2T38SHlPT5YJjBOZmM0Bau6YuNTKfBBX4iHzeusaQ==", + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-0.21.2.tgz", + "integrity": "sha512-HBU+EuesDj/HRs7EtYH7gBACljVhqLylltrCLModRmCToIIrrNvMh54aylUt4AD4qiwylgOx4Vgb9sBlrIcRDw==", "dev": true, "requires": { "@antfu/utils": "^0.5.2", @@ -7173,11 +7155,11 @@ "chokidar": "^3.5.3", "debug": "^4.3.4", "fast-glob": "^3.2.11", - "local-pkg": "^0.4.1", + "local-pkg": "^0.4.2", "magic-string": "^0.26.2", "minimatch": "^5.1.0", "resolve": "^1.22.1", - "unplugin": "^0.7.1" + "unplugin": "^0.7.2" }, "dependencies": { "brace-expansion": { @@ -7246,9 +7228,9 @@ "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" }, "vite": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.0.0.tgz", - "integrity": "sha512-M7phQhY3+fRZa0H+1WzI6N+/onruwPTBTMvaj7TzgZ0v2TE+N2sdLKxJOfOv9CckDWt5C4HmyQP81xB4dwRKzA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.0.3.tgz", + "integrity": "sha512-sDIpIcl3mv1NUaSzZwiXGEy1ZoWwwC2vkxUHY6yiDacR6zf//ZFuBJrozO62gedpE43pmxnLATNR5IYUdAEkMQ==", "dev": true, "requires": { "esbuild": "^0.14.47", @@ -7347,9 +7329,9 @@ "requires": {} }, "vue-router": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.2.tgz", - "integrity": "sha512-5BP1qXFncVRwgV/XnqzsKApdMjQPqWIpoUBdL1ynz8HyLxIX/UDAx7Ql2BjmA5CXT/p61JfZvkpiFWFpaqcfag==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.3.tgz", + "integrity": "sha512-XvK81bcYglKiayT7/vYAg/f36ExPC4t90R/HIpzrZ5x+17BOWptXLCrEPufGgZeuq68ww4ekSIMBZY1qdUdfjA==", "requires": { "@vue/devtools-api": "^6.1.4" } @@ -7363,9 +7345,9 @@ } }, "vue3-simple-icons": { - "version": "7.4.0-beta.2", - "resolved": "https://registry.npmjs.org/vue3-simple-icons/-/vue3-simple-icons-7.4.0-beta.2.tgz", - "integrity": "sha512-3Y66vlEaQ638kFcqXgv2FqMPC3E0G4BxyqQ8cCS7iya/Uijp/l9uTTXRDWiK1gB09sSnaqXW72VStCN8bw+IwQ==", + "version": "7.5.0-beta.1", + "resolved": "https://registry.npmjs.org/vue3-simple-icons/-/vue3-simple-icons-7.5.0-beta.1.tgz", + "integrity": "sha512-ODA85cY3Wj8WDQNfj6oP6J2ZWmJUc+536YxzXlmkX0IsmmtKY3u+zxfWdD34Q4KdvH0IaxLHUktNSa2ydUU4ww==", "requires": { "vue": "^3.0.0" } diff --git a/frontend/package.json b/frontend/package.json index 078fd6ca..7b23a80a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,18 +10,17 @@ "lint": "eslint src/**/*.{ts,vue}" }, "dependencies": { - "@kyvg/vue3-notification": "^2.3.5", + "@kyvg/vue3-notification": "^2.3.6", "@types/webpack-env": "^1.17.0", "@uppy/drag-drop": "^2.1.1", "@uppy/vue": "^0.4.8", "axios": "^0.27.2", "boxicons": "^2.1.2", - "core-js": "^3.23.4", + "core-js": "^3.24.0", "equal-vue": "^0.79.3", "fast-xml-parser": "^4.0.9", - "pinia": "^2.0.16", + "pinia": "^2.0.17", "prismjs": "^1.28.0", - "simple-icons": "^7.4.0", "ts-results": "^3.3.0", "vite-plugin-ejs": "^1.5.0", "vue": "^3.2.37", @@ -31,27 +30,27 @@ "vue-final-modal": "^3.4.3", "vue-meta": "3.0.0-alpha.10", "vue-prism-editor": "^2.0.0-alpha.2", - "vue-router": "^4.1.2", + "vue-router": "^4.1.3", "vue3-cookies": "^1.0.6", - "vue3-simple-icons": "^7.4.0-beta.2" + "vue3-simple-icons": "^7.5.0-beta.1" }, "devDependencies": { "@types/prismjs": "^1.26.0", - "@typescript-eslint/eslint-plugin": "5.30.6", - "@typescript-eslint/parser": "5.30.6", - "@vitejs/plugin-vue": "^3.0.0", + "@typescript-eslint/eslint-plugin": "5.31.0", + "@typescript-eslint/parser": "5.31.0", + "@vitejs/plugin-vue": "^3.0.1", "autoprefixer": "^10.4.7", "@vue/compiler-sfc": "^3.2.37", "@vue/eslint-config-prettier": "7.0.0", "@vue/eslint-config-typescript": "11.0.0", "eslint": "8.20.0", "eslint-plugin-prettier": "4.2.1", - "eslint-plugin-vue": "9.2.0", + "eslint-plugin-vue": "9.3.0", "prettier": "2.7.1", - "sass": "^1.53.0", + "sass": "^1.54.0", "tailwindcss": "^3.1.6", "typescript": "^4.7.4", - "unplugin-vue-components": "^0.21.1", - "vite": "^3.0.0" + "unplugin-vue-components": "^0.21.2", + "vite": "^3.0.3" } } From e63e393b7882d344d1779be9df24484a0f23001c Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Thu, 28 Jul 2022 20:30:51 -0400 Subject: [PATCH 51/76] Stops Querying the password every database user request. Changed the Token Database a bit. --- backend/Cargo.toml | 14 ++-- .../src/authentication/auth_token/database.rs | 16 +++-- backend/src/authentication/auth_token/mod.rs | 67 ++++++++--------- .../src/authentication/auth_token/web/mod.rs | 72 ++++++++++--------- backend/src/authentication/middleware.rs | 40 ++++++----- backend/src/authentication/mod.rs | 48 ++++++++++--- backend/src/bin/nitro_repo_full.rs | 4 +- backend/src/repository/handler.rs | 2 +- backend/src/repository/maven/hosted.rs | 4 +- backend/src/repository/maven/mod.rs | 1 + backend/src/repository/maven/proxy.rs | 2 +- .../src/repository/maven/staging/external.rs | 3 +- backend/src/repository/maven/staging/git.rs | 4 +- backend/src/repository/maven/staging/mod.rs | 7 +- backend/src/repository/nitro/dynamic.rs | 2 +- .../src/repository/nitro/nitro_repository.rs | 4 +- backend/src/repository/npm/mod.rs | 4 +- backend/src/repository/staging/dynamic.rs | 2 +- backend/src/repository/staging/mod.rs | 3 +- backend/src/repository/web/multi/admin.rs | 15 ++-- backend/src/repository/web/multi/configs.rs | 4 +- .../repository/web/multi/public/project.rs | 2 +- .../web/multi/public/repositories.rs | 5 +- .../web/multi/repository_handler.rs | 2 +- backend/src/storage/multi/web/admin.rs | 8 +-- backend/src/system/mod.rs | 8 +-- backend/src/system/permissions/options.rs | 58 +++++++++++++++ backend/src/system/permissions/orm.rs | 8 ++- backend/src/system/user/database.rs | 29 ++++++++ backend/src/system/user/mod.rs | 12 +++- backend/src/system/web/admin.rs | 8 ++- backend/src/system/web/mod.rs | 2 +- backend/src/system/web/user.rs | 34 +++++++-- 33 files changed, 328 insertions(+), 166 deletions(-) diff --git a/backend/Cargo.toml b/backend/Cargo.toml index aa3f9c83..5b3fae80 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -18,17 +18,17 @@ name = "simple_installer" [dependencies] # Web -actix-web = { version = "4.1.0", features = ["openssl", "cookies"] } -actix-cors = "0.6.1" -actix-service = "2.0.2" -openssl = { version = "0.10.41", features = ["v110"], optional = true } -actix-files = "0.6.1" +actix-web = { version = "4.1", features = ["openssl", "cookies"] } +actix-cors = "0.6" +actix-service = "2.0" +openssl = { version = "0.10", features = ["v110"], optional = true } +actix-files = "0.6" # Partly Web lettre = "0.10.0" handlebars = "4.3.2" # Database -sea-orm = { version = "0.9.0", features = ["sqlx-mysql", "sqlx-sqlite", "runtime-actix-native-tls", "macros"] } -sqlx = "0.6.0" +sea-orm = { version = "0.9", features = ["sqlx-mysql", "sqlx-sqlite", "runtime-actix-native-tls", "macros"] } +sqlx = "0.6" # Serde serde = { version = "1.0.139", features = ["derive"] } serde_json = "1.0.82" diff --git a/backend/src/authentication/auth_token/database.rs b/backend/src/authentication/auth_token/database.rs index d4ba69fd..ae48c538 100644 --- a/backend/src/authentication/auth_token/database.rs +++ b/backend/src/authentication/auth_token/database.rs @@ -8,6 +8,7 @@ use sea_orm::entity::prelude::*; use sea_orm::JsonValue; use serde::{Deserialize, Serialize}; +use crate::system::user::database::UserSafeData; use crate::system::user::{UserEntity, UserModel}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -63,21 +64,24 @@ impl sea_orm::sea_query::ValueType for TokenProperties { #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] #[sea_orm(table_name = "auth_tokens")] pub struct Model { - #[sea_orm(primary_key)] + #[sea_orm(primary_key, auto_increment = false)] pub id: Uuid, - pub token: String, - pub expiration: i64, + pub token_hash: String, + pub token_last_eight: String, pub properties: TokenProperties, - pub created: i64, pub user_id: i64, + pub created: i64, } impl Model { pub async fn get_user( &self, database: &DatabaseConnection, - ) -> Result, DbErr> { - UserEntity::find_by_id(self.user_id).one(database).await + ) -> Result, DbErr> { + UserEntity::find_by_id(self.user_id) + .into_model() + .one(database) + .await } } diff --git a/backend/src/authentication/auth_token/mod.rs b/backend/src/authentication/auth_token/mod.rs index 39df6caa..4e3042b4 100644 --- a/backend/src/authentication/auth_token/mod.rs +++ b/backend/src/authentication/auth_token/mod.rs @@ -4,6 +4,8 @@ pub mod web; use crate::authentication::auth_token::database::TokenProperties; use crate::error::internal_error::InternalError; use crate::utils::get_current_time; +use argon2::{Argon2, PasswordHash, PasswordVerifier}; +pub use database::ActiveModel as ActiveAuthTokenModel; pub use database::Entity as AuthTokenEntity; pub use database::Model as AuthTokenModel; use log::error; @@ -16,10 +18,9 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize, FromQueryResult)] pub struct TokenResponse { pub id: i64, - pub expiration: i64, pub properties: TokenProperties, - pub created: i64, pub user_id: i64, + pub created: i64, } pub async fn get_tokens_by_user( @@ -33,52 +34,46 @@ pub async fn get_tokens_by_user( .await .map_err(InternalError::DBError) } - -pub async fn get_by_token( - token: &str, +/// 0 = no user. i64 is cheaper than Option +pub async fn get_token( + user_id: i64, + token: impl AsRef, connection: &DatabaseConnection, ) -> Result, InternalError> { + let (_, end) = token.as_ref().split_at(token.as_ref().len() - 8); + let mut expr = database::Column::TokenLastEight.eq(end); + if user_id != 0 { + expr = expr.and(database::Column::UserId.eq(user_id)) + } let result = database::Entity::find() - .filter(database::Column::Token.eq(token)) - .one(connection) + .filter(expr) + .all(connection) .await?; - if let Some(token) = result { - // Delete Token if Expired - if token.expiration <= get_current_time() { - let database = connection.clone(); - actix_web::rt::spawn(async move { - let database = database; - if let Err(error) = AuthTokenEntity::delete_by_id(token.id) - .exec(&database) - .await - { - error!("Unable to delete Auth Token Error: {}", error); - } - }); + let option = result.into_iter().find(|v| { + let argon2 = Argon2::default(); + if let Ok(hash) = PasswordHash::new(v.token_hash.as_str()) { + if argon2 + .verify_password(token.as_ref().as_bytes(), &hash) + .is_err() + { + return false; + } else { + true + } + } else { + false } - return Ok(Some(token)); - } - Ok(None) -} - -pub async fn delete_by_token( - token: &str, - connection: &DatabaseConnection, -) -> Result<(), InternalError> { - database::Entity::delete_many() - .filter(database::Column::Token.eq(token)) - .exec(connection) - .await?; - Ok(()) + }); + Ok(option) } pub fn generate_token() -> String { let token: String = rand::thread_rng() .sample_iter(&Alphanumeric) - .take(24) + .take(40) .map(char::from) .collect(); - format!("nrp_{}", token) + token } pub fn token_expiration(add: i64) -> i64 { diff --git a/backend/src/authentication/auth_token/web/mod.rs b/backend/src/authentication/auth_token/web/mod.rs index 592de000..a3d2b2f5 100644 --- a/backend/src/authentication/auth_token/web/mod.rs +++ b/backend/src/authentication/auth_token/web/mod.rs @@ -1,75 +1,77 @@ use crate::authentication::auth_token::database::TokenProperties; -use crate::authentication::auth_token::{generate_token, token_expiration}; -use crate::authentication::{verify_login, Authentication}; +use crate::authentication::auth_token::{ + generate_token, token_expiration, ActiveAuthTokenModel, AuthTokenEntity, AuthTokenModel, +}; +use crate::authentication::{verify_login, Authentication, SecureAction}; +use crate::system::hash; use crate::system::user::UserModel; use crate::utils::get_current_time; +use actix_web::error::ErrorInternalServerError; use actix_web::http::StatusCode; use actix_web::web; use actix_web::{delete, get, post, HttpRequest, HttpResponse}; use chrono::Duration; use log::error; use sea_orm::ActiveValue::Set; -use sea_orm::EntityTrait; +use sea_orm::{ColumnTrait, EntityTrait, QueryFilter}; use sea_orm::{DatabaseConnection, IntoActiveModel}; use serde::{Deserialize, Serialize}; use serde_json::json; use uuid::Uuid; + pub fn authentication_router(cfg: &mut web::ServiceConfig) { cfg.service(create_token); } -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct TokenAPISecure { - pub username: String, - pub password: String, -} -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct NewTokenRequest { - pub token_name: Option, -} #[derive(Serialize, Deserialize, Clone, Debug)] pub struct NewTokenResponse { pub token: String, pub token_id: Uuid, +} +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct TokenResponse { pub expiration: i64, + pub properties: TokenProperties, + pub created: i64, } - #[get("/token/list")] pub async fn list_tokens( database: web::Data, - login: web::Json, + login: web::Json>, ) -> actix_web::Result { Ok(HttpResponse::NoContent().finish()) } + #[post("/token/create")] pub async fn create_token( connection: web::Data, - login: web::Json, - new_token: web::Query, + login: web::Json>>, ) -> actix_web::Result { let login = login.into_inner(); - let user: UserModel = verify_login(login.username, login.password, &connection).await??; + let user = login.verify(connection.get_ref()).await??; + let token = generate_token(); + let hash = hash(&token)?; + let token_last_eight = token.split_at(token.len() - 8).1.to_string(); let uuid = Uuid::new_v4(); - let string = generate_token(); - let i = token_expiration(Duration::days(31).num_milliseconds()); - let v = super::AuthTokenModel { - id: uuid.clone(), - token: string.clone(), - expiration: i, - properties: TokenProperties { - description: new_token.token_name.clone(), - }, - created: get_current_time(), - user_id: user.id, + let value = ActiveAuthTokenModel { + id: Set(uuid.clone()), + token_hash: Set(hash), + properties: Set(TokenProperties { + description: login.into_inner(), + }), + token_last_eight: Set(token_last_eight), + user_id: Set(user.id), + created: Set(get_current_time()), }; - super::AuthTokenEntity::insert(v.into_active_model()) + let result = AuthTokenEntity::insert(value) .exec(connection.as_ref()) - .await; - Ok(HttpResponse::Ok().json(NewTokenResponse { - token: string, + .await + .map_err(ErrorInternalServerError)?; + let response = NewTokenResponse { + token: token, token_id: uuid, - expiration: i, - })) + }; + Ok(HttpResponse::Ok().json(response)) } #[delete("/token/{id}")] @@ -77,6 +79,6 @@ pub async fn delete_token( database: web::Data, auth: Authentication, ) -> actix_web::Result { - let user: UserModel = auth.get_user(&database).await??; + let user = auth.get_user(&database).await??; Ok(HttpResponse::NoContent().finish()) } diff --git a/backend/src/authentication/middleware.rs b/backend/src/authentication/middleware.rs index ffd3c64a..4747fe00 100644 --- a/backend/src/authentication/middleware.rs +++ b/backend/src/authentication/middleware.rs @@ -1,6 +1,7 @@ use std::fmt; use std::future::{ready, Ready}; use std::rc::Rc; +use std::str::FromStr; use actix_web::cookie::{Cookie, Expiration, SameSite}; use actix_web::http::header::{HeaderValue, AUTHORIZATION, ORIGIN, SET_COOKIE}; @@ -94,7 +95,7 @@ where let session = session_manager.create_session().await.unwrap(); (Authentication::Session(session.clone()), Some(session)) } else { - (Authentication::NoIdentification, Option::None) + (Authentication::NoIdentification, None) } } else if let Some(mut session) = session { if session.expiration <= get_current_time() as u64 { @@ -103,9 +104,9 @@ where .await .unwrap(); } - (Authentication::Session(session.clone()), Option::None) + (Authentication::Session(session.clone()), None) } else { - (Authentication::NoIdentification, Option::None) + (Authentication::NoIdentification, None) } } else if let Some(header) = req.headers().get(AUTHORIZATION) { //If it is an Authorization Header pull Database from App Data @@ -118,7 +119,7 @@ where if split.len() != 2 { debug!("Invalid Authorization Header!"); // If the length is not correct. It is an invalid authorization. But let request continue - (Authentication::NoIdentification, Option::None) + (Authentication::NoIdentification, None) } else { let value = split.get(1).unwrap(); let auth_type = split.get(0).unwrap(); @@ -126,14 +127,14 @@ where if auth_type.eq(&"Bearer") { trace!("Authorization Bearer (token)"); - let auth_token = auth_token::get_by_token(value, database) + let auth_token = auth_token::get_token(0, value, database) .await .map_err(internal_server_error)?; if let Some(token) = auth_token { - (Authentication::AuthToken(token), Option::None) + (Authentication::AuthToken(token), None) } else { - (Authentication::NoIdentification, Option::None) + (Authentication::NoIdentification, None) } } else if auth_type.eq(&"Basic") { //If its a Basic header. Parse from base64 @@ -143,22 +144,27 @@ where if split.len() != 2 { debug!("Invalid Authorization Basic Header!"); - (Authentication::NoIdentification, Option::None) + (Authentication::NoIdentification, None) } else { - let username = split.get(0).unwrap().to_string(); - let password = split.get(1).unwrap().to_string(); + let (username, password) = unsafe { + ( + split.get(0).unwrap_unchecked(), + split.get(1).unwrap_unchecked(), + ) + }; + // Maven will pass everything as a Basic. Setting the username as Token lets you use the token system - if username.eq("token") { - trace!("Authorization Basic token:(token)"); + if let Ok(v) = i64::from_str(*username) { + trace!("Authorization Basic user_id:(token)"); // Treat the password as a token - let auth_token = auth_token::get_by_token(&password, database) + let auth_token = auth_token::get_token(v, password, database) .await .map_err(internal_server_error)?; if let Some(token) = auth_token { - (Authentication::AuthToken(token), Option::None) + (Authentication::AuthToken(token), None) } else { - (Authentication::NoIdentification, Option::None) + (Authentication::NoIdentification, None) } } else { // Treat authorization as normal login @@ -195,10 +201,10 @@ where (Authentication::Session(session.clone()), Some(session)) } else { warn!("A Not Origin Not Authorized Request was made"); - (Authentication::NoIdentification, Option::None) + (Authentication::NoIdentification, None) } } else { - (Authentication::NoIdentification, Option::None) + (Authentication::NoIdentification, None) }; // Add the authentication Information for the data req.extensions_mut().insert(authentication); diff --git a/backend/src/authentication/mod.rs b/backend/src/authentication/mod.rs index d30fc24a..3ba71dcd 100644 --- a/backend/src/authentication/mod.rs +++ b/backend/src/authentication/mod.rs @@ -7,13 +7,17 @@ use actix_web::{FromRequest, HttpMessage, HttpRequest, ResponseError}; use argon2::{Argon2, PasswordHash, PasswordVerifier}; use futures_util::future::{ready, Ready}; use log::trace; -use sea_orm::{DatabaseConnection, EntityTrait}; +use regex::internal::Input; +use sea_orm::{ColumnTrait, DatabaseConnection, EntityTrait, QueryFilter}; +use serde::Deserialize; use serde_json::json; use crate::authentication::auth_token::AuthTokenModel; use crate::authentication::session::Session; use crate::error::internal_error::InternalError; use crate::system::user; +use crate::system::user::database::Column::Username; +use crate::system::user::database::UserSafeData; use crate::system::user::{UserEntity, UserModel}; pub mod auth_token; @@ -55,7 +59,7 @@ pub enum Authentication { /// If the Authorization Header could not be parsed. Give them the value AuthorizationHeaderUnknown(String, String), /// Authorization Basic Header - Basic(UserModel), + Basic(UserSafeData), } impl Authentication { @@ -71,7 +75,7 @@ impl Authentication { pub async fn get_user( self, database: &DatabaseConnection, - ) -> Result, InternalError> { + ) -> Result, InternalError> { match self { Authentication::AuthToken(auth) => { let option = auth.get_user(database).await?; @@ -83,7 +87,10 @@ impl Authentication { } Authentication::Session(session) => { if let Some(user) = session.user { - let option = UserEntity::find_by_id(user).one(database).await?; + let option = UserEntity::find_by_id(user) + .into_model() + .one(database) + .await?; if let Some(user) = option { Ok(Ok(user)) } else { @@ -115,12 +122,33 @@ impl FromRequest for Authentication { } } +#[derive(Deserialize, Clone, Debug)] +pub struct SecureAction { + pub username: String, + pub password: String, + pub secure_data: T, +} +impl SecureAction { + pub async fn verify( + &self, + database: &DatabaseConnection, + ) -> Result, InternalError> { + verify_login(&self.username, &self.password, database).await + } + pub fn into_inner(self) -> T { + self.secure_data + } +} +#[inline(always)] pub async fn verify_login( - username: String, - password: String, + username: impl AsRef, + password: impl AsRef, database: &DatabaseConnection, -) -> Result, InternalError> { - let user_found: Option = user::get_by_username(&username, database).await?; +) -> Result, InternalError> { + let user_found: Option = UserEntity::find() + .filter(Username.eq(username.as_ref())) + .one(database) + .await?; if user_found.is_none() { return Ok(Err(NotAuthenticated)); } @@ -128,10 +156,10 @@ pub async fn verify_login( let user = user_found.unwrap(); let parsed_hash = PasswordHash::new(user.password.as_str())?; if argon2 - .verify_password(password.as_bytes(), &parsed_hash) + .verify_password(password.as_ref().as_bytes(), &parsed_hash) .is_err() { return Ok(Err(NotAuthenticated)); } - Ok(Ok(user)) + Ok(Ok(user.into())) } diff --git a/backend/src/bin/nitro_repo_full.rs b/backend/src/bin/nitro_repo_full.rs index 9b692dba..117d9e18 100644 --- a/backend/src/bin/nitro_repo_full.rs +++ b/backend/src/bin/nitro_repo_full.rs @@ -20,11 +20,13 @@ use api::storage::{GeneralConfig, StorageConfig, StorageSaver, StorageType}; use api::utils::load_logger; use api::{authentication, frontend, repository, storage, system, NitroRepo}; use log::info; +use sea_orm::sea_query::MysqlQueryBuilder; +use sea_orm::{DatabaseBackend, Schema}; use semver::Version; use tokio::fs::read_to_string; use tokio::sync::RwLock; -#[main] +#[actix_web::main] async fn main() -> std::io::Result<()> { let test = StorageSaver { storage_type: StorageType::LocalStorage, diff --git a/backend/src/repository/handler.rs b/backend/src/repository/handler.rs index 35570029..8cc777f2 100644 --- a/backend/src/repository/handler.rs +++ b/backend/src/repository/handler.rs @@ -9,10 +9,10 @@ use std::sync::Arc; use crate::authentication::Authentication; use crate::error::api_error::APIError; use crate::error::internal_error::InternalError; - use crate::repository::response::RepoResponse; use crate::repository::settings::RepositoryConfig; use crate::storage::models::Storage; +use crate::system::user::database::UserSafeData; use serde::{Deserialize, Serialize}; #[async_trait] pub trait Repository: Send + Sync + Clone { diff --git a/backend/src/repository/maven/hosted.rs b/backend/src/repository/maven/hosted.rs index e544a95e..8cb8f3c6 100644 --- a/backend/src/repository/maven/hosted.rs +++ b/backend/src/repository/maven/hosted.rs @@ -96,7 +96,7 @@ impl Repository for HostedMavenRepository { authentication: Authentication, ) -> Result { if self.config.visibility == Visibility::Private { - let caller: UserModel = authentication.get_user(conn).await??; + let caller = authentication.get_user(conn).await??; if let Some(value) = caller.can_read_from(&self.config)? { return Err(value.into()); } @@ -124,7 +124,7 @@ impl Repository for HostedMavenRepository { authentication: Authentication, bytes: Bytes, ) -> Result { - let caller: UserModel = authentication.get_user(conn).await??; + let caller = authentication.get_user(conn).await??; if let Some(_value) = caller.can_deploy_to(&self.config)? {} match self.config.policy { Policy::Release => { diff --git a/backend/src/repository/maven/mod.rs b/backend/src/repository/maven/mod.rs index ffbf95cc..ac9f9b2a 100644 --- a/backend/src/repository/maven/mod.rs +++ b/backend/src/repository/maven/mod.rs @@ -41,6 +41,7 @@ repository_handler!( StagingRepository ); use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; +use crate::system::user::database::UserSafeData; crate::repository::nitro::dynamic::nitro_repo_handler!(MavenHandler, Hosted, HostedMavenRepository); crate::repository::staging::dynamic::gen_dynamic_stage!(MavenHandler, Staging); diff --git a/backend/src/repository/maven/proxy.rs b/backend/src/repository/maven/proxy.rs index b71685cc..31f843c6 100644 --- a/backend/src/repository/maven/proxy.rs +++ b/backend/src/repository/maven/proxy.rs @@ -95,7 +95,7 @@ impl Repository for ProxyMavenRepository { authentication: Authentication, ) -> Result { if self.config.visibility == Visibility::Private { - let caller: UserModel = authentication.get_user(conn).await??; + let caller = authentication.get_user(conn).await??; if let Some(value) = caller.can_read_from(&self.config)? { return Err(value.into()); } diff --git a/backend/src/repository/maven/staging/external.rs b/backend/src/repository/maven/staging/external.rs index a48ce9f8..2eb012a5 100644 --- a/backend/src/repository/maven/staging/external.rs +++ b/backend/src/repository/maven/staging/external.rs @@ -1,6 +1,7 @@ use crate::repository::settings::RepositoryConfig; use crate::storage::models::Storage; use crate::storage::DynamicStorage; +use crate::system::user::database::UserSafeData; use crate::system::user::UserModel; use log::{trace, warn}; use reqwest::header::{HeaderMap, USER_AGENT}; @@ -14,7 +15,7 @@ pub async fn stage_to_external( directory: String, storage: Arc, repository: RepositoryConfig, - model: UserModel, + model: UserSafeData, ) -> anyhow::Result<()> { let string = base64::encode(format!("{}:{}", username, password)); let mut map = HeaderMap::new(); diff --git a/backend/src/repository/maven/staging/git.rs b/backend/src/repository/maven/staging/git.rs index f8f35e27..606cdbef 100644 --- a/backend/src/repository/maven/staging/git.rs +++ b/backend/src/repository/maven/staging/git.rs @@ -1,7 +1,7 @@ use crate::repository::maven::models::Pom; use crate::repository::settings::RepositoryConfig; use crate::storage::DynamicStorage; -use crate::system::user::database::Model as UserModel; +use crate::system::user::database::{Model as UserModel, UserSafeData}; use git2::PushOptions; use log::{error, trace}; use std::path::Path; @@ -17,7 +17,7 @@ pub async fn stage_to_git( directory: String, storage: Arc, repository: RepositoryConfig, - model: UserModel, + model: UserSafeData, ) -> anyhow::Result<()> { let dir = tempdir()?; trace!("Cloning {} to {}", url, dir.path().display()); diff --git a/backend/src/repository/maven/staging/mod.rs b/backend/src/repository/maven/staging/mod.rs index f3ac85e1..71fce820 100644 --- a/backend/src/repository/maven/staging/mod.rs +++ b/backend/src/repository/maven/staging/mod.rs @@ -27,6 +27,7 @@ use sea_orm::DatabaseConnection; use serde::{Deserialize, Serialize}; use crate::repository::maven::models::Pom; +use crate::system::user::database::UserSafeData; use git2::PushOptions; use log::{error, info, trace}; use std::sync::Arc; @@ -89,7 +90,7 @@ impl<'a, S: Storage> StageHandler for StagingRepository { &self, directory: String, storages: Arc>, - model: UserModel, + model: UserSafeData, ) -> Result<(), InternalError> { for stage in self.stage_settings.stage_to.iter() { match stage { @@ -195,7 +196,7 @@ impl Repository for StagingRepository { authentication: Authentication, ) -> Result { if self.config.visibility == Visibility::Private { - let caller: UserModel = authentication.get_user(conn).await??; + let caller = authentication.get_user(conn).await??; if let Some(value) = caller.can_read_from(&self.config)? { return Err(value.into()); } @@ -239,7 +240,7 @@ impl Repository for StagingRepository { authentication: Authentication, bytes: Bytes, ) -> Result { - let caller: UserModel = authentication.get_user(conn).await??; + let caller = authentication.get_user(conn).await??; if let Some(_value) = caller.can_deploy_to(&self.config)? {} match self.config.policy { Policy::Release => { diff --git a/backend/src/repository/nitro/dynamic.rs b/backend/src/repository/nitro/dynamic.rs index 7c4fda0f..83775179 100644 --- a/backend/src/repository/nitro/dynamic.rs +++ b/backend/src/repository/nitro/dynamic.rs @@ -74,7 +74,7 @@ macro_rules! nitro_repo_handler { &self, project_folder: String, version_folder: String, - model: crate::system::user::database::Model, + model: crate::system::user::database::UserSafeData, version_data: crate::repository::nitro::VersionData, ) -> Result<(), InternalError> { match self { diff --git a/backend/src/repository/nitro/nitro_repository.rs b/backend/src/repository/nitro/nitro_repository.rs index 4be30323..e28c7645 100644 --- a/backend/src/repository/nitro/nitro_repository.rs +++ b/backend/src/repository/nitro/nitro_repository.rs @@ -15,7 +15,7 @@ use crate::repository::response::Project; use crate::storage::file::StorageDirectoryResponse; use crate::storage::models::Storage; -use crate::system::user::UserModel; +use crate::system::user::database::UserSafeData; #[async_trait] pub trait NitroRepositoryHandler: Repository { @@ -173,7 +173,7 @@ pub trait NitroRepositoryHandler: Repository &self, project_folder: String, version_folder: String, - _: UserModel, + _: UserSafeData, version_data: VersionData, ) -> Result<(), InternalError> { let project_file = format!("{}/{}", &project_folder, PROJECT_FILE); diff --git a/backend/src/repository/npm/mod.rs b/backend/src/repository/npm/mod.rs index ee5fa37a..1925c064 100644 --- a/backend/src/repository/npm/mod.rs +++ b/backend/src/repository/npm/mod.rs @@ -74,7 +74,7 @@ impl Repository for NPMHandler { conn: &DatabaseConnection, authentication: Authentication, ) -> Result { - let caller: UserModel = authentication.get_user(conn).await??; + let caller = authentication.get_user(conn).await??; if let Some(value) = caller.can_read_from(&self.config)? { return Err(value.into()); } @@ -150,7 +150,7 @@ impl Repository for NPMHandler { return Ok(RepoResponse::Json(created_response, StatusCode::CREATED)); } //Handle Normal Request - let caller: UserModel = authentication.get_user(conn).await??; + let caller = authentication.get_user(conn).await??; if let Some(value) = caller.can_deploy_to(&self.config)? { return Err(value.into()); } diff --git a/backend/src/repository/staging/dynamic.rs b/backend/src/repository/staging/dynamic.rs index a75bce71..37f9fd9b 100644 --- a/backend/src/repository/staging/dynamic.rs +++ b/backend/src/repository/staging/dynamic.rs @@ -23,7 +23,7 @@ macro_rules! gen_dynamic_stage { &self, directory: String, storages: Arc>, - user: crate::system::user::UserModel, + user: UserSafeData, ) -> Result<(), InternalError>{ match self { $( diff --git a/backend/src/repository/staging/mod.rs b/backend/src/repository/staging/mod.rs index fe0d69f6..d4f176b2 100644 --- a/backend/src/repository/staging/mod.rs +++ b/backend/src/repository/staging/mod.rs @@ -9,6 +9,7 @@ use crate::storage::DynamicStorage; use async_trait::async_trait; use serde::{Deserialize, Serialize}; +use crate::system::user::database::UserSafeData; use crate::system::user::UserModel; use std::sync::Arc; @@ -35,6 +36,6 @@ pub trait StageHandler { &self, directory: String, storages: Arc>, - user: UserModel, + user: UserSafeData, ) -> Result<(), InternalError>; } diff --git a/backend/src/repository/web/multi/admin.rs b/backend/src/repository/web/multi/admin.rs index 2abf0554..77445466 100644 --- a/backend/src/repository/web/multi/admin.rs +++ b/backend/src/repository/web/multi/admin.rs @@ -1,7 +1,5 @@ - use std::sync::Arc; - use actix_web::{delete, get, post, web, HttpResponse}; use lockfree::map::Removed; @@ -12,7 +10,7 @@ use crate::authentication::Authentication; use crate::error::internal_error::InternalError; -use crate::repository::handler::{Repository}; +use crate::repository::handler::Repository; use crate::repository::settings::{Policy, Visibility}; @@ -26,7 +24,6 @@ use crate::system::user::UserModel; use paste::paste; use serde_json::Value; - /// Get all repositories from the storage #[get("/repositories/{storage_name}")] pub async fn get_repositories( @@ -35,7 +32,7 @@ pub async fn get_repositories( auth: Authentication, storage_name: web::Path, ) -> actix_web::Result { - let user: UserModel = auth.get_user(&database).await??; + let user = auth.get_user(&database).await??; user.can_i_edit_repos()?; let storage = crate::helpers::get_storage!(storage_handler, storage_name); @@ -52,7 +49,7 @@ pub async fn create_repository( query_params: web::Path<(String, String, RepositoryType)>, _inner_config: web::Json>, ) -> actix_web::Result { - let user: UserModel = auth.get_user(&database).await??; + let user = auth.get_user(&database).await??; user.can_i_edit_repos()?; let (storage_name, _repository_name, _repository_type) = query_params.into_inner(); @@ -76,7 +73,7 @@ pub async fn get_repository( path_params: web::Path<(String, String)>, _query_params: web::Query, ) -> actix_web::Result { - let user: UserModel = auth.get_user(&database).await??; + let user = auth.get_user(&database).await??; user.can_i_edit_repos()?; let (storage_name, repository_name) = path_params.into_inner(); let storage = crate::helpers::get_storage!(storage_handler, storage_name); @@ -99,7 +96,7 @@ pub async fn delete_repository( path_params: web::Path<(String, String)>, query_params: web::Query, ) -> actix_web::Result { - let user: UserModel = auth.get_user(&database).await??; + let user = auth.get_user(&database).await??; user.can_i_edit_repos()?; let (storage_name, repository_name) = path_params.into_inner(); let storage = crate::helpers::get_storage!(storage_handler, storage_name); @@ -121,7 +118,7 @@ macro_rules! update_repository_core_prop { auth: Authentication, path_params: web::Path<(String, String, $value_type)>, ) -> actix_web::Result { - let user: UserModel = auth.get_user(&database).await??; + let user = auth.get_user(&database).await??; user.can_i_edit_repos()?; let (storage_name, repository_name, value) = path_params.into_inner(); let storage = crate::helpers::get_storage!(storage_handler, storage_name); diff --git a/backend/src/repository/web/multi/configs.rs b/backend/src/repository/web/multi/configs.rs index e0d3fcfb..86c00db9 100644 --- a/backend/src/repository/web/multi/configs.rs +++ b/backend/src/repository/web/multi/configs.rs @@ -9,7 +9,7 @@ macro_rules! define_repository_config_get { ) -> actix_web::Result { use crate::storage::models::Storage; use crate::system::permissions::options::CanIDo; - let user: crate::system::user::UserModel = auth.get_user(&database).await??; + let user = auth.get_user(&database).await??; user.can_i_edit_repos()?; let (storage_name, repository_name) = path_params.into_inner(); let storage = crate::helpers::get_storage!(storage_handler, storage_name); @@ -41,7 +41,7 @@ macro_rules! define_repository_config_set { ) -> actix_web::Result { use crate::storage::models::Storage; use crate::system::permissions::options::CanIDo; - let user: crate::system::user::UserModel = auth.get_user(&database).await??; + let user = auth.get_user(&database).await??; user.can_i_edit_repos()?; let (storage_name, repository_name) = path_params.into_inner(); let storage = crate::helpers::get_storage!(storage_handler, storage_name); diff --git a/backend/src/repository/web/multi/public/project.rs b/backend/src/repository/web/multi/public/project.rs index 7664165b..9f047755 100644 --- a/backend/src/repository/web/multi/public/project.rs +++ b/backend/src/repository/web/multi/public/project.rs @@ -33,7 +33,7 @@ pub async fn get_project( .visibility .eq(&Visibility::Public) { - let caller: UserModel = authentication.get_user(database.as_ref()).await??; + let caller = authentication.get_user(database.as_ref()).await??; if let Some(value) = caller.can_read_from(repository.get_repository())? { return Err(value.into()); } diff --git a/backend/src/repository/web/multi/public/repositories.rs b/backend/src/repository/web/multi/public/repositories.rs index a18081ab..4b945916 100644 --- a/backend/src/repository/web/multi/public/repositories.rs +++ b/backend/src/repository/web/multi/public/repositories.rs @@ -14,6 +14,7 @@ use crate::storage::models::Storage; use crate::storage::multi::MultiStorageController; use crate::storage::DynamicStorage; use crate::system::permissions::options::CanIDo; +use crate::system::user::database::UserSafeData; use crate::system::user::UserModel; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct PublicRepositoryResponse { @@ -31,7 +32,7 @@ pub async fn get_repositories( let storage_name = path.into_inner(); let value = crate::helpers::get_storage!(storage_handler, storage_name); - let caller: Option = authentication.get_user(database.as_ref()).await?.ok(); + let caller: Option = authentication.get_user(database.as_ref()).await?.ok(); let vec: Vec = value .get_repository_list() .map_err(actix_web::error::ErrorInternalServerError)? @@ -77,7 +78,7 @@ pub async fn get_repository( .visibility .eq(&Visibility::Public) { - let caller: UserModel = authentication.get_user(database.as_ref()).await??; + let caller = authentication.get_user(database.as_ref()).await??; if let Some(value) = caller.can_read_from(repository.get_repository())? { return Err(value.into()); } diff --git a/backend/src/repository/web/multi/repository_handler.rs b/backend/src/repository/web/multi/repository_handler.rs index 7f421fd5..e4503346 100644 --- a/backend/src/repository/web/multi/repository_handler.rs +++ b/backend/src/repository/web/multi/repository_handler.rs @@ -68,7 +68,7 @@ pub async fn stage_repository( if !repository.staging_repository() { return Ok(HttpResponse::BadRequest().finish().into()); } - let caller: UserModel = authentication.get_user(pool.as_ref()).await??; + let caller = authentication.get_user(pool.as_ref()).await??; if let Some(_value) = caller.can_deploy_to(&repository.get_repository())? {} repository.push(file, storages.into_inner(), caller).await?; Ok(HttpResponse::NoContent().finish().into()) diff --git a/backend/src/storage/multi/web/admin.rs b/backend/src/storage/multi/web/admin.rs index a7bc01f4..7cb81ec5 100644 --- a/backend/src/storage/multi/web/admin.rs +++ b/backend/src/storage/multi/web/admin.rs @@ -18,7 +18,7 @@ pub async fn get_storages( database: web::Data, auth: Authentication, ) -> actix_web::Result { - let user: UserModel = auth.get_user(&database).await??; + let user = auth.get_user(&database).await??; user.can_i_edit_repos()?; Ok(HttpResponse::Ok().json(storage_handler.storage_savers().await)) @@ -32,7 +32,7 @@ pub async fn new_storage( database: web::Data, auth: Authentication, ) -> actix_web::Result { - let user: UserModel = auth.get_user(&database).await??; + let user = auth.get_user(&database).await??; user.can_i_edit_repos()?; if let Err(error) = storage_handler.create_storage(new_storage.0).await { match error { @@ -56,7 +56,7 @@ pub async fn delete_storage( auth: Authentication, name: web::Path, ) -> actix_web::Result { - let user: UserModel = auth.get_user(&database).await??; + let user = auth.get_user(&database).await??; user.can_i_edit_repos()?; if storage_handler .delete_storage(&name.into_inner()) @@ -76,7 +76,7 @@ pub async fn get_storage( database: web::Data, auth: Authentication, ) -> actix_web::Result { - let user: UserModel = auth.get_user(&database).await??; + let user = auth.get_user(&database).await??; user.can_i_edit_repos()?; let storage = crate::helpers::get_storage!(storage_handler, name); Ok(HttpResponse::Ok().json(storage.storage_config())) diff --git a/backend/src/system/mod.rs b/backend/src/system/mod.rs index 3155d68e..4d171c9f 100644 --- a/backend/src/system/mod.rs +++ b/backend/src/system/mod.rs @@ -1,5 +1,6 @@ -use argon2::password_hash::SaltString; +use argon2::password_hash::{Salt, SaltString}; use argon2::{Argon2, PasswordHasher}; +use clap::arg; use rand::rngs::OsRng; use crate::error::internal_error::InternalError; @@ -8,12 +9,11 @@ pub mod permissions; pub mod user; pub mod web; -pub fn hash(password: String) -> Result { +pub fn hash(password: impl AsRef) -> Result { let salt = SaltString::generate(&mut OsRng); - let argon2 = Argon2::default(); let password_hash = argon2 - .hash_password(password.as_bytes(), salt.as_ref())? + .hash_password(password.as_ref().as_bytes(), salt.as_ref())? .to_string(); Ok(password_hash) } diff --git a/backend/src/system/permissions/options.rs b/backend/src/system/permissions/options.rs index fc979779..8b1f45a9 100644 --- a/backend/src/system/permissions/options.rs +++ b/backend/src/system/permissions/options.rs @@ -9,6 +9,7 @@ use crate::error::internal_error::InternalError; use crate::repository::settings::RepositoryConfig; use crate::repository::settings::Visibility; use crate::system::permissions::{can_deploy, can_read}; +use crate::system::user::database::UserSafeData; use crate::system::user::UserModel; pub struct MissingPermission(String); @@ -95,6 +96,63 @@ impl CanIDo for Option { } } } +impl CanIDo for UserSafeData { + fn can_i_edit_repos(&self) -> Result<(), MissingPermission> { + let permissions = &self.permissions; + + if !permissions.admin && !permissions.repository_manager { + return Err("repository_manager".into()); + } + Ok(()) + } + + fn can_i_edit_users(&self) -> Result<(), MissingPermission> { + let permissions = &self.permissions; + if !permissions.admin && !permissions.user_manager { + return Err("user_manager".into()); + } + Ok(()) + } + + fn can_i_admin(&self) -> Result<(), MissingPermission> { + let permissions = &self.permissions; + + if !permissions.admin { + return Err("admin".into()); + } + Ok(()) + } + + fn can_deploy_to( + &self, + repo: &RepositoryConfig, + ) -> Result, InternalError> { + let can_read = can_deploy(&self.permissions, repo)?; + if can_read { + Ok(None) + } else { + Ok(Some(MissingPermission("Write Repository".to_string()))) + } + } + + fn can_read_from( + &self, + repo: &RepositoryConfig, + ) -> Result, InternalError> { + match repo.visibility { + Visibility::Public => Ok(None), + Visibility::Private => { + let can_read = can_read(&self.permissions, repo)?; + if can_read { + Ok(None) + } else { + Ok(Some(MissingPermission("Read Repository".to_string()))) + } + } + Visibility::Hidden => Ok(None), + } + } +} impl CanIDo for UserModel { fn can_i_edit_repos(&self) -> Result<(), MissingPermission> { let permissions = &self.permissions; diff --git a/backend/src/system/permissions/orm.rs b/backend/src/system/permissions/orm.rs index bd4572c5..be2e1310 100644 --- a/backend/src/system/permissions/orm.rs +++ b/backend/src/system/permissions/orm.rs @@ -1,5 +1,6 @@ use crate::system::permissions::UserPermissions; -use sea_orm::{DbErr, JsonValue}; +use sea_orm::ActiveValue::Set; +use sea_orm::{ActiveValue, DbErr, IntoActiveValue, JsonValue}; impl From for JsonValue { fn from(auth: UserPermissions) -> Self { @@ -45,3 +46,8 @@ impl sea_orm::sea_query::ValueType for UserPermissions { sea_orm::sea_query::ColumnType::Json } } +impl IntoActiveValue for UserPermissions { + fn into_active_value(self) -> ActiveValue { + Set(self) + } +} diff --git a/backend/src/system/user/database.rs b/backend/src/system/user/database.rs index 674d95fb..99cb54a2 100644 --- a/backend/src/system/user/database.rs +++ b/backend/src/system/user/database.rs @@ -1,5 +1,6 @@ use crate::system::permissions::UserPermissions; use sea_orm::entity::prelude::*; +use sea_orm::FromQueryResult; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] @@ -23,6 +24,34 @@ pub struct ModifyUser { pub email: String, } +#[derive(FromQueryResult, DeriveIntoActiveModel, Serialize, Deserialize, Clone, Debug)] +pub struct UserSafeData { + pub id: i64, + pub name: String, + pub username: String, + pub email: String, + #[sea_orm(column_type = "Json")] + pub permissions: UserPermissions, + pub created: i64, +} +impl From for UserSafeData { + fn from(v: Model) -> Self { + UserSafeData { + id: v.id, + name: v.name, + username: v.username, + email: v.email, + permissions: v.permissions, + created: v.created, + } + } +} +impl PartialEq for UserSafeData { + fn eq(&self, other: &Self) -> bool { + self.id == other.id + } +} + impl ActiveModelBehavior for ActiveModel {} #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/backend/src/system/user/mod.rs b/backend/src/system/user/mod.rs index 00d0d7e9..3fb3e748 100644 --- a/backend/src/system/user/mod.rs +++ b/backend/src/system/user/mod.rs @@ -1,24 +1,30 @@ pub mod database; +use crate::system::user::database::UserSafeData; pub use database::Entity as UserEntity; pub use database::Model as UserModel; -use sea_orm::{ColumnTrait, DatabaseConnection, DbErr, EntityTrait, QueryFilter}; +use sea_orm::{ + ColumnTrait, DatabaseConnection, DbErr, EntityTrait, FromQueryResult, QueryFilter, Statement, +}; +use serde::Deserialize; pub async fn get_by_username( username: &str, connection: &DatabaseConnection, -) -> Result, DbErr> { +) -> Result, DbErr> { UserEntity::find() .filter(database::Column::Username.eq(username)) + .into_model() .one(connection) .await } pub async fn get_by_id( id: i64, connection: &DatabaseConnection, -) -> Result, DbErr> { +) -> Result, DbErr> { UserEntity::find() .filter(database::Column::Id.eq(id)) + .into_model::() .one(connection) .await } diff --git a/backend/src/system/web/admin.rs b/backend/src/system/web/admin.rs index 46c5f6c4..4b84b789 100644 --- a/backend/src/system/web/admin.rs +++ b/backend/src/system/web/admin.rs @@ -7,6 +7,8 @@ use sea_orm::DatabaseConnection; use serde::{Deserialize, Serialize}; use crate::helpers::unwrap_or_not_found; +use crate::system::user::database::UserSafeData; + // struct that derives Serialize and Deserialize contains the number of active storages, number of active repositories, and the number of active users. #[derive(Serialize, Deserialize, Clone, Debug)] pub struct SystemStatus { @@ -20,7 +22,7 @@ pub async fn list_users( auth: Authentication, database: web::Data, ) -> actix_web::Result { - let user: UserModel = auth.get_user(&database).await??; + let user = auth.get_user(&database).await??; user.can_i_edit_users()?; let result: Vec = super::super::user::get_users(&database) .await @@ -35,9 +37,9 @@ pub async fn get_user( database: web::Data, id: web::Path, ) -> actix_web::Result { - let user: UserModel = auth.get_user(&database).await??; + let user = auth.get_user(&database).await??; user.can_i_edit_users()?; - let result: UserModel = + let result: UserSafeData = unwrap_or_not_found!(super::super::user::get_by_id(id.into_inner(), &database) .await .map_err(actix_web::error::ErrorInternalServerError)?); diff --git a/backend/src/system/web/mod.rs b/backend/src/system/web/mod.rs index 391c8312..63ae949c 100644 --- a/backend/src/system/web/mod.rs +++ b/backend/src/system/web/mod.rs @@ -9,7 +9,7 @@ pub fn init_public_routes(cfg: &mut ServiceConfig) { } pub fn user_routes(cfg: &mut ServiceConfig) { - cfg.service(user::me); + cfg.service(user::me).service(user::update_password); } pub fn init_user_manager_routes(cfg: &mut ServiceConfig) { diff --git a/backend/src/system/web/user.rs b/backend/src/system/web/user.rs index d7f705fa..903e8c61 100644 --- a/backend/src/system/web/user.rs +++ b/backend/src/system/web/user.rs @@ -1,15 +1,37 @@ -use actix_web::get; +use actix_web::error::ErrorInternalServerError; +use actix_web::{get, put}; use actix_web::{web, HttpResponse}; -use sea_orm::DatabaseConnection; - -use crate::authentication::Authentication; -use crate::system::user::UserModel; +use sea_orm::ActiveValue::Set; +use sea_orm::{DatabaseConnection, IntoActiveModel}; +use crate::authentication::{verify_login, Authentication, SecureAction}; +use crate::system::hash; +use crate::system::user::{UserEntity, UserModel}; +use sea_orm::EntityTrait; #[get("/me")] pub async fn me( database: web::Data, auth: Authentication, ) -> actix_web::Result { - let user: UserModel = auth.get_user(&database).await??; + let user = auth.get_user(&database).await??; Ok(HttpResponse::Ok().json(user)) } + +#[put("/me/password")] +pub async fn update_password( + database: web::Data, + auth: Authentication, + nc: web::Json>, +) -> actix_web::Result { + let secure_action: SecureAction = nc.into_inner(); + let model = secure_action.verify(&database).await??; + + let result = hash(secure_action.into_inner())?; + let mut model = model.into_active_model(); + model.password = Set(result); + UserEntity::update(model) + .exec(database.as_ref()) + .await + .map_err(ErrorInternalServerError)?; + Ok(HttpResponse::NoContent().finish()) +} From a498d8a251336bd800172ea6701978191b1beba6 Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Fri, 29 Jul 2022 20:11:18 -0400 Subject: [PATCH 52/76] API delete, list, and add added. --- .../src/authentication/auth_token/web/mod.rs | 47 +++-- backend/src/system/permissions/mod.rs | 21 ++- frontend/.nvmrc | 2 +- frontend/components.d.ts | 6 + frontend/src/components/UpdateUser.vue | 2 +- .../src/components/common/forms/Switch.vue | 13 +- frontend/src/components/common/tabs/Tab.vue | 1 + frontend/src/components/user/LoginComp.vue | 2 +- frontend/src/components/user/PasswordBox.vue | 46 +++++ .../src/components/user/UpdatePassword.vue | 11 ++ frontend/src/components/user/keys/APIKeys.vue | 36 ++++ .../src/components/user/keys/MyAPIKeys.vue | 166 ++++++++++++++++++ frontend/src/components/user/keys/Token.vue | 64 +++++++ .../components/user/update/PermissionList.vue | 116 ++++++++++-- .../components/user/update/Permissions.vue | 136 ++++---------- .../components/user/update/UserGeneral.vue | 23 +-- frontend/src/store/user.ts | 2 +- frontend/src/types/user.ts | 30 ---- frontend/src/types/userTypes.ts | 10 +- frontend/src/views/Me.vue | 105 +++++------ nrc/src/add.rs | 2 - nrc/src/configs/user.rs | 1 - 22 files changed, 599 insertions(+), 243 deletions(-) create mode 100644 frontend/src/components/user/PasswordBox.vue create mode 100644 frontend/src/components/user/UpdatePassword.vue create mode 100644 frontend/src/components/user/keys/APIKeys.vue create mode 100644 frontend/src/components/user/keys/MyAPIKeys.vue create mode 100644 frontend/src/components/user/keys/Token.vue delete mode 100644 frontend/src/types/user.ts diff --git a/backend/src/authentication/auth_token/web/mod.rs b/backend/src/authentication/auth_token/web/mod.rs index a3d2b2f5..716015e7 100644 --- a/backend/src/authentication/auth_token/web/mod.rs +++ b/backend/src/authentication/auth_token/web/mod.rs @@ -13,14 +13,16 @@ use actix_web::{delete, get, post, HttpRequest, HttpResponse}; use chrono::Duration; use log::error; use sea_orm::ActiveValue::Set; -use sea_orm::{ColumnTrait, EntityTrait, QueryFilter}; +use sea_orm::{ColumnTrait, EntityTrait, FromQueryResult, QueryFilter}; use sea_orm::{DatabaseConnection, IntoActiveModel}; use serde::{Deserialize, Serialize}; use serde_json::json; use uuid::Uuid; pub fn authentication_router(cfg: &mut web::ServiceConfig) { - cfg.service(create_token); + cfg.service(create_token) + .service(list_tokens) + .service(delete_token); } #[derive(Serialize, Deserialize, Clone, Debug)] @@ -28,18 +30,25 @@ pub struct NewTokenResponse { pub token: String, pub token_id: Uuid, } -#[derive(Serialize, Deserialize, Clone, Debug)] +#[derive(Serialize, Deserialize, FromQueryResult, Clone, Debug)] pub struct TokenResponse { - pub expiration: i64, + pub id: Uuid, pub properties: TokenProperties, pub created: i64, } #[get("/token/list")] pub async fn list_tokens( database: web::Data, - login: web::Json>, + authentication: Authentication, ) -> actix_web::Result { - Ok(HttpResponse::NoContent().finish()) + let login = authentication.get_user(database.as_ref()).await??; + let tokens = AuthTokenEntity::find() + .filter(super::database::Column::UserId.eq(login.id)) + .into_model::() + .all(database.as_ref()) + .await + .map_err(ErrorInternalServerError)?; + Ok(HttpResponse::Ok().json(tokens)) } #[post("/token/create")] @@ -57,7 +66,9 @@ pub async fn create_token( id: Set(uuid.clone()), token_hash: Set(hash), properties: Set(TokenProperties { - description: login.into_inner(), + description: login + .into_inner() + .and_then(|x| if x.is_empty() { None } else { Some(x) }), }), token_last_eight: Set(token_last_eight), user_id: Set(user.id), @@ -71,14 +82,28 @@ pub async fn create_token( token: token, token_id: uuid, }; - Ok(HttpResponse::Ok().json(response)) + Ok(HttpResponse::Created().json(response)) } #[delete("/token/{id}")] pub async fn delete_token( database: web::Data, - auth: Authentication, + delete_token: web::Path, + authentication: Authentication, ) -> actix_web::Result { - let user = auth.get_user(&database).await??; - Ok(HttpResponse::NoContent().finish()) + let user = authentication.get_user(database.get_ref()).await??; + let result = AuthTokenEntity::delete_many() + .filter( + super::database::Column::Id + .eq(delete_token.into_inner()) + .and(super::database::Column::UserId.eq(user.id)), + ) + .exec(database.as_ref()) + .await + .map_err(ErrorInternalServerError)?; + if result.rows_affected == 0 { + Ok(HttpResponse::NotFound().finish()) + } else { + Ok(HttpResponse::NoContent().finish()) + } } diff --git a/backend/src/system/permissions/mod.rs b/backend/src/system/permissions/mod.rs index 12225f7c..502394d0 100644 --- a/backend/src/system/permissions/mod.rs +++ b/backend/src/system/permissions/mod.rs @@ -33,14 +33,23 @@ pub struct UserPermissions { pub admin: bool, pub user_manager: bool, pub repository_manager: bool, - pub deployer: Option, - pub viewer: Option, + #[serde(default)] + pub deployer: RepositoryPermission, + #[serde(default)] + pub viewer: RepositoryPermission, } #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] pub struct RepositoryPermission { pub permissions: Vec, } +impl Default for RepositoryPermission { + fn default() -> Self { + RepositoryPermission { + permissions: vec!["*".to_string()], + } + } +} #[derive(Serialize, Deserialize, Debug, Default)] pub struct RepositoryPermissionValue { @@ -60,8 +69,8 @@ pub fn can_deploy( return Ok(true); } - if let Some(perms) = &user_perms.deployer { - return can(repo, perms); + if !user_perms.deployer.permissions.is_empty() { + return can(repo, &user_perms.deployer); } Ok(false) } @@ -80,8 +89,8 @@ pub fn can_read( match repo.visibility { Visibility::Public => Ok(true), Visibility::Private => { - if let Some(perms) = &user_perms.viewer { - if can(repo, perms)? { + if !user_perms.viewer.permissions.is_empty() { + if can(repo, &user_perms.viewer)? { return Ok(true); } } diff --git a/frontend/.nvmrc b/frontend/.nvmrc index a11d04fe..0828ab79 100644 --- a/frontend/.nvmrc +++ b/frontend/.nvmrc @@ -1 +1 @@ -v18.5.0 \ No newline at end of file +v18 \ No newline at end of file diff --git a/frontend/components.d.ts b/frontend/components.d.ts index 7d8836a2..55b74191 100644 --- a/frontend/components.d.ts +++ b/frontend/components.d.ts @@ -8,6 +8,7 @@ export {} declare module '@vue/runtime-core' { export interface GlobalComponents { AdminDropBox: typeof import('./src/components/nav/AdminDropBox.vue')['default'] + APIKeys: typeof import('./src/components/user/keys/APIKeys.vue')['default'] ArtifactSearch: typeof import('./src/components/ArtifactSearch.vue')['default'] ArtifactSettings: typeof import('./src/components/repo/update/ArtifactSettings.vue')['default'] BrowseBox: typeof import('./src/components/browse/BrowseBox.vue')['default'] @@ -29,9 +30,12 @@ declare module '@vue/runtime-core' { MavenSettings: typeof import('./src/components/repo/types/maven/MavenSettings.vue')['default'] MavenUpload: typeof import('./src/components/upload/MavenUpload.vue')['default'] MenuButton: typeof import('./src/components/nav/MenuButton.vue')['default'] + MyAPIKeys: typeof import('./src/components/user/keys/MyAPIKeys.vue')['default'] Navbar: typeof import('./src/components/nav/Navbar.vue')['default'] + NewToken: typeof import('./src/components/user/keys/NewToken.vue')['default'] NitroModal: typeof import('./src/components/common/model/NitroModal.vue')['default'] NPMSettings: typeof import('./src/components/repo/types/npm/NPMSettings.vue')['default'] + PasswordBox: typeof import('./src/components/user/PasswordBox.vue')['default'] PermissionList: typeof import('./src/components/user/update/PermissionList.vue')['default'] Permissions: typeof import('./src/components/user/update/Permissions.vue')['default'] PomCreator: typeof import('./src/components/upload/PomCreator.vue')['default'] @@ -49,6 +53,8 @@ declare module '@vue/runtime-core' { Switch: typeof import('./src/components/common/forms/Switch.vue')['default'] Tab: typeof import('./src/components/common/tabs/Tab.vue')['default'] Tabs: typeof import('./src/components/common/tabs/Tabs.vue')['default'] + Token: typeof import('./src/components/user/keys/Token.vue')['default'] + UpdatePassword: typeof import('./src/components/user/UpdatePassword.vue')['default'] UpdateRepo: typeof import('./src/components/repo/update/UpdateRepo.vue')['default'] UpdateStorage: typeof import('./src/components/UpdateStorage.vue')['default'] UpdateUser: typeof import('./src/components/UpdateUser.vue')['default'] diff --git a/frontend/src/components/UpdateUser.vue b/frontend/src/components/UpdateUser.vue index 9e041446..556a3b42 100644 --- a/frontend/src/components/UpdateUser.vue +++ b/frontend/src/components/UpdateUser.vue @@ -11,8 +11,8 @@ import { defineComponent, inject, ref } from "vue"; import UserGeneral from "./user/update/UserGeneral.vue"; import { useRouter } from "vue-router"; -import { User } from "@/types/user"; import httpCommon from "@/http-common"; +import { User } from "@/types/userTypes"; export default defineComponent({ props: { diff --git a/frontend/src/components/common/forms/Switch.vue b/frontend/src/components/common/forms/Switch.vue index 3344ac25..a8d88772 100644 --- a/frontend/src/components/common/forms/Switch.vue +++ b/frontend/src/components/common/forms/Switch.vue @@ -1,5 +1,9 @@ From 9dbefc419c0e4be802993ac0e68c4b0819ba981e Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Thu, 18 Aug 2022 08:36:16 -0400 Subject: [PATCH 70/76] Raw Support --- backend/Cargo.toml | 11 +++--- backend/src/bin/nitro_repo_full.rs | 24 +++++++----- backend/src/bin/updator.rs | 1 + backend/src/cli/mod.rs | 33 ---------------- backend/src/lib.rs | 6 +-- backend/src/repository/raw/mod.rs | 60 +++++++++++++++++++++++------- backend/src/settings/models.rs | 17 +++++---- backend/src/updater/mod.rs | 17 +++++++-- backend/src/updater/one_one/mod.rs | 4 ++ build.sh | 2 +- 10 files changed, 100 insertions(+), 75 deletions(-) create mode 100644 backend/src/bin/updator.rs delete mode 100644 backend/src/cli/mod.rs diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 63fc91ea..a0a090ea 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -15,6 +15,10 @@ name = "nitro_repo_full" required-features = ["multi_storage"] [[bin]] name = "simple_installer" +required-features = ["clap"] +[[bin]] +name = "updator" +required-features = ["clap"] [dependencies] # Web @@ -65,7 +69,7 @@ badge-maker = "0.3" # Webhook webhook_sender = { git = "https://github.com/wyatt-herkamp/webhook_sender.git" } # Installer -clap = { version = "3.2.12", features = ["derive"] } +clap = { version = "3.2.12", features = ["derive"], optional = true } semver = { version = "1", features = ["std", "serde"] } # Cache redis = "0.21.5" @@ -82,12 +86,9 @@ this_actix_error = { git = "https://github.com/wyatt-herkamp/this_actix_errors.g vergen = { version = "7.0.0" } [features] # The latest Updaters will always be under default features -default = ["updater_one-one", "multi_storage"] +default = ["multi_storage"] ssl = ["openssl", "actix-web/openssl"] multi_storage = [] -# Updaters -# Updater for 1.0.0 - 1.1.0 -updater_one-one = [] # Development Tools ## Allows you to add a file called unsafe_cookies.txt to the active directory. And contains KEY=VALUE(Value being the user id) for cookies/sessions to be added to the system upon start diff --git a/backend/src/bin/nitro_repo_full.rs b/backend/src/bin/nitro_repo_full.rs index cd58855a..e4dcb044 100644 --- a/backend/src/bin/nitro_repo_full.rs +++ b/backend/src/bin/nitro_repo_full.rs @@ -14,7 +14,6 @@ use actix_web::{web, App, HttpServer}; use handlebars::template::Parameter::Path; use api::authentication::middleware::HandleSession; use api::authentication::session::{Session, SessionManager, SessionManagerType}; -use api::cli::handle_cli; use api::generators::GeneratorCache; use api::settings::load_configs; @@ -32,9 +31,6 @@ use tokio::sync::RwLock; #[actix_web::main] async fn main() -> std::io::Result<()> { - if handle_cli().await.map_err(convert_error)? { - return Ok(()); - } let current_dir = current_dir()?; let configs = current_dir.join("cfg"); let main_config = current_dir.join("nitro_repo.toml"); @@ -48,9 +44,19 @@ async fn main() -> std::io::Result<()> { let init_settings: GeneralSettings = toml::from_str(&read_to_string(&main_config).await?).map_err(convert_error)?; - let version = semver::Version::parse(&init_settings.internal.version).map_err(convert_error)?; + let version = Version::new(init_settings.internal.version.clone()); + if init_settings.internal.version.major != version.cargo_version.major && init_settings.internal.version.minor != version.cargo_version.minor { + eprintln!( + "Version mismatch. Expected {:?} but found {:?}", + version.cargo_version, + init_settings.internal.version + ); + exit(1) + } + // Sets the Log Location set_var("LOG_LOCATION", &init_settings.application.log); + set_var("FRONTEND", &init_settings.application.frontend); load_logger(&init_settings.application.mode); info!("Initializing Database Connection"); let connection = sea_orm::Database::connect(init_settings.database.clone()) @@ -69,7 +75,7 @@ async fn main() -> std::io::Result<()> { let nitro_repo = NitroRepo { settings: RwLock::new(settings), core: init_settings, - current_version: Version::new(version), + current_version: version, }; info!("Version: {:?}", nitro_repo.current_version); let application = nitro_repo.core.application.clone(); @@ -89,7 +95,7 @@ async fn main() -> std::io::Result<()> { { #[cfg(not(debug_assertions))] { - compile_error!("You are not in a development environment"); + //compile_error!("You are not in a development environment"); } warn!("Using unsafe cookies"); warn!("This is not recommended. This is only for development purposes"); @@ -153,9 +159,9 @@ async fn main() -> std::io::Result<()> { .service( web::scope("") .wrap(HandleSession(false)) - .configure(repository::web::multi::init_repository_handlers), + .configure(repository::web::multi::init_repository_handlers) + .configure(frontend::init), ) - .configure(frontend::init) }); #[cfg(feature = "ssl")] diff --git a/backend/src/bin/updator.rs b/backend/src/bin/updator.rs new file mode 100644 index 00000000..e71fdf55 --- /dev/null +++ b/backend/src/bin/updator.rs @@ -0,0 +1 @@ +fn main() {} \ No newline at end of file diff --git a/backend/src/cli/mod.rs b/backend/src/cli/mod.rs deleted file mode 100644 index a641117a..00000000 --- a/backend/src/cli/mod.rs +++ /dev/null @@ -1,33 +0,0 @@ -use std::env::current_dir; - -use clap::Parser; -use log::error; -use style_term::{DefaultColor, StyleString}; - -use crate::updater; - -#[derive(Parser, Debug)] -#[clap(author, version, about, long_about = None)] -struct NitroRepoCLI { - #[clap(short, long)] - update: Option, -} - -pub async fn handle_cli() -> std::io::Result { - let _path = current_dir()?; - - let parse: NitroRepoCLI = NitroRepoCLI::parse(); - if let Some(update) = parse.update { - if let Err(error) = updater::update(update).await { - error!("Unable to complete update {error}"); - println!( - "{}", - "Unable to Complete Update" - .style() - .text_color(DefaultColor::Red) - ); - } - return Ok(true); - } - Ok(false) -} diff --git a/backend/src/lib.rs b/backend/src/lib.rs index f059df6f..25398042 100644 --- a/backend/src/lib.rs +++ b/backend/src/lib.rs @@ -10,7 +10,6 @@ use tokio::sync::RwLock; use crate::settings::models::{GeneralSettings, Settings}; pub mod authentication; -pub mod cli; pub mod constants; pub mod error; pub mod frontend; @@ -21,6 +20,7 @@ pub mod repository; pub mod settings; pub mod storage; pub mod system; +#[cfg(feature = "updater")] pub mod updater; pub mod utils; @@ -36,7 +36,7 @@ pub struct Version { /// What the local config says the version is pub installed: semver::Version, /// The Cargo Build Version - pub cargo_version: &'static str, + pub cargo_version: semver::Version, pub git_branch: &'static str, pub git_commit: &'static str, /// The channel rust is in @@ -53,7 +53,7 @@ impl Version { pub fn new(installed: semver::Version) -> Version { Version { installed, - cargo_version: env!("VERGEN_BUILD_SEMVER"), + cargo_version: semver::Version::parse(env!("VERGEN_BUILD_SEMVER")).unwrap(), git_branch: env!("VERGEN_GIT_BRANCH"), git_commit: env!("VERGEN_GIT_SHA"), mode: env!("VERGEN_RUSTC_CHANNEL"), diff --git a/backend/src/repository/raw/mod.rs b/backend/src/repository/raw/mod.rs index 208ccd95..5614a3d5 100644 --- a/backend/src/repository/raw/mod.rs +++ b/backend/src/repository/raw/mod.rs @@ -7,12 +7,20 @@ use async_trait::async_trait; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::sync::Arc; - +use actix_web::Error; +use actix_web::http::header::HeaderMap; +use bytes::Bytes; +use sea_orm::DatabaseConnection; +use crate::authentication::Authentication; +use crate::repository::response::RepoResponse; +use crate::storage::file::StorageFileResponse; +use crate::system::permissions::permissions_checker::CanIDo; #[derive(Debug)] pub struct RawHandler { config: RepositoryConfig, storage: Arc, } + impl RawHandler { pub async fn create( config: RepositoryConfig, @@ -21,6 +29,7 @@ impl RawHandler { Ok(RawHandler { config, storage }) } } + impl Clone for RawHandler { fn clone(&self) -> Self { RawHandler { @@ -42,12 +51,41 @@ impl Repository for RawHandler { fn get_storage(&self) -> &StorageType { &self.storage } + + async fn handle_get(&self, path: &str, _: &HeaderMap, conn: &DatabaseConnection, authentication: Authentication) -> Result { + crate::helpers::read_check!(authentication, conn, self.config); + + let response = self + .storage + .get_file_as_response(&self.config, path) + .await + .map_err(InternalError::from)?; + Ok(RepoResponse::FileResponse(response)) + } + async fn handle_put(&self, path: &str, _: &HeaderMap, conn: &DatabaseConnection, authentication: Authentication, bytes: Bytes) -> Result { + let _ = crate::helpers::write_check!(authentication, conn, self.config); + let exists = self + .storage + .save_file(&self.config, bytes.as_ref(), path) + .await + .map_err(InternalError::from)?; + // Everything was ok + Ok(RepoResponse::PUTResponse( + exists, + format!( + "/storages/{}/{}/{}", + &self.storage.storage_config().generic_config.id, + &self.config.name, + path + ), + )) + } } + #[derive(Debug, Serialize, Deserialize, Clone, Default, JsonSchema)] pub struct RawSettings {} impl RepositoryConfigType for RawSettings { - fn config_name() -> &'static str { "raw.json" } @@ -62,18 +100,14 @@ impl CreateRepository for RawHandler { name: impl Into, storage: Arc, ) -> Result<(Self, Self::Config), Self::Error> - where - Self: Sized, + where + Self: Sized, { - let repository_config = RepositoryConfig { - name: name.into(), - repository_type: RepositoryType::Raw, - storage: storage.storage_config().generic_config.id.clone(), - visibility: Default::default(), - active: true, - require_token_over_basic: false, - created: get_current_time(), - }; + let repository_config = RepositoryConfig::new( + name.into(), + RepositoryType::Raw, + storage.storage_config().generic_config.id.clone(), + ); Ok(( RawHandler { config: repository_config, diff --git a/backend/src/settings/models.rs b/backend/src/settings/models.rs index a64dd713..c6365cc5 100644 --- a/backend/src/settings/models.rs +++ b/backend/src/settings/models.rs @@ -31,20 +31,14 @@ pub struct Settings { #[derive(Debug, Deserialize, Serialize, Clone)] pub struct Internal { pub installed: bool, - pub version: String, -} - -impl Internal { - pub fn parse_version(&self) -> Result { - semver::Version::parse(&self.version) - } + pub version: Version, } impl Default for Internal { fn default() -> Self { Self { installed: true, - version: env!("CARGO_PKG_VERSION").to_string(), + version: Version::parse(env!("CARGO_PKG_VERSION")).unwrap(), } } } @@ -55,6 +49,7 @@ pub enum Database { Mysql(MysqlSettings), Sqlite(SqliteSettings), } + #[allow(clippy::from_over_into)] impl Into for Database { fn into(self) -> ConnectOptions { @@ -84,18 +79,22 @@ pub struct MysqlSettings { pub host: String, pub database: String, } + #[derive(Debug, Deserialize, Serialize, Clone)] pub struct SqliteSettings { pub database_file: PathBuf, } + impl Display for SqliteSettings { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "sqlite:{}", self.database_file.display()) } } + #[derive(Debug, Deserialize, Serialize, Clone)] pub struct Application { pub log: String, + pub frontend: String, pub address: String, pub app_url: String, pub max_upload: usize, @@ -111,6 +110,7 @@ impl Default for Application { create_dir_all(&buf).unwrap(); Self { log: "./".to_string(), + frontend: "frontend".to_string(), address: "0.0.0.0:6742".to_string(), app_url: "http://127.0.0.1:6742".to_string(), max_upload: 1024, @@ -121,6 +121,7 @@ impl Default for Application { } } } + #[derive(Debug, Deserialize, Serialize, Clone)] pub struct GeneralSettings { pub database: Database, diff --git a/backend/src/updater/mod.rs b/backend/src/updater/mod.rs index a0b957bf..0acf77f9 100644 --- a/backend/src/updater/mod.rs +++ b/backend/src/updater/mod.rs @@ -1,11 +1,22 @@ -#[cfg(feature = "updater_one-one")] pub mod one_one; use thiserror::Error; #[derive(Error, Clone, Debug)] -pub enum UpdateError {} +pub enum UpdateError { + #[error("{0}")] + Other(&'static str), +} + -pub async fn update(_version: String) -> Result<(), UpdateError> { +pub async fn update(version: impl AsRef) -> Result<(), UpdateError> { + match version.as_ref() { + "1.1" => { + one_one::update().await?; + } + _ => { + return Err(UpdateError::Other("Unsupported version")); + } + } Ok(()) } diff --git a/backend/src/updater/one_one/mod.rs b/backend/src/updater/one_one/mod.rs index 8b137891..1fb0284c 100644 --- a/backend/src/updater/one_one/mod.rs +++ b/backend/src/updater/one_one/mod.rs @@ -1 +1,5 @@ +use crate::updater::UpdateError; +pub async fn update() -> Result<(), UpdateError> { + Ok(()) +} \ No newline at end of file diff --git a/build.sh b/build.sh index c65ba2f9..db353e8b 100644 --- a/build.sh +++ b/build.sh @@ -13,7 +13,7 @@ else fi mkdir -p build/frontend cp -R frontend/dist/* build/frontend -cp backend/target/release/nitro_repo build +cp backend/target/release/nitro_repo_full build cp -R other build cp -R LICENSE build ( From 3a2b2e1fe289d029d543c0143e6481b8ef5b1508 Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Thu, 18 Aug 2022 10:18:37 -0400 Subject: [PATCH 71/76] Windows Installer Work --- backend/src/frontend/controllers.rs | 68 +++++++- backend/wix/main.wxs | 250 ++++++++++++++++++++++++++++ 2 files changed, 314 insertions(+), 4 deletions(-) create mode 100644 backend/wix/main.wxs diff --git a/backend/src/frontend/controllers.rs b/backend/src/frontend/controllers.rs index feb58c75..ae8ce7de 100644 --- a/backend/src/frontend/controllers.rs +++ b/backend/src/frontend/controllers.rs @@ -1,12 +1,12 @@ -use std::fs::read_to_string; -use std::path::Path; +use std::fs::{create_dir_all, File, read_to_string}; +use std::path::{Path, PathBuf}; use actix_files::Files; use actix_web::error::ErrorInternalServerError; use actix_web::web::Data; use actix_web::{web, HttpResponse}; use handlebars::Handlebars; -use log::{debug, trace, warn}; +use log::{debug, error, info, trace, warn}; use serde_json::json; use crate::NitroRepoData; @@ -14,7 +14,23 @@ use crate::NitroRepoData; pub fn init(cfg: &mut web::ServiceConfig) { debug!("Loading Frontend!"); let frontend_string = std::env::var("FRONTEND").unwrap_or_else(|_| "frontend".to_string()); - let frontend_path = Path::new(&frontend_string); + let frontend_path = if frontend_string.ends_with(".zip") { + let zip_to = Path::new(frontend_string.trim_end_matches(".zip")); + info!("Unzipping frontend to {}", zip_to.display()); + if !zip_to.exists() { + create_dir_all(zip_to).unwrap(); + let zip_path = Path::new(&frontend_string); + if let Err(error) = extract(zip_to, zip_path) { + error!("Error extracting frontend: {}",error); + } + zip_to.to_path_buf() + } else { + info!("Frontend already unzipped"); + zip_to.to_path_buf() + } + } else { + Path::new(&frontend_string).to_path_buf() + }; let index = frontend_path.join("index.html"); trace!("Frontend Path {}", frontend_path.display()); if !frontend_path.exists() { @@ -51,3 +67,47 @@ pub async fn frontend_handler( .map_err(ErrorInternalServerError)?; return Ok(HttpResponse::Ok().content_type("text/html").body(content)); } + +fn extract( + extract_to: impl AsRef, + archive: impl AsRef, +) -> Result<(), std::io::Error> +{ + let file = File::open(&archive)?; + + let mut archive = zip::ZipArchive::new(file)?; + + for i in 0..archive.len() { + let mut file = archive.by_index(i)?; + let outpath = match file.enclosed_name() { + Some(path) => { + let components = path.components(); + let buf = components.skip(1).fold(PathBuf::default(), |buf, component| { + buf.join(component) + }); + extract_to.as_ref().join(buf) + } + None => continue, + }; + + if (*file.name()).ends_with('/') { + debug!("File {} extracted to \"{}\"", i, outpath.display()); + create_dir_all(&outpath)?; + } else { + debug!( + "File {} extracted to \"{}\" ({} bytes)", + i, + outpath.display(), + file.size() + ); + if let Some(p) = outpath.parent() { + if !p.exists() { + create_dir_all(&p)?; + } + } + let mut outfile = File::create(&outpath)?; + std::io::copy(&mut file, &mut outfile)?; + } + } + Ok(()) +} diff --git a/backend/wix/main.wxs b/backend/wix/main.wxs new file mode 100644 index 00000000..6d41862b --- /dev/null +++ b/backend/wix/main.wxs @@ -0,0 +1,250 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 1 + + + + + + + + + + + + + + + + + + From 93a9dfa6b2b6c88ee120c4337a8d5a50bcacd76d Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Thu, 18 Aug 2022 10:50:18 -0400 Subject: [PATCH 72/76] Windows Installer Work --- .gitignore | 4 +++- backend/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 2ce42ec1..06fabbc9 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,6 @@ docs/docs/.vitepress/dist/ *.log *.env* *.tar.gz -backend/test/ \ No newline at end of file +backend/test/ +frontend.zip +.vs diff --git a/backend/Cargo.toml b/backend/Cargo.toml index a0a090ea..6239426a 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -81,7 +81,7 @@ schemars = "0.8.10" # Maven Stuff maven-rs = { git = "https://github.com/wyatt-herkamp/maven-rs.git" } this_actix_error = { git = "https://github.com/wyatt-herkamp/this_actix_errors.git" } - +zip = "0.6" [build-dependencies] vergen = { version = "7.0.0" } [features] From 951688c2373f3dab66442663c7ab822cda6edec8 Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Thu, 18 Aug 2022 12:47:16 -0400 Subject: [PATCH 73/76] Installer Work --- backend/Cargo.toml | 4 +- backend/src/bin/simple_installer.rs | 33 ++++++++--- backend/wix/main.wxs | 92 ++++++----------------------- 3 files changed, 45 insertions(+), 84 deletions(-) diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 6239426a..caca6bce 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -15,7 +15,7 @@ name = "nitro_repo_full" required-features = ["multi_storage"] [[bin]] name = "simple_installer" -required-features = ["clap"] +required-features = ["clap", "whoami"] [[bin]] name = "updator" required-features = ["clap"] @@ -71,6 +71,7 @@ webhook_sender = { git = "https://github.com/wyatt-herkamp/webhook_sender.git" } # Installer clap = { version = "3.2.12", features = ["derive"], optional = true } semver = { version = "1", features = ["std", "serde"] } +whoami = { version = "1.2", optional = true } # Cache redis = "0.21.5" comrak = "0.14" @@ -82,6 +83,7 @@ schemars = "0.8.10" maven-rs = { git = "https://github.com/wyatt-herkamp/maven-rs.git" } this_actix_error = { git = "https://github.com/wyatt-herkamp/this_actix_errors.git" } zip = "0.6" + [build-dependencies] vergen = { version = "7.0.0" } [features] diff --git a/backend/src/bin/simple_installer.rs b/backend/src/bin/simple_installer.rs index 1490cd9a..484a4bfa 100644 --- a/backend/src/bin/simple_installer.rs +++ b/backend/src/bin/simple_installer.rs @@ -1,4 +1,4 @@ -use api::settings::models::{Database, GeneralSettings, MysqlSettings, SqliteSettings}; +use api::settings::models::{Application, Database, GeneralSettings, MysqlSettings, SqliteSettings}; use api::system::permissions::{RepositoryPermission, UserPermissions}; use api::system::user::database::ActiveModel; use api::system::user::UserEntity; @@ -10,7 +10,8 @@ use sea_orm::{ConnectOptions, EntityTrait}; use std::env; use std::fs::OpenOptions; -use std::path::Path; +use std::path::{Path, PathBuf}; +use std::process::exit; #[derive(Parser, Debug)] #[clap(author, version, about, long_about = None)] @@ -18,9 +19,13 @@ struct InstallCommand { #[clap(subcommand)] database_type: DatabaseTypes, #[clap(long)] - admin_username: String, + admin_username: Option, #[clap(long)] - admin_password: String, + admin_password: Option, + #[clap(long)] + frontend_path: String, + #[clap(long)] + storage_path: Option, } #[derive(Subcommand, Debug)] @@ -28,6 +33,7 @@ enum DatabaseTypes { Mysql(MysqlInstall), Sqlite(SqliteInstall), } + #[derive(Parser, Debug)] #[clap(author, version, about, long_about = None)] struct SqliteInstall { @@ -47,9 +53,10 @@ struct MysqlInstall { #[clap(long)] pub database: String, } + #[tokio::main] async fn main() { - let install_command = InstallCommand::parse(); + let install_command: InstallCommand = InstallCommand::parse(); let config = match install_command.database_type { DatabaseTypes::Mysql(mysql) => { let mysql_settings = MysqlSettings { @@ -81,13 +88,15 @@ async fn main() { api::utils::run_database_setup(&mut database_conn) .await .expect("Failed to run database setup"); + let option = install_command.admin_username.unwrap_or_else(|| whoami::username()); + let password: &str = install_command.admin_password.as_ref().and_then(|v| Some(v.as_str())).unwrap_or("password"); let user: user::database::ActiveModel = ActiveModel { id: Default::default(), - name: Set(install_command.admin_username.clone()), - username: Set(install_command.admin_username), + name: Set(option.clone()), + username: Set(option), email: Set("admin@nitro_repo.dev".to_string()), - password: Set(hash(install_command.admin_password).unwrap()), + password: Set(hash(password).unwrap()), permissions: Set(UserPermissions { disabled: false, admin: true, @@ -105,7 +114,13 @@ async fn main() { .expect("Failed to insert user"); let general = GeneralSettings { database: config, - application: Default::default(), + application: Application { + frontend: install_command.frontend_path, + storage_location: install_command.storage_path.and_then(|v| Some(PathBuf::from(v))).unwrap_or_else(|| { + env::current_dir().unwrap().join("storages") + }), + ..Application::default() + }, internal: Default::default(), session: Default::default(), }; diff --git a/backend/wix/main.wxs b/backend/wix/main.wxs index 6d41862b..2f8ddd1d 100644 --- a/backend/wix/main.wxs +++ b/backend/wix/main.wxs @@ -130,16 +130,15 @@ Source='$(var.CargoTargetBinDir)\simple_installer.exe' KeyPath='yes'/> - - - - + + + @@ -175,76 +174,21 @@ - - - - - - - - - - - + 1 1 - - - - - - - - - - - - - + + + + - From e5760a620c835fe0d4c7433811d32d5312b69af9 Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Fri, 19 Aug 2022 10:07:02 -0400 Subject: [PATCH 74/76] User Admin Page --- backend/src/system/web/admin.rs | 80 ++++- backend/src/system/web/mod.rs | 2 +- frontend/package-lock.json | 274 +++++++++--------- frontend/package.json | 8 +- frontend/src/components/CreateUser.vue | 204 +++++++------ frontend/src/components/Users.vue | 26 +- .../components/common/model/NitroModal.vue | 26 +- frontend/src/components/common/tabs/Tabs.vue | 2 +- .../components/user/update/UserGeneral.vue | 52 +++- frontend/src/styles/app.css | 26 ++ 10 files changed, 418 insertions(+), 282 deletions(-) diff --git a/backend/src/system/web/admin.rs b/backend/src/system/web/admin.rs index a290214d..cbca59de 100644 --- a/backend/src/system/web/admin.rs +++ b/backend/src/system/web/admin.rs @@ -1,13 +1,22 @@ use crate::authentication::Authentication; use crate::system::permissions::permissions_checker::CanIDo; use crate::system::user::UserModel; -use actix_web::{get, web, HttpResponse}; +use actix_web::{get, post, delete, web, HttpResponse}; -use sea_orm::DatabaseConnection; +use sea_orm::{ColumnTrait, DatabaseConnection, IntoActiveModel, QueryFilter}; +use sea_orm::ActiveValue::Set; use serde::{Deserialize, Serialize}; - +use this_actix_error::ActixError; +use thiserror::Error; +use sea_orm::EntityTrait; use crate::helpers::unwrap_or_not_found; +use crate::system::hash; +use crate::system::permissions::UserPermissions; use crate::system::user::database::UserSafeData; +use crate::utils::get_current_time; +use super::super::user::database::ActiveModel; +use super::super::user::database::*; +use sea_orm::ActiveModelTrait; // struct that derives Serialize and Deserialize contains the number of active storages, number of active repositories, and the number of active users. #[derive(Serialize, Deserialize, Clone, Debug)] @@ -45,3 +54,68 @@ pub async fn get_user( .map_err(actix_web::error::ErrorInternalServerError)?); Ok(HttpResponse::Ok().json(result)) } + +#[derive(Deserialize, Debug)] +pub struct NewUser { + pub name: String, + pub username: String, + pub password: String, + pub email: String, +} + +#[derive(Debug, Error, ActixError)] +pub enum NewUserResponse { + #[error("Username already exists")] + #[status_code(CONFLICT)] + UsernameAlreadyExists, + #[error("Email already exists")] + #[status_code(CONFLICT)] + EmailAlreadyExists, +} + +#[post("/user")] +pub async fn create_user( + auth: Authentication, + database: web::Data, + value: web::Json, +) -> actix_web::Result { + let user = auth.get_user(&database).await??; + user.can_i_edit_users()?; + let user = value.into_inner(); + if Entity::find().filter(Column::Username.eq(user.username.as_str())).one(database.as_ref()) + .await + .map_err(actix_web::error::ErrorInternalServerError)?.is_some() { + return Err(NewUserResponse::UsernameAlreadyExists.into()); + } + if Entity::find().filter(Column::Email.eq(user.email.as_str())).one(database.as_ref()) + .await + .map_err(actix_web::error::ErrorInternalServerError)?.is_some() { + return Err(NewUserResponse::EmailAlreadyExists.into()); + } + let user: ActiveModel = ActiveModel { + id: Default::default(), + name: Set(user.name), + username: Set(user.username), + email: Set(user.email), + password: Set(hash(user.password).unwrap()), + permissions: Set(UserPermissions::default()), + created: Set(get_current_time()), + }; + user.insert(database.as_ref()).await.map_err(actix_web::error::ErrorInternalServerError)?; + Ok(HttpResponse::Created().finish()) +} + +#[delete("user/{id}")] +pub async fn delete_user( + auth: Authentication, + database: web::Data, + id: web::Path, +) -> actix_web::Result { + let user = auth.get_user(&database).await??; + user.can_i_edit_users()?; + let user: Model = unwrap_or_not_found!(Entity::find().filter(Column::Id.eq(id.into_inner())).one(database.as_ref()).await + .map_err(actix_web::error::ErrorInternalServerError)?); + Entity::delete(user.into_active_model()).exec(database.as_ref()).await + .map_err(actix_web::error::ErrorInternalServerError)?; + Ok(HttpResponse::Ok().finish()) +} \ No newline at end of file diff --git a/backend/src/system/web/mod.rs b/backend/src/system/web/mod.rs index ef09a1a8..8baa63de 100644 --- a/backend/src/system/web/mod.rs +++ b/backend/src/system/web/mod.rs @@ -13,5 +13,5 @@ pub fn user_routes(cfg: &mut ServiceConfig) { } pub fn init_user_manager_routes(cfg: &mut ServiceConfig) { - cfg.service(admin::list_users).service(admin::get_user); + cfg.service(admin::list_users).service(admin::get_user).service(admin::create_user).service(admin::delete_user); } diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 056180af..49161de4 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -16,14 +16,14 @@ "@milkdown/prose": "^6.3.2", "@milkdown/theme-nord": "^6.3.2", "@milkdown/vue": "^6.3.2", - "@uppy/drag-drop": "^2.1.1", - "@uppy/vue": "^0.4.8", + "@uppy/drag-drop": "^2.1.2", + "@uppy/vue": "^0.4.9", "axios": "^0.27.2", "core-js": "^3.24.1", "fast-xml-parser": "^4.0.9", "highlight.js": "^11.6.0", "json-editor-vue": "^0.4.13", - "pinia": "^2.0.18", + "pinia": "^2.0.19", "vanilla-jsoneditor": "^0.6.3", "vite-plugin-ejs": "^1.5.0", "vue": "^3.2.37", @@ -54,7 +54,7 @@ "tailwindcss": "^3.1.8", "typescript": "^4.7.4", "unplugin-vue-components": "^0.22.4", - "vite": "^3.0.8" + "vite": "^3.0.9" } }, "../nitro_repo-api-wrapper": { @@ -1281,14 +1281,14 @@ } }, "node_modules/@uppy/core": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@uppy/core/-/core-2.3.1.tgz", - "integrity": "sha512-KV04X7ueYbYX1p37/i3QsoQSw8IDP8Yb+Bh9KNN0X2Vcun6K2VnNjhVtPmPXtyjDZooK7lVIqhRX8TZWcSfgSQ==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@uppy/core/-/core-2.3.3.tgz", + "integrity": "sha512-oTFYZT02dIoUGm8Ar6+Tg/xbL8MliwiPQdiuoCimPBmY19ZhuJm/K4wEYZ6nOFeYsgBWYi1yWfsmdx8LvFVx4g==", "peer": true, "dependencies": { "@transloadit/prettier-bytes": "0.0.7", - "@uppy/store-default": "^2.1.0", - "@uppy/utils": "^4.1.0", + "@uppy/store-default": "^2.1.1", + "@uppy/utils": "^4.1.2", "lodash.throttle": "^4.1.1", "mime-match": "^1.0.2", "namespace-emitter": "^2.0.1", @@ -1297,16 +1297,16 @@ } }, "node_modules/@uppy/dashboard": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@uppy/dashboard/-/dashboard-2.3.0.tgz", - "integrity": "sha512-q7GaLrYt3Tb+x4R8rARfzBuqPtdf6lKnc5Rg/XW18VOIaQM/UZNuBr+EVGhwuDiQt/1QJz1t2lS2Mx246zJ/qA==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@uppy/dashboard/-/dashboard-2.4.2.tgz", + "integrity": "sha512-PNS/aRDAH446w/EVUsyEFDBhAaxzE113bWEBjFVn5SaXM8/AT2fByZDs+8IDmhTNW93kmfKsEQpl+Bonadu7jg==", "dependencies": { "@transloadit/prettier-bytes": "0.0.7", - "@uppy/informer": "^2.1.0", - "@uppy/provider-views": "^2.1.1", - "@uppy/status-bar": "^2.2.1", - "@uppy/thumbnail-generator": "^2.2.0", - "@uppy/utils": "^4.1.0", + "@uppy/informer": "^2.1.1", + "@uppy/provider-views": "^2.1.3", + "@uppy/status-bar": "^2.2.2", + "@uppy/thumbnail-generator": "^2.2.1", + "@uppy/utils": "^4.1.2", "classnames": "^2.2.6", "is-shallow-equal": "^1.0.1", "lodash.debounce": "^4.0.8", @@ -1315,125 +1315,125 @@ "preact": "^10.5.13" }, "peerDependencies": { - "@uppy/core": "^2.3.0" + "@uppy/core": "^2.3.3" } }, "node_modules/@uppy/drag-drop": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@uppy/drag-drop/-/drag-drop-2.1.1.tgz", - "integrity": "sha512-3cTXzmoMpCJvaM0H59acm/CNkS3y6jr03SYK7u6X/vd3/a6e3XyfaGc/jwKSsGBm+oMLftFKv/inhQLKOZR5CQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@uppy/drag-drop/-/drag-drop-2.1.2.tgz", + "integrity": "sha512-J6hBiYcBc8p6U9PylqtZ+eMJ48yT1qP1Xzon2Pou5AQxQ4D7UAL97OvcjnONpOfp8P7uGmaqXFUubBNgEUCfQg==", "dependencies": { - "@uppy/utils": "^4.1.0", + "@uppy/utils": "^4.1.2", "preact": "^10.5.13" }, "peerDependencies": { - "@uppy/core": "^2.3.0" + "@uppy/core": "^2.3.3" } }, "node_modules/@uppy/file-input": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@uppy/file-input/-/file-input-2.1.1.tgz", - "integrity": "sha512-yqsNxDuOoEm0DP/+jw1osW8t1rkx8wpxRCmea33HyvS/rLAU/5VFKyXPfatw/UnoLKrtcsQTj5BRTXspOoRciQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@uppy/file-input/-/file-input-2.1.2.tgz", + "integrity": "sha512-tdn6HNMnLOC2xpdZYbdXNSjTS9EpLvY97vOfq9SZWkoX/cmZiOf6JfFc3Qm8pS3RRnVmwsdi5usEPbzMQ5RAEg==", "dependencies": { - "@uppy/utils": "^4.1.0", + "@uppy/utils": "^4.1.2", "preact": "^10.5.13" }, "peerDependencies": { - "@uppy/core": "^2.3.0" + "@uppy/core": "^2.3.3" } }, "node_modules/@uppy/informer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@uppy/informer/-/informer-2.1.0.tgz", - "integrity": "sha512-/nR7Dxh1RH1FvKRPQ/xZk1lS3F+lh93xaN6Z9utGg5u1hHREuaHfFTcEXhkeq1/hiKbVYsjNaNZ5aPe7+4flkg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@uppy/informer/-/informer-2.1.1.tgz", + "integrity": "sha512-aSdtJO0QvDGzcWHQ1Kd1hOFLyn+0e8LY82708WGkt8BwYwjmKhCJUuxdPDsCu3I2wpFUSUzpvQ9pik7AajBFjw==", "dependencies": { - "@uppy/utils": "^4.1.0", + "@uppy/utils": "^4.1.2", "preact": "^10.5.13" }, "peerDependencies": { - "@uppy/core": "^2.3.0" + "@uppy/core": "^2.3.3" } }, "node_modules/@uppy/progress-bar": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@uppy/progress-bar/-/progress-bar-2.1.1.tgz", - "integrity": "sha512-Kh/kM5rGUABxwwDRzR3pjDzkNRELES2T3nIBdstRIfWCxlHjIFpgqOkvvNRXKflm2hcYUzTRELgtfi09LuqE9A==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@uppy/progress-bar/-/progress-bar-2.1.2.tgz", + "integrity": "sha512-BzO+LSMDj+daT93yoUhNdkQ1Bq79lSm+hTUcuFpUt397B0ETzUeHUg3wUj39Zu3r7BlO/JmQLbH4NkejK4rYGg==", "dependencies": { - "@uppy/utils": "^4.1.0", + "@uppy/utils": "^4.1.2", "preact": "^10.5.13" }, "peerDependencies": { - "@uppy/core": "^2.3.0" + "@uppy/core": "^2.3.3" } }, "node_modules/@uppy/provider-views": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@uppy/provider-views/-/provider-views-2.1.2.tgz", - "integrity": "sha512-tcIQkP/v7DjrLF6KvUJldafyxHlT+Yc1oH/01N6pu/T249UAUjy3j91ChGGqcjYCTMpvQPQDgskVLBqnWAdzcQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@uppy/provider-views/-/provider-views-2.1.3.tgz", + "integrity": "sha512-IXk8j+0nXxsTLV1KwUJbholiwMYXJ9H2r7pJlBRiu/lB/hgd5t7ENqt2susnepBFQJ+XlaIsuM5YVLgppBwc5w==", "dependencies": { - "@uppy/utils": "^4.1.0", + "@uppy/utils": "^4.1.2", "classnames": "^2.2.6", "preact": "^10.5.13" }, "peerDependencies": { - "@uppy/core": "^2.3.1" + "@uppy/core": "^2.3.3" } }, "node_modules/@uppy/status-bar": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@uppy/status-bar/-/status-bar-2.2.1.tgz", - "integrity": "sha512-jnJ/DSEuWGPU6+m0i2yfGl5cPb6CJnxDtcL6/gXKOyjGeRfriWjeEsRHmEkdK+xLv/AJC//eEfSOCL3N737p0g==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@uppy/status-bar/-/status-bar-2.2.2.tgz", + "integrity": "sha512-XV4/3RyNF42enqPc4wWZupqI1KuGtfdt49waux7kebxaGqNzV+T72o/C+QDDqY/h4mKadrp6p98/BnMefC5QtQ==", "dependencies": { "@transloadit/prettier-bytes": "0.0.7", - "@uppy/utils": "^4.1.0", + "@uppy/utils": "^4.1.2", "classnames": "^2.2.6", "lodash.throttle": "^4.1.1", "preact": "^10.5.13" }, "peerDependencies": { - "@uppy/core": "^2.3.0" + "@uppy/core": "^2.3.3" } }, "node_modules/@uppy/store-default": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@uppy/store-default/-/store-default-2.1.0.tgz", - "integrity": "sha512-BkcR1wGw6Kwbvr8m1tKF9EDDWSTJoTGnVseBF/iW4bzR22assbtxZIE1iroo68UMqYEG4rv63SX4BUEtNvVjdA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@uppy/store-default/-/store-default-2.1.1.tgz", + "integrity": "sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ==", "peer": true }, "node_modules/@uppy/thumbnail-generator": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@uppy/thumbnail-generator/-/thumbnail-generator-2.2.0.tgz", - "integrity": "sha512-ySZoB0tK7sQ/PRSFvU5JLxcq/wVqJM/G95cVdJ2Wv1BzQ7+/wKBEPFgJuHDqgzpgUrHwmc+N0JYVXqfk297DZA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@uppy/thumbnail-generator/-/thumbnail-generator-2.2.1.tgz", + "integrity": "sha512-p8GnoeFef3DYVzKI5deeTSVPw/JCbumvUfSuPfqWmK0id/pGveXNFfVZz9qDxjzDyDMv5FGWxf1cui4ADs52UA==", "dependencies": { - "@uppy/utils": "^4.1.0", + "@uppy/utils": "^4.1.2", "exifr": "^7.0.0" }, "peerDependencies": { - "@uppy/core": "^2.3.0" + "@uppy/core": "^2.3.3" } }, "node_modules/@uppy/utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-4.1.0.tgz", - "integrity": "sha512-C47DUl4uLzmQZdW+VmetIgGRurXuPsvb+/pyYqh9DJn0Phep8u7AOj/tlJA5CHv4pefNHsFjXpaWfSUG3HtW3A==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-4.1.2.tgz", + "integrity": "sha512-rl9aKRE4o2mRKVAhYHHf8uV7BoUOQkvDH6yOaJ4tuHJ6HgPkvxVxqUY8L+yKV1hx4mw6OF9hLIzpW/+TLSfyfQ==", "dependencies": { "lodash.throttle": "^4.1.1" } }, "node_modules/@uppy/vue": { - "version": "0.4.8", - "resolved": "https://registry.npmjs.org/@uppy/vue/-/vue-0.4.8.tgz", - "integrity": "sha512-tOLjLD4E7AzI6ijtCEFgQ3NCJQKBYCTgRDNYdZPapRvM8rNIoN4lOZxkqMbBO20cdZnZ78p1b9DZRffvax1nHg==", - "dependencies": { - "@uppy/dashboard": "^2.3.0", - "@uppy/drag-drop": "^2.1.1", - "@uppy/file-input": "^2.1.1", - "@uppy/progress-bar": "^2.1.1", - "@uppy/status-bar": "^2.2.1", + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/@uppy/vue/-/vue-0.4.9.tgz", + "integrity": "sha512-zsonVh4NULfwTEUWMs/BOux8big1kzCartgwmzhyyvTud7Bv+mvjCHvRb6J+uo4QnUuKF9489HcUiWTRzbA2KQ==", + "dependencies": { + "@uppy/dashboard": "^2.4.2", + "@uppy/drag-drop": "^2.1.2", + "@uppy/file-input": "^2.1.2", + "@uppy/progress-bar": "^2.1.2", + "@uppy/status-bar": "^2.2.2", "shallow-equal": "^1.2.1" }, "peerDependencies": { - "@uppy/core": "^2.3.0", + "@uppy/core": "^2.3.3", "vue": ">=2.6.11" } }, @@ -4593,9 +4593,9 @@ } }, "node_modules/pinia": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.18.tgz", - "integrity": "sha512-I5MW05UVX6a5Djka136oH3VzYFiZUgeOApBwFjMx6pL91eHtGVlE3adjNUKLgtwGnrxiBRuJ8+4R3LKJKwnyZg==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.19.tgz", + "integrity": "sha512-Q/UQrmFLDMdlCkLfM5rGw1Ug0A7dy0G7NtBusMQSK+TNjf3CV/pO0RqblNIfuurWl42byTjM6HIemCWOfo8KXA==", "dependencies": { "@vue/devtools-api": "^6.2.1", "vue-demi": "*" @@ -5766,9 +5766,9 @@ } }, "node_modules/vite": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.0.8.tgz", - "integrity": "sha512-AOZ4eN7mrkJiOLuw8IA7piS4IdOQyQCA81GxGsAQvAZzMRi9ZwGB3TOaYsj4uLAWK46T5L4AfQ6InNGlxX30IQ==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.0.9.tgz", + "integrity": "sha512-waYABTM+G6DBTCpYAxvevpG50UOlZuynR0ckTK5PawNVt7ebX6X7wNXHaGIO6wYYFXSM7/WcuFuO2QzhBB6aMw==", "dev": true, "dependencies": { "esbuild": "^0.14.47", @@ -6986,14 +6986,14 @@ } }, "@uppy/core": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@uppy/core/-/core-2.3.1.tgz", - "integrity": "sha512-KV04X7ueYbYX1p37/i3QsoQSw8IDP8Yb+Bh9KNN0X2Vcun6K2VnNjhVtPmPXtyjDZooK7lVIqhRX8TZWcSfgSQ==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@uppy/core/-/core-2.3.3.tgz", + "integrity": "sha512-oTFYZT02dIoUGm8Ar6+Tg/xbL8MliwiPQdiuoCimPBmY19ZhuJm/K4wEYZ6nOFeYsgBWYi1yWfsmdx8LvFVx4g==", "peer": true, "requires": { "@transloadit/prettier-bytes": "0.0.7", - "@uppy/store-default": "^2.1.0", - "@uppy/utils": "^4.1.0", + "@uppy/store-default": "^2.1.1", + "@uppy/utils": "^4.1.2", "lodash.throttle": "^4.1.1", "mime-match": "^1.0.2", "namespace-emitter": "^2.0.1", @@ -7002,16 +7002,16 @@ } }, "@uppy/dashboard": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@uppy/dashboard/-/dashboard-2.3.0.tgz", - "integrity": "sha512-q7GaLrYt3Tb+x4R8rARfzBuqPtdf6lKnc5Rg/XW18VOIaQM/UZNuBr+EVGhwuDiQt/1QJz1t2lS2Mx246zJ/qA==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@uppy/dashboard/-/dashboard-2.4.2.tgz", + "integrity": "sha512-PNS/aRDAH446w/EVUsyEFDBhAaxzE113bWEBjFVn5SaXM8/AT2fByZDs+8IDmhTNW93kmfKsEQpl+Bonadu7jg==", "requires": { "@transloadit/prettier-bytes": "0.0.7", - "@uppy/informer": "^2.1.0", - "@uppy/provider-views": "^2.1.1", - "@uppy/status-bar": "^2.2.1", - "@uppy/thumbnail-generator": "^2.2.0", - "@uppy/utils": "^4.1.0", + "@uppy/informer": "^2.1.1", + "@uppy/provider-views": "^2.1.3", + "@uppy/status-bar": "^2.2.2", + "@uppy/thumbnail-generator": "^2.2.1", + "@uppy/utils": "^4.1.2", "classnames": "^2.2.6", "is-shallow-equal": "^1.0.1", "lodash.debounce": "^4.0.8", @@ -7021,96 +7021,96 @@ } }, "@uppy/drag-drop": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@uppy/drag-drop/-/drag-drop-2.1.1.tgz", - "integrity": "sha512-3cTXzmoMpCJvaM0H59acm/CNkS3y6jr03SYK7u6X/vd3/a6e3XyfaGc/jwKSsGBm+oMLftFKv/inhQLKOZR5CQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@uppy/drag-drop/-/drag-drop-2.1.2.tgz", + "integrity": "sha512-J6hBiYcBc8p6U9PylqtZ+eMJ48yT1qP1Xzon2Pou5AQxQ4D7UAL97OvcjnONpOfp8P7uGmaqXFUubBNgEUCfQg==", "requires": { - "@uppy/utils": "^4.1.0", + "@uppy/utils": "^4.1.2", "preact": "^10.5.13" } }, "@uppy/file-input": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@uppy/file-input/-/file-input-2.1.1.tgz", - "integrity": "sha512-yqsNxDuOoEm0DP/+jw1osW8t1rkx8wpxRCmea33HyvS/rLAU/5VFKyXPfatw/UnoLKrtcsQTj5BRTXspOoRciQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@uppy/file-input/-/file-input-2.1.2.tgz", + "integrity": "sha512-tdn6HNMnLOC2xpdZYbdXNSjTS9EpLvY97vOfq9SZWkoX/cmZiOf6JfFc3Qm8pS3RRnVmwsdi5usEPbzMQ5RAEg==", "requires": { - "@uppy/utils": "^4.1.0", + "@uppy/utils": "^4.1.2", "preact": "^10.5.13" } }, "@uppy/informer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@uppy/informer/-/informer-2.1.0.tgz", - "integrity": "sha512-/nR7Dxh1RH1FvKRPQ/xZk1lS3F+lh93xaN6Z9utGg5u1hHREuaHfFTcEXhkeq1/hiKbVYsjNaNZ5aPe7+4flkg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@uppy/informer/-/informer-2.1.1.tgz", + "integrity": "sha512-aSdtJO0QvDGzcWHQ1Kd1hOFLyn+0e8LY82708WGkt8BwYwjmKhCJUuxdPDsCu3I2wpFUSUzpvQ9pik7AajBFjw==", "requires": { - "@uppy/utils": "^4.1.0", + "@uppy/utils": "^4.1.2", "preact": "^10.5.13" } }, "@uppy/progress-bar": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@uppy/progress-bar/-/progress-bar-2.1.1.tgz", - "integrity": "sha512-Kh/kM5rGUABxwwDRzR3pjDzkNRELES2T3nIBdstRIfWCxlHjIFpgqOkvvNRXKflm2hcYUzTRELgtfi09LuqE9A==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@uppy/progress-bar/-/progress-bar-2.1.2.tgz", + "integrity": "sha512-BzO+LSMDj+daT93yoUhNdkQ1Bq79lSm+hTUcuFpUt397B0ETzUeHUg3wUj39Zu3r7BlO/JmQLbH4NkejK4rYGg==", "requires": { - "@uppy/utils": "^4.1.0", + "@uppy/utils": "^4.1.2", "preact": "^10.5.13" } }, "@uppy/provider-views": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@uppy/provider-views/-/provider-views-2.1.2.tgz", - "integrity": "sha512-tcIQkP/v7DjrLF6KvUJldafyxHlT+Yc1oH/01N6pu/T249UAUjy3j91ChGGqcjYCTMpvQPQDgskVLBqnWAdzcQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@uppy/provider-views/-/provider-views-2.1.3.tgz", + "integrity": "sha512-IXk8j+0nXxsTLV1KwUJbholiwMYXJ9H2r7pJlBRiu/lB/hgd5t7ENqt2susnepBFQJ+XlaIsuM5YVLgppBwc5w==", "requires": { - "@uppy/utils": "^4.1.0", + "@uppy/utils": "^4.1.2", "classnames": "^2.2.6", "preact": "^10.5.13" } }, "@uppy/status-bar": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@uppy/status-bar/-/status-bar-2.2.1.tgz", - "integrity": "sha512-jnJ/DSEuWGPU6+m0i2yfGl5cPb6CJnxDtcL6/gXKOyjGeRfriWjeEsRHmEkdK+xLv/AJC//eEfSOCL3N737p0g==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@uppy/status-bar/-/status-bar-2.2.2.tgz", + "integrity": "sha512-XV4/3RyNF42enqPc4wWZupqI1KuGtfdt49waux7kebxaGqNzV+T72o/C+QDDqY/h4mKadrp6p98/BnMefC5QtQ==", "requires": { "@transloadit/prettier-bytes": "0.0.7", - "@uppy/utils": "^4.1.0", + "@uppy/utils": "^4.1.2", "classnames": "^2.2.6", "lodash.throttle": "^4.1.1", "preact": "^10.5.13" } }, "@uppy/store-default": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@uppy/store-default/-/store-default-2.1.0.tgz", - "integrity": "sha512-BkcR1wGw6Kwbvr8m1tKF9EDDWSTJoTGnVseBF/iW4bzR22assbtxZIE1iroo68UMqYEG4rv63SX4BUEtNvVjdA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@uppy/store-default/-/store-default-2.1.1.tgz", + "integrity": "sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ==", "peer": true }, "@uppy/thumbnail-generator": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@uppy/thumbnail-generator/-/thumbnail-generator-2.2.0.tgz", - "integrity": "sha512-ySZoB0tK7sQ/PRSFvU5JLxcq/wVqJM/G95cVdJ2Wv1BzQ7+/wKBEPFgJuHDqgzpgUrHwmc+N0JYVXqfk297DZA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@uppy/thumbnail-generator/-/thumbnail-generator-2.2.1.tgz", + "integrity": "sha512-p8GnoeFef3DYVzKI5deeTSVPw/JCbumvUfSuPfqWmK0id/pGveXNFfVZz9qDxjzDyDMv5FGWxf1cui4ADs52UA==", "requires": { - "@uppy/utils": "^4.1.0", + "@uppy/utils": "^4.1.2", "exifr": "^7.0.0" } }, "@uppy/utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-4.1.0.tgz", - "integrity": "sha512-C47DUl4uLzmQZdW+VmetIgGRurXuPsvb+/pyYqh9DJn0Phep8u7AOj/tlJA5CHv4pefNHsFjXpaWfSUG3HtW3A==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-4.1.2.tgz", + "integrity": "sha512-rl9aKRE4o2mRKVAhYHHf8uV7BoUOQkvDH6yOaJ4tuHJ6HgPkvxVxqUY8L+yKV1hx4mw6OF9hLIzpW/+TLSfyfQ==", "requires": { "lodash.throttle": "^4.1.1" } }, "@uppy/vue": { - "version": "0.4.8", - "resolved": "https://registry.npmjs.org/@uppy/vue/-/vue-0.4.8.tgz", - "integrity": "sha512-tOLjLD4E7AzI6ijtCEFgQ3NCJQKBYCTgRDNYdZPapRvM8rNIoN4lOZxkqMbBO20cdZnZ78p1b9DZRffvax1nHg==", - "requires": { - "@uppy/dashboard": "^2.3.0", - "@uppy/drag-drop": "^2.1.1", - "@uppy/file-input": "^2.1.1", - "@uppy/progress-bar": "^2.1.1", - "@uppy/status-bar": "^2.2.1", + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/@uppy/vue/-/vue-0.4.9.tgz", + "integrity": "sha512-zsonVh4NULfwTEUWMs/BOux8big1kzCartgwmzhyyvTud7Bv+mvjCHvRb6J+uo4QnUuKF9489HcUiWTRzbA2KQ==", + "requires": { + "@uppy/dashboard": "^2.4.2", + "@uppy/drag-drop": "^2.1.2", + "@uppy/file-input": "^2.1.2", + "@uppy/progress-bar": "^2.1.2", + "@uppy/status-bar": "^2.2.2", "shallow-equal": "^1.2.1" } }, @@ -9276,9 +9276,9 @@ "dev": true }, "pinia": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.18.tgz", - "integrity": "sha512-I5MW05UVX6a5Djka136oH3VzYFiZUgeOApBwFjMx6pL91eHtGVlE3adjNUKLgtwGnrxiBRuJ8+4R3LKJKwnyZg==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.19.tgz", + "integrity": "sha512-Q/UQrmFLDMdlCkLfM5rGw1Ug0A7dy0G7NtBusMQSK+TNjf3CV/pO0RqblNIfuurWl42byTjM6HIemCWOfo8KXA==", "requires": { "@vue/devtools-api": "^6.2.1", "vue-demi": "*" @@ -10072,9 +10072,9 @@ } }, "vite": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.0.8.tgz", - "integrity": "sha512-AOZ4eN7mrkJiOLuw8IA7piS4IdOQyQCA81GxGsAQvAZzMRi9ZwGB3TOaYsj4uLAWK46T5L4AfQ6InNGlxX30IQ==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.0.9.tgz", + "integrity": "sha512-waYABTM+G6DBTCpYAxvevpG50UOlZuynR0ckTK5PawNVt7ebX6X7wNXHaGIO6wYYFXSM7/WcuFuO2QzhBB6aMw==", "dev": true, "requires": { "esbuild": "^0.14.47", diff --git a/frontend/package.json b/frontend/package.json index 227bb7ab..344cb18e 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -18,14 +18,14 @@ "@milkdown/prose": "^6.3.2", "@milkdown/theme-nord": "^6.3.2", "@milkdown/vue": "^6.3.2", - "@uppy/drag-drop": "^2.1.1", - "@uppy/vue": "^0.4.8", + "@uppy/drag-drop": "^2.1.2", + "@uppy/vue": "^0.4.9", "axios": "^0.27.2", "core-js": "^3.24.1", "fast-xml-parser": "^4.0.9", "highlight.js": "^11.6.0", "json-editor-vue": "^0.4.13", - "pinia": "^2.0.18", + "pinia": "^2.0.19", "vanilla-jsoneditor": "^0.6.3", "vite-plugin-ejs": "^1.5.0", "vue": "^3.2.37", @@ -56,6 +56,6 @@ "tailwindcss": "^3.1.8", "typescript": "^4.7.4", "unplugin-vue-components": "^0.22.4", - "vite": "^3.0.8" + "vite": "^3.0.9" } } diff --git a/frontend/src/components/CreateUser.vue b/frontend/src/components/CreateUser.vue index 0b9a872c..0214b941 100644 --- a/frontend/src/components/CreateUser.vue +++ b/frontend/src/components/CreateUser.vue @@ -1,109 +1,83 @@ diff --git a/frontend/src/styles/app.css b/frontend/src/styles/app.css index 5dc79f4e..0ecff409 100644 --- a/frontend/src/styles/app.css +++ b/frontend/src/styles/app.css @@ -15,3 +15,29 @@ body { min-height: 100%; @apply bg-primary; } +.modal > .header { + @apply flex; + @apply flex-row; + @apply w-full; + @apply mb-5; +} +.modal > .header > button { + @apply text-quaternary; +} +.modal > .header > h1 { + @apply text-xl; + @apply text-quaternary; + @apply text-left; + @apply flex-grow; +} +.modal { + @apply border; + @apply bg-primary; + @apply border-primary/90; + @apply pt-5; + @apply px-5; + @apply rounded-2xl; + @apply shadow-xl; + @apply text-center; + @apply w-full; +} From de472dfccd11a400210a3b7188ccae3912a6dd75 Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Fri, 19 Aug 2022 11:36:04 -0400 Subject: [PATCH 75/76] Starting to work on the docker stuff --- .dockerignore | 9 ++++++++ .gitignore | 2 +- Dockerfile | 35 ++++++++++++++++++++++------- backend/src/bin/simple_installer.rs | 17 +++++++++++++- docker-compose.yml | 16 +++++++++++++ entrypoint.sh | 7 ++++++ 6 files changed, 76 insertions(+), 10 deletions(-) create mode 100644 .dockerignore create mode 100644 docker-compose.yml create mode 100644 entrypoint.sh diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..efcbdcc9 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +backend/target +backend/test/ +nrc/ +docs/ +.idea + +log +frontend/node_modules +frontend/dist \ No newline at end of file diff --git a/.gitignore b/.gitignore index 06fabbc9..f32a271f 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,4 @@ docs/docs/.vitepress/dist/ *.tar.gz backend/test/ frontend.zip -.vs +backend/src/authentication/.vs diff --git a/Dockerfile b/Dockerfile index 3ec71f9f..a373361a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,33 @@ -FROM rust:latest +FROM rust:latest AS build +COPY . /home/build +WORKDIR /home/build -LABEL author="Wyatt Herkamp" maintaner="wherkamp@kingtux.me" +LABEL org.label-schema.name="nitro_repo" \ + org.label-schema.vendor="wyatt-herkamp" \ + org.label-schema.schema-version="1.0" -RUN apt-get update -y \ apt-get install git -RUN cargo install fnm -RUN git pull https://github.com/wyatt-herkamp/nitro_repo.git -RUN git checkout dev +RUN apt-get update; apt-get install -y curl \ + && curl -sL https://deb.nodesource.com/setup_18.x | bash - \ + && apt-get install -y nodejs \ + && curl -L https://www.npmjs.com/install.sh | sh -RUN cd /backend && cargo build --release && cd .. -RUN cd /frontend && fnm use && npm install && npm run build +WORKDIR /home/build/backend +RUN cargo build --release --features multi_storage,ssl,clap,whoami +# Build Frontend +WORKDIR /home/build/frontend +RUN npm install +RUN npm run build +# The Final Image +FROM alpine:latest +RUN mkdir -p /app/data/storages && mkdir -p /var/log/nitro_repo +VOLUME /app/data +WORKDIR /app +COPY --from=build /home/build/nitro_repo/backend/target/release/nitro_repo_full nitro_repo_full +COPY --from=build /home/build/nitro_repo/backend/target/release/simple_installer simple_installer +COPY --from=build /home/build/nitro_repo/frontend/dist frontend +COPY --from=build /home/build/nitro_repo/entrypoint.sh entrypoint.sh +ENTRYPOINT ["/bin/sh", "entrypoint.sh"] +CMD [] \ No newline at end of file diff --git a/backend/src/bin/simple_installer.rs b/backend/src/bin/simple_installer.rs index 484a4bfa..72d9c391 100644 --- a/backend/src/bin/simple_installer.rs +++ b/backend/src/bin/simple_installer.rs @@ -26,6 +26,11 @@ struct InstallCommand { frontend_path: String, #[clap(long)] storage_path: Option, + #[clap(long)] + ignore_if_installed: Option, + #[clap(long)] + log_dir: Option, + } #[derive(Subcommand, Debug)] @@ -57,6 +62,15 @@ struct MysqlInstall { #[tokio::main] async fn main() { let install_command: InstallCommand = InstallCommand::parse(); + + let working_directory = env::current_dir().unwrap(); + if working_directory.join("nitro_repo.toml").exists() { + if install_command.ignore_if_installed.unwrap_or(true) { + return; + } else { + exit(1); + } + } let config = match install_command.database_type { DatabaseTypes::Mysql(mysql) => { let mysql_settings = MysqlSettings { @@ -115,6 +129,7 @@ async fn main() { let general = GeneralSettings { database: config, application: Application { + log: install_command.log_dir.unwrap_or("./logs".to_string()).to_string(), frontend: install_command.frontend_path, storage_location: install_command.storage_path.and_then(|v| Some(PathBuf::from(v))).unwrap_or_else(|| { env::current_dir().unwrap().join("storages") @@ -124,6 +139,6 @@ async fn main() { internal: Default::default(), session: Default::default(), }; - api::install::install_data(env::current_dir().unwrap(), general) + api::install::install_data(working_directory, general) .expect("Failed to install data"); } diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..21563381 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,16 @@ +version: "3.9" +services: + nitro_repo: + image: nitro_repo:1.1.0 + build: + context: . + dockerfile: Dockerfile + ports: + - ${PORT}:${PORT} + volumes: + - nitro_repo-data:/app/data + restart: unless-stopped + stdin_open: true + tty: true +volumes: + nitro_repo-data: { } \ No newline at end of file diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 00000000..25cc738b --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,7 @@ +chown -R nitro_repo:nitro_repo /app +chown -R nitro_repo:nitro_repo /var/log/nitro_repo + +cd data +# shellcheck disable=SC2093 +exec runuser -u nitro_repo -- ../simple_installer --log-dir /var/log/nitro_repo --storage-path /app/data/storages --frontend-path /app/frontend sqlite --database-file /app/data/database.db +exec runuser -u nitro_repo -- ../nitro_repo_full From 011583077cb1ed9e7f896f65fdcfa4b5ac556d85 Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Fri, 19 Aug 2022 12:35:59 -0400 Subject: [PATCH 76/76] Rebuilt Badge Code --- backend/src/repository/web/multi/mod.rs | 21 +++++++----- .../web/multi/repository_handler.rs | 34 +++++++++++++++++++ frontend/src/api/repository/BadgeGen.ts | 4 +-- .../src/components/project/ViewProject.vue | 1 - .../components/project/badge/ProjectBadge.vue | 12 +++---- .../components/repo/badge/RepositoryBadge.vue | 4 +-- .../repo/types/maven/MavenRepoInfo.vue | 2 +- 7 files changed, 55 insertions(+), 23 deletions(-) diff --git a/backend/src/repository/web/multi/mod.rs b/backend/src/repository/web/multi/mod.rs index 8ccf16bb..0b3ae8d9 100644 --- a/backend/src/repository/web/multi/mod.rs +++ b/backend/src/repository/web/multi/mod.rs @@ -4,6 +4,7 @@ pub mod admin; pub mod public; pub mod repository_handler; pub mod settings; + use crate::repository; pub fn init_repository_handlers(cfg: &mut web::ServiceConfig) { @@ -16,16 +17,18 @@ pub fn init_repository_handlers(cfg: &mut web::ServiceConfig) { "/storages/{storage}/{repository}/{file:.*}", "/storages/{storage}/{repository}/", ]) - .route(web::get().to(repository_handler::get_repository)) - .route(web::put().to(repository_handler::put_repository)) - .route(web::head().to(repository_handler::head_repository)) - .route(web::patch().to(repository_handler::patch_repository)) - .route(web::post().to(repository_handler::post_repository)), + .route(web::get().to(repository_handler::get_repository)) + .route(web::put().to(repository_handler::put_repository)) + .route(web::head().to(repository_handler::head_repository)) + .route(web::patch().to(repository_handler::patch_repository)) + .route(web::post().to(repository_handler::post_repository)), ) - .service( - web::resource("/stage/repositories/{storage}/{repository}/{file:.*}") - .route(web::put().to(repository_handler::stage_repository)), - ); + .service( + web::resource("/stage/repositories/{storage}/{repository}/{file:.*}") + .route(web::put().to(repository_handler::stage_repository)), + ) + .service(web::resource("/badge/repositories/{storage}/{repository}/{file:.*}") + .route(web::get().to(repository_handler::badge_repository))); } pub fn init_admin(cfg: &mut web::ServiceConfig) { diff --git a/backend/src/repository/web/multi/repository_handler.rs b/backend/src/repository/web/multi/repository_handler.rs index 96ca2091..28a72bda 100644 --- a/backend/src/repository/web/multi/repository_handler.rs +++ b/backend/src/repository/web/multi/repository_handler.rs @@ -1,12 +1,17 @@ use actix_web::web::Bytes; use actix_web::{web, HttpRequest, HttpResponse}; +use actix_web::http::header::CONTENT_TYPE; +use badge_maker::{Badge, BadgeBuilder}; use sea_orm::DatabaseConnection; use serde::Deserialize; use crate::authentication::Authentication; use crate::repository::handler::Repository; +use crate::repository::nitro::nitro_repository::NitroRepositoryHandler; use crate::repository::response::RepoResponse; +use crate::repository::settings::badge::BadgeSettings; +use crate::repository::settings::{RepositoryConfig, RepositoryConfigHandler}; use crate::repository::staging::StageHandler; use crate::storage::models::Storage; use crate::storage::multi::MultiStorageController; @@ -20,6 +25,7 @@ pub struct GetPath { #[serde(default)] pub file: String, } + impl GetPath { pub fn into_inner(self) -> (String, String, String) { (self.storage, self.repository, self.file) @@ -41,6 +47,33 @@ pub async fn get_repository( .await } +pub async fn badge_repository( + storages: web::Data>, + path: web::Path, +) -> actix_web::Result { + let (storage_name, repository_name, file) = path.into_inner().into_inner(); + let storage = crate::helpers::get_storage!(storages, storage_name); + let repository = crate::helpers::get_repository!(storage, repository_name); + if !RepositoryConfigHandler::::supports_config(repository.as_ref()) || !NitroRepositoryHandler::supports_nitro(repository.as_ref()) { + return Ok(HttpResponse::BadRequest().finish()); + } + let settings = RepositoryConfigHandler::::get(repository.as_ref()); + let badge: Badge = if file.eq("nitro_repo_badge") { + let string = repository.get_repository().repository_type.to_string(); + BadgeBuilder::new().color_parse(&settings.color).label_color_parse(&settings.label_color). + style(settings.style.to_badge_maker_style()).label(&repository.get_repository().name).message(&string).build().unwrap() + } else { + if let Some(some) = NitroRepositoryHandler::latest_version(repository.as_ref(), &file).await? { + BadgeBuilder::new().color_parse(&settings.color).label_color_parse(&settings.label_color). + style(settings.style.to_badge_maker_style()).label(&repository.get_repository().name).message(&some).build().unwrap() + } else { + return Ok(HttpResponse::NotFound().finish()); + } + }; + + Ok(HttpResponse::Ok().append_header((CONTENT_TYPE, "image/svg+xml")).body(badge.svg())) +} + pub async fn put_repository( pool: web::Data, storages: web::Data>, @@ -56,6 +89,7 @@ pub async fn put_repository( .handle_put(&file, r.headers(), pool.get_ref(), auth, bytes) .await } + pub async fn stage_repository( pool: web::Data, storages: web::Data>, diff --git a/frontend/src/api/repository/BadgeGen.ts b/frontend/src/api/repository/BadgeGen.ts index dcf1a6da..2c23da64 100644 --- a/frontend/src/api/repository/BadgeGen.ts +++ b/frontend/src/api/repository/BadgeGen.ts @@ -34,8 +34,8 @@ export function createProjectSnippet( projectName: string ): SnippetInfo[] { const url = apiURL; - const badgeURL = `${url}badge/${storage}/${repository}/${project}/badge`; - const appURL = `${url}project/${storage}/${repository}/${projectName}`; + const badgeURL = `${url}/badge/repositories/${storage}/${repository}/${project}`; + const appURL = `${url}/project/${storage}/${repository}/${project}`; const text = `${repository} Repository`; return [ { diff --git a/frontend/src/components/project/ViewProject.vue b/frontend/src/components/project/ViewProject.vue index f8ad8c0f..e3201a32 100644 --- a/frontend/src/components/project/ViewProject.vue +++ b/frontend/src/components/project/ViewProject.vue @@ -40,7 +40,6 @@ storage: storage, repository: repositoryName, project: projectName, - version: version, }" /> diff --git a/frontend/src/components/project/badge/ProjectBadge.vue b/frontend/src/components/project/badge/ProjectBadge.vue index bd15b5aa..ffe37c0d 100644 --- a/frontend/src/components/project/badge/ProjectBadge.vue +++ b/frontend/src/components/project/badge/ProjectBadge.vue @@ -12,13 +12,12 @@ class="object-none my-5" :src=" url + - '/badge/' + + '/badge/repositories/' + project.storage + '/' + project.repository + '/' + - projectPath + - '/badge' + project.project " />
@@ -47,17 +46,14 @@ export default defineComponent({ }, setup(props) { const url = apiURL; - const projectPath = props.project.version - .replace(":", "/") - .replace(".", "/"); const snippets = createProjectSnippet( props.project.storage, props.project.repository, - projectPath, + props.project.project, props.project.version ); const page = ref(snippets[0].name); - return { url, page, snippets, projectPath }; + return { url, page, snippets }; }, methods: { diff --git a/frontend/src/components/repo/badge/RepositoryBadge.vue b/frontend/src/components/repo/badge/RepositoryBadge.vue index 105f2539..a42db337 100644 --- a/frontend/src/components/repo/badge/RepositoryBadge.vue +++ b/frontend/src/components/repo/badge/RepositoryBadge.vue @@ -12,11 +12,11 @@ class="object-none my-5" :src=" url + - 'badge/' + + '/badge/repositories/' + repository.storage + '/' + repository.name + - '/nitro_repo_info/badge' + '/nitro_repo_badge' " :alt="repository.storage + '/' + repository.name" /> diff --git a/frontend/src/components/repo/types/maven/MavenRepoInfo.vue b/frontend/src/components/repo/types/maven/MavenRepoInfo.vue index c43f18d5..c7749d77 100644 --- a/frontend/src/components/repo/types/maven/MavenRepoInfo.vue +++ b/frontend/src/components/repo/types/maven/MavenRepoInfo.vue @@ -28,7 +28,7 @@ export default defineComponent({ const url = apiURL; const repoURL = url + - "storages/" + + "/repositories/" + props.repository.storage + "/" + props.repository.name;