Compare commits
84 Commits
feature/sc
...
main
Author | SHA1 | Date | |
---|---|---|---|
3db5a22d74 | |||
f1ff03045d | |||
f6d816f224 | |||
ed110d3b4a | |||
a034578c0f | |||
644c169d44 | |||
47a3f27f8a | |||
123b7daccc | |||
29b371f20e | |||
c3a0c5355d | |||
0d313f846b | |||
e996c59934 | |||
8cbcbaf373 | |||
3882dae5ec | |||
c2763c6429 | |||
334243f1e4 | |||
6ae00a1d3a | |||
a245b98e32 | |||
734b5fd91f | |||
7d0fc29984 | |||
00c486c40d | |||
7b102fc1a5 | |||
ff3260c08b | |||
4ac34bca6f | |||
51800eb11f | |||
9596d0859c | |||
03c79d5190 | |||
dc446ec217 | |||
e4b4293f2b | |||
74ea9ddf79 | |||
ec8d0b5ebc | |||
15dd5ce45e | |||
13321a44a2 | |||
24b9ab97b5 | |||
39416042ba | |||
5d7539b72d | |||
1953a5b467 | |||
22e8466e3b | |||
82eb9894d7 | |||
a843fbfa04 | |||
95007ee15b | |||
49ea2bb3a4 | |||
b20574bf6c | |||
650a3b05c2 | |||
15a72ace70 | |||
86dd72b71a | |||
bbb037ee71 | |||
1e824b0692 | |||
7e18f95026 | |||
989ca5df21 | |||
f571c724dc | |||
82e9bec7c9 | |||
aa992b7e3e | |||
3c77241c93 | |||
a7ca61a086 | |||
484d5b4119 | |||
9a15b512fc | |||
02dbc498ae | |||
1275ac07fd | |||
a1e9f31dc2 | |||
34e009e53c | |||
a3a10e7f35 | |||
8fca3e147f | |||
120a1ae223 | |||
cbaa6b9e8d | |||
502bb26b90 | |||
bf7675d20b | |||
edce6fa0ac | |||
2cf4169542 | |||
44b0f32a9b | |||
c18db07cba | |||
4df964f023 | |||
adab603511 | |||
b70cf5e25d | |||
11f02eba00 | |||
5f90d663cf | |||
ea61ba9ed7 | |||
86cc2ea889 | |||
5aecf1ef26 | |||
085fc3b179 | |||
66358bdd05 | |||
2608b10efa | |||
92ce57dc60 | |||
05745f51ad |
4
.dockerignore
Normal file
4
.dockerignore
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
target/
|
||||||
|
.git/
|
||||||
|
.env
|
||||||
|
data/
|
2
.drone.yml
Normal file
2
.drone.yml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
kind: template
|
||||||
|
load: cuddle-rust-service-plan.yaml
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
target/
|
target/
|
||||||
|
.env
|
||||||
|
1701
Cargo.lock
generated
1701
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,2 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
|
members = ["crates/*"]
|
||||||
members = ["src/cmd/scel", "src/lib/scel_core", "src/lib/scel_api"]
|
|
||||||
|
31
Dockerfile
Normal file
31
Dockerfile
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
FROM node:19-alpine as web_builder
|
||||||
|
|
||||||
|
WORKDIR /usr/src/scel/web
|
||||||
|
|
||||||
|
COPY src/web/ .
|
||||||
|
|
||||||
|
RUN --mount=type=cache,target=/usr/src/scel/web/dist yarn
|
||||||
|
RUN --mount=type=cache,target=/usr/src/scel/web/dist yarn build
|
||||||
|
|
||||||
|
FROM rust:1.65 as builder
|
||||||
|
|
||||||
|
WORKDIR /usr/src/scel
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN --mount=type=cache,target=/usr/src/scel/target cargo build --release
|
||||||
|
RUN --mount=type=cache,target=/usr/src/scel/target cargo install --path src/cmd/scel
|
||||||
|
|
||||||
|
FROM debian:bullseye-slim
|
||||||
|
|
||||||
|
# Install YTD
|
||||||
|
RUN rm -f /etc/apt/apt.conf.d/docker-clean; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
|
||||||
|
RUN --mount=type=cache,target=/var/cache/apt --mount=type=cache,target=/var/lib/apt \
|
||||||
|
apt-get update && apt-get install -y python3 python3-pip
|
||||||
|
RUN python3 -m pip install -U yt-dlp
|
||||||
|
|
||||||
|
# Copy binary
|
||||||
|
COPY --from=builder /usr/local/cargo/bin/scel /usr/local/bin/scel
|
||||||
|
COPY --from=web_builder /usr/src/scel/web/dist /src/web/dist
|
||||||
|
|
||||||
|
CMD ["scel"]
|
@ -6,10 +6,11 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tokio = { version = "1.0", features = ["full"] }
|
tokio = { version = "1.22", features = ["full"] }
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||||
anyhow = { version = "1.0.58" }
|
anyhow = { version = "1.0.66" }
|
||||||
|
dotenv = { version = "*" }
|
||||||
|
|
||||||
scel_api = { path = "../../lib/scel_api" }
|
scel_api = { path = "../scel_api" }
|
||||||
scel_core = { path = "../../lib/scel_core" }
|
scel_core = { path = "../scel_core" }
|
28
crates/scel/src/main.rs
Normal file
28
crates/scel/src/main.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use dotenv::dotenv;
|
||||||
|
use scel_core::App;
|
||||||
|
use tracing::info;
|
||||||
|
use tracing_subscriber::{EnvFilter, FmtSubscriber};
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> anyhow::Result<()> {
|
||||||
|
dotenv().ok();
|
||||||
|
|
||||||
|
let subscriber = FmtSubscriber::builder()
|
||||||
|
.with_env_filter(
|
||||||
|
EnvFilter::default()
|
||||||
|
.add_directive("tower_http=debug".parse().unwrap())
|
||||||
|
.add_directive("scel_api=info".parse().unwrap())
|
||||||
|
.add_directive("scel=info".parse().unwrap()),
|
||||||
|
)
|
||||||
|
.finish();
|
||||||
|
|
||||||
|
tracing::subscriber::set_global_default(subscriber)?;
|
||||||
|
|
||||||
|
info!("Starting scel");
|
||||||
|
|
||||||
|
let app = Arc::new(App::new());
|
||||||
|
|
||||||
|
scel_api::Server::new(app.clone()).start().await
|
||||||
|
}
|
33
crates/scel_api/Cargo.toml
Normal file
33
crates/scel_api/Cargo.toml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
[package]
|
||||||
|
name = "scel_api"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
axum = { version = "0.5.17" }
|
||||||
|
axum-extra = { version = "0.3.7", features = ["spa"] }
|
||||||
|
futures = "0.3.30"
|
||||||
|
tower-http = { version = "0.3.4", features = ["cors", "trace"] }
|
||||||
|
async-graphql = { version = "4.0.16", features = [
|
||||||
|
'tracing',
|
||||||
|
'opentelemetry',
|
||||||
|
"log",
|
||||||
|
] }
|
||||||
|
async-graphql-axum = { version = "4.0.16" }
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = "1.0.89"
|
||||||
|
tokio = { version = "1.22", features = ["full"] }
|
||||||
|
tracing = "0.1"
|
||||||
|
tracing-subscriber = { version = "0.3" }
|
||||||
|
anyhow = { version = "1.0.66" }
|
||||||
|
oauth2 = { version = "*" }
|
||||||
|
async-session = { version = "*" }
|
||||||
|
reqwest = { version = "*", default-features = false, features = [
|
||||||
|
"rustls-tls",
|
||||||
|
"json",
|
||||||
|
] }
|
||||||
|
hyper = { version = "*" }
|
||||||
|
|
||||||
|
scel_core = { path = "../scel_core" }
|
99
crates/scel_api/src/auth/mod.rs
Normal file
99
crates/scel_api/src/auth/mod.rs
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
use std::env;
|
||||||
|
|
||||||
|
use async_session::{MemoryStore, Session, SessionStore};
|
||||||
|
use axum::{
|
||||||
|
extract::Query,
|
||||||
|
http::HeaderMap,
|
||||||
|
response::{IntoResponse, Redirect},
|
||||||
|
Extension,
|
||||||
|
};
|
||||||
|
use oauth2::{
|
||||||
|
basic::BasicClient, reqwest::async_http_client, AuthUrl, AuthorizationCode, ClientId,
|
||||||
|
ClientSecret, CsrfToken, RedirectUrl, TokenResponse, TokenUrl,
|
||||||
|
};
|
||||||
|
use reqwest::header::SET_COOKIE;
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
use crate::{User, COOKIE_NAME};
|
||||||
|
|
||||||
|
pub fn oauth_client() -> BasicClient {
|
||||||
|
let client_id = env::var("GITEA_CLIENT_ID").expect("Missing GITEA_CLIENT_ID");
|
||||||
|
let client_secret = env::var("GITEA_CLIENT_SECRET").expect("Missing GITEA_CLIENT_SECRET");
|
||||||
|
let redirect_url = env::var("GITEA_REDIRECT_URL")
|
||||||
|
.unwrap_or_else(|_| "http://127.0.0.1:3000/auth/authorized".to_string());
|
||||||
|
|
||||||
|
let auth_url =
|
||||||
|
env::var("GITEA_AUTH_URL").unwrap_or_else(|_| "https://git.front.kjuulh.io".to_string());
|
||||||
|
|
||||||
|
let token_url =
|
||||||
|
env::var("GITEA_TOKEN_URL").unwrap_or_else(|_| "https://git.front.kjuulh.io".to_string());
|
||||||
|
|
||||||
|
BasicClient::new(
|
||||||
|
ClientId::new(client_id),
|
||||||
|
Some(ClientSecret::new(client_secret)),
|
||||||
|
AuthUrl::new(auth_url).expect("AuthUrl was invalid"),
|
||||||
|
Some(TokenUrl::new(token_url).expect("Token url was invalid")),
|
||||||
|
)
|
||||||
|
.set_redirect_uri(RedirectUrl::new(redirect_url).expect("RedirectUrl was invalid"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn gitea(Extension(client): Extension<BasicClient>) -> impl IntoResponse {
|
||||||
|
let (auth_url, _crsf_token) = client.authorize_url(CsrfToken::new_random).url();
|
||||||
|
|
||||||
|
Redirect::to(&auth_url.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct AuthRequest {
|
||||||
|
code: String,
|
||||||
|
state: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn authorized(
|
||||||
|
Query(query): Query<AuthRequest>,
|
||||||
|
Extension(store): Extension<MemoryStore>,
|
||||||
|
Extension(oauth_client): Extension<BasicClient>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
let token = oauth_client
|
||||||
|
.exchange_code(AuthorizationCode::new(query.code.clone()))
|
||||||
|
.request_async(async_http_client)
|
||||||
|
.await
|
||||||
|
.expect("failed to get http client");
|
||||||
|
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
let user_data_json = client
|
||||||
|
.get(get_gitea_user_data_url())
|
||||||
|
.bearer_auth(token.access_token().secret())
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.expect("Request did not succeed");
|
||||||
|
// .text()
|
||||||
|
// .await
|
||||||
|
// .unwrap();
|
||||||
|
|
||||||
|
let user_data: User = user_data_json
|
||||||
|
.json::<User>()
|
||||||
|
.await
|
||||||
|
.expect("could not parse user");
|
||||||
|
|
||||||
|
let mut session = Session::new();
|
||||||
|
session
|
||||||
|
.insert("user", &user_data)
|
||||||
|
.expect("could not insert user data");
|
||||||
|
|
||||||
|
let cookie = store
|
||||||
|
.store_session(session)
|
||||||
|
.await
|
||||||
|
.expect("could not insert session")
|
||||||
|
.expect("session was not valid");
|
||||||
|
|
||||||
|
let cookie = format!("{}={}; SameSite=Lax; Path=/", COOKIE_NAME, cookie);
|
||||||
|
|
||||||
|
let mut headers = HeaderMap::new();
|
||||||
|
headers.insert(SET_COOKIE, cookie.parse().expect("Cookie is not valid"));
|
||||||
|
(headers, Redirect::to("/"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_gitea_user_data_url() -> String {
|
||||||
|
env::var("GITEA_USER_INFO_URL").expect("Missing GITEA_USER_INFO_URL")
|
||||||
|
}
|
4
crates/scel_api/src/graphql/mod.rs
Normal file
4
crates/scel_api/src/graphql/mod.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
pub mod mutation;
|
||||||
|
pub mod query;
|
||||||
|
pub mod schema;
|
||||||
|
pub mod subscription;
|
38
crates/scel_api/src/graphql/mutation.rs
Normal file
38
crates/scel_api/src/graphql/mutation.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use async_graphql::{Context, Object, Result, SimpleObject, ID};
|
||||||
|
use scel_core::{services::Download, App};
|
||||||
|
|
||||||
|
pub struct MutationRoot;
|
||||||
|
|
||||||
|
#[derive(SimpleObject)]
|
||||||
|
struct RequestDownloadResponse {
|
||||||
|
id: ID,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Object]
|
||||||
|
impl MutationRoot {
|
||||||
|
async fn request_download(
|
||||||
|
&self,
|
||||||
|
ctx: &Context<'_>,
|
||||||
|
download_link: String,
|
||||||
|
) -> Result<RequestDownloadResponse> {
|
||||||
|
let app = ctx.data_unchecked::<Arc<App>>();
|
||||||
|
|
||||||
|
let download = app
|
||||||
|
.download_service
|
||||||
|
.clone()
|
||||||
|
.add_download(Download {
|
||||||
|
id: None,
|
||||||
|
link: download_link,
|
||||||
|
progress: None,
|
||||||
|
file_name: None,
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Ok(RequestDownloadResponse {
|
||||||
|
id: download.id.unwrap().into(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
32
crates/scel_api/src/graphql/query.rs
Normal file
32
crates/scel_api/src/graphql/query.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use async_graphql::{Context, Object, Result, SimpleObject, ID};
|
||||||
|
use scel_core::App;
|
||||||
|
|
||||||
|
#[derive(SimpleObject, Clone)]
|
||||||
|
pub struct Download {
|
||||||
|
pub id: ID,
|
||||||
|
pub link: String,
|
||||||
|
pub progress: Option<u32>,
|
||||||
|
pub file_name: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct QueryRoot;
|
||||||
|
|
||||||
|
#[Object]
|
||||||
|
impl QueryRoot {
|
||||||
|
async fn get_download(&self, ctx: &Context<'_>, id: ID) -> Result<Option<Download>> {
|
||||||
|
let app = ctx.data_unchecked::<Arc<App>>();
|
||||||
|
|
||||||
|
match app.download_service.get_download(id.to_string()).await {
|
||||||
|
Ok(Some(d)) => Ok(Some(Download {
|
||||||
|
id: ID::from(d.id.expect("ID could not be found")),
|
||||||
|
progress: None,
|
||||||
|
link: d.link,
|
||||||
|
file_name: None,
|
||||||
|
})),
|
||||||
|
Ok(None) => Ok(None),
|
||||||
|
Err(e) => Err(e.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
use async_graphql::Schema;
|
use async_graphql::Schema;
|
||||||
|
|
||||||
use crate::{mutation::MutationRoot, query::QueryRoot, subscription::SubscriptionRoot};
|
use super::{mutation::MutationRoot, query::QueryRoot, subscription::SubscriptionRoot};
|
||||||
|
|
||||||
pub type ScelSchema = Schema<QueryRoot, MutationRoot, SubscriptionRoot>;
|
pub type ScelSchema = Schema<QueryRoot, MutationRoot, SubscriptionRoot>;
|
49
crates/scel_api/src/graphql/subscription.rs
Normal file
49
crates/scel_api/src/graphql/subscription.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use async_graphql::{
|
||||||
|
async_stream::stream, futures_util::Stream, Context, Object, Subscription, ID,
|
||||||
|
};
|
||||||
|
use scel_core::App;
|
||||||
|
|
||||||
|
use super::query::Download;
|
||||||
|
|
||||||
|
pub struct SubscriptionRoot;
|
||||||
|
|
||||||
|
struct DownloadChanged {
|
||||||
|
download: Download,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Object]
|
||||||
|
impl DownloadChanged {
|
||||||
|
async fn download(&self) -> Download {
|
||||||
|
self.download.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Subscription]
|
||||||
|
impl SubscriptionRoot {
|
||||||
|
async fn get_download(&self, ctx: &Context<'_>, id: ID) -> impl Stream<Item = DownloadChanged> {
|
||||||
|
let app = ctx.data_unchecked::<Arc<App>>();
|
||||||
|
|
||||||
|
let mut stream = app
|
||||||
|
.download_service
|
||||||
|
.subscribe_download(id.to_string())
|
||||||
|
.await;
|
||||||
|
|
||||||
|
stream! {
|
||||||
|
while stream.changed().await.is_ok() {
|
||||||
|
let next_download = (*stream.borrow()).clone();
|
||||||
|
let id = ID::from(next_download.id.unwrap());
|
||||||
|
|
||||||
|
yield DownloadChanged {
|
||||||
|
download: Download {
|
||||||
|
id: id,
|
||||||
|
link: next_download.link,
|
||||||
|
file_name: next_download.file_name,
|
||||||
|
progress: next_download.progress,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
173
crates/scel_api/src/lib.rs
Normal file
173
crates/scel_api/src/lib.rs
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
mod auth;
|
||||||
|
mod graphql;
|
||||||
|
|
||||||
|
use std::{io, net::SocketAddr, sync::Arc};
|
||||||
|
|
||||||
|
use async_graphql::{
|
||||||
|
extensions::{Logger, Tracing},
|
||||||
|
http::{playground_source, GraphQLPlaygroundConfig},
|
||||||
|
Request, Response, Schema,
|
||||||
|
};
|
||||||
|
use async_graphql_axum::GraphQLSubscription;
|
||||||
|
use async_session::{async_trait, MemoryStore, SessionStore};
|
||||||
|
use auth::{authorized, gitea};
|
||||||
|
use axum::{
|
||||||
|
extract::{rejection::TypedHeaderRejectionReason, FromRequest, RequestParts},
|
||||||
|
headers,
|
||||||
|
http::{header, Method},
|
||||||
|
response::{Html, IntoResponse, Redirect},
|
||||||
|
routing::{self, get_service},
|
||||||
|
Extension, Json, Router, TypedHeader,
|
||||||
|
};
|
||||||
|
use graphql::{
|
||||||
|
mutation::MutationRoot, query::QueryRoot, schema::ScelSchema, subscription::SubscriptionRoot,
|
||||||
|
};
|
||||||
|
use reqwest::StatusCode;
|
||||||
|
use scel_core::App;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tower_http::{
|
||||||
|
cors::CorsLayer,
|
||||||
|
services::ServeDir,
|
||||||
|
trace::{DefaultMakeSpan, TraceLayer},
|
||||||
|
};
|
||||||
|
|
||||||
|
async fn graphql_playground() -> impl IntoResponse {
|
||||||
|
Html(playground_source(
|
||||||
|
GraphQLPlaygroundConfig::new("/graphql").subscription_endpoint("/ws"),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
async fn graphql_handler(
|
||||||
|
schema: Extension<ScelSchema>,
|
||||||
|
req: Json<Request>,
|
||||||
|
_: User,
|
||||||
|
) -> Json<Response> {
|
||||||
|
schema.execute(req.0).await.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Server {
|
||||||
|
app: Router,
|
||||||
|
addr: SocketAddr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Server {
|
||||||
|
pub fn new(app: Arc<App>) -> Server {
|
||||||
|
let schema = Schema::build(QueryRoot, MutationRoot, SubscriptionRoot)
|
||||||
|
.extension(Tracing)
|
||||||
|
.extension(Logger)
|
||||||
|
.data(app)
|
||||||
|
.finish();
|
||||||
|
|
||||||
|
let cors = vec![
|
||||||
|
"http://localhost:3000"
|
||||||
|
.parse()
|
||||||
|
.expect("Could not parse url"),
|
||||||
|
"https://scel.front.kjuulh.io"
|
||||||
|
.parse()
|
||||||
|
.expect("Could not parse url"),
|
||||||
|
];
|
||||||
|
|
||||||
|
let api_router = Router::new()
|
||||||
|
.route(
|
||||||
|
"/graphql",
|
||||||
|
routing::get(graphql_playground).post(graphql_handler),
|
||||||
|
)
|
||||||
|
.route("/ws", GraphQLSubscription::new(schema.clone()))
|
||||||
|
.route("/auth/gitea", routing::get(gitea))
|
||||||
|
.route("/auth/authorized", routing::get(authorized))
|
||||||
|
// .merge(axum_extra::routing::SpaRouter::new(
|
||||||
|
// "/assets",
|
||||||
|
// "src/web/dist/assets",
|
||||||
|
// ))
|
||||||
|
.fallback(get_service(ServeDir::new("./src/web/dist/")).handle_error(handle_error))
|
||||||
|
.layer(Extension(schema))
|
||||||
|
.layer(Extension(MemoryStore::new()))
|
||||||
|
.layer(Extension(auth::oauth_client()))
|
||||||
|
.layer(
|
||||||
|
CorsLayer::new()
|
||||||
|
.allow_origin(cors)
|
||||||
|
.allow_headers([axum::http::header::CONTENT_TYPE])
|
||||||
|
.allow_methods([Method::GET, Method::POST, Method::OPTIONS]),
|
||||||
|
)
|
||||||
|
.layer(TraceLayer::new_for_http().make_span_with(DefaultMakeSpan::default()));
|
||||||
|
|
||||||
|
let app = Router::new().nest("/api", api_router);
|
||||||
|
|
||||||
|
let addr = SocketAddr::from(([0, 0, 0, 0], 3000));
|
||||||
|
|
||||||
|
Server { app, addr }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn start(self) -> anyhow::Result<()> {
|
||||||
|
tracing::info!("listening on {}", self.addr);
|
||||||
|
|
||||||
|
match axum::Server::bind(&self.addr)
|
||||||
|
.serve(self.app.into_make_service())
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(e) => Err(e.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
struct User {
|
||||||
|
#[serde(alias = "sub")]
|
||||||
|
id: String,
|
||||||
|
#[serde(alias = "picture")]
|
||||||
|
avatar: Option<String>,
|
||||||
|
#[serde(alias = "email")]
|
||||||
|
email: String,
|
||||||
|
#[serde(alias = "preferred_username")]
|
||||||
|
username: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AuthRedirect;
|
||||||
|
|
||||||
|
impl IntoResponse for AuthRedirect {
|
||||||
|
fn into_response(self) -> axum::response::Response {
|
||||||
|
Redirect::temporary("/auth/gitea").into_response()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const COOKIE_NAME: &str = "auth";
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl<B> FromRequest<B> for User
|
||||||
|
where
|
||||||
|
B: Send,
|
||||||
|
{
|
||||||
|
type Rejection = AuthRedirect;
|
||||||
|
|
||||||
|
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
|
||||||
|
let Extension(store) = Extension::<MemoryStore>::from_request(req)
|
||||||
|
.await
|
||||||
|
.expect("MemoryStore extension is missing");
|
||||||
|
|
||||||
|
let cookies = TypedHeader::<headers::Cookie>::from_request(req)
|
||||||
|
.await
|
||||||
|
.map_err(|e| match *e.name() {
|
||||||
|
header::COOKIE => match e.reason() {
|
||||||
|
TypedHeaderRejectionReason::Missing => AuthRedirect,
|
||||||
|
_ => panic!("unexpected error getting Cookie header(s): {}", e),
|
||||||
|
},
|
||||||
|
_ => panic!("unexpected error getting cookies: {}", e),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let session_cookie = cookies.get(COOKIE_NAME).ok_or(AuthRedirect)?;
|
||||||
|
|
||||||
|
let session = store
|
||||||
|
.load_session(session_cookie.to_string())
|
||||||
|
.await
|
||||||
|
.expect("could not load session")
|
||||||
|
.ok_or(AuthRedirect)?;
|
||||||
|
|
||||||
|
let user = session.get::<User>("user").ok_or(AuthRedirect)?;
|
||||||
|
|
||||||
|
Ok(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_error(_err: io::Error) -> impl IntoResponse {
|
||||||
|
(StatusCode::INTERNAL_SERVER_ERROR, "Something went wrong...")
|
||||||
|
}
|
17
crates/scel_core/Cargo.toml
Normal file
17
crates/scel_core/Cargo.toml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
[package]
|
||||||
|
name = "scel_core"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tokio = { version = "1.22", features = ["full"] }
|
||||||
|
anyhow = { version = "*" }
|
||||||
|
async-trait = { version = "0.1.58" }
|
||||||
|
futures = "0.3.30"
|
||||||
|
tracing = "0.1"
|
||||||
|
lazy_static = "1.4.0"
|
||||||
|
regex = { version = "1.7.0" }
|
||||||
|
thiserror = "1.0.37"
|
||||||
|
uuid = {version = "1.2.2", features = ["v4", "fast-rng"]}
|
19
crates/scel_core/src/lib.rs
Normal file
19
crates/scel_core/src/lib.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use services::InMemoryDownloadService;
|
||||||
|
|
||||||
|
pub mod services;
|
||||||
|
mod youtube;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub struct App {
|
||||||
|
pub download_service: Arc<InMemoryDownloadService>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl App {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
download_service: Arc::new(InMemoryDownloadService::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3
crates/scel_core/src/repo/users_repo.rs
Normal file
3
crates/scel_core/src/repo/users_repo.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub trait UsersRepo {
|
||||||
|
// add code here
|
||||||
|
}
|
128
crates/scel_core/src/services/mod.rs
Normal file
128
crates/scel_core/src/services/mod.rs
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
use std::{collections::HashMap, path::PathBuf, sync::Arc};
|
||||||
|
use tokio::sync::{watch, Mutex};
|
||||||
|
use tracing::error;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::youtube::{Arg, YoutubeDL};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Download {
|
||||||
|
pub id: Option<String>,
|
||||||
|
pub link: String,
|
||||||
|
pub progress: Option<u32>,
|
||||||
|
pub file_name: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct InMemoryDownloadService {
|
||||||
|
downloads: Mutex<
|
||||||
|
HashMap<
|
||||||
|
String,
|
||||||
|
(
|
||||||
|
Arc<Mutex<Download>>,
|
||||||
|
Arc<Mutex<tokio::sync::watch::Sender<Download>>>,
|
||||||
|
tokio::sync::watch::Receiver<Download>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InMemoryDownloadService {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
downloads: Mutex::new(HashMap::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn add_download(self: Arc<Self>, download: Download) -> anyhow::Result<Download> {
|
||||||
|
let mut downloads = self.downloads.lock().await;
|
||||||
|
|
||||||
|
let (tx, rx) = watch::channel(download.clone());
|
||||||
|
let shared_tx = Arc::new(Mutex::new(tx));
|
||||||
|
|
||||||
|
let mut d = download.to_owned();
|
||||||
|
|
||||||
|
let id = Uuid::new_v4().to_string();
|
||||||
|
d.id = Some(id.clone());
|
||||||
|
|
||||||
|
downloads.insert(id.clone(), (Arc::new(Mutex::new(d.clone())), shared_tx, rx));
|
||||||
|
|
||||||
|
let args = vec![
|
||||||
|
Arg::new("--progress"),
|
||||||
|
Arg::new("--newline"),
|
||||||
|
Arg::new_with_args("--output", "%(title).90s.%(ext)s"),
|
||||||
|
];
|
||||||
|
let ytd = YoutubeDL::new(
|
||||||
|
&PathBuf::from("./data/downloads"),
|
||||||
|
args,
|
||||||
|
download.link.as_str(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
tokio::spawn({
|
||||||
|
let download_service = self.clone();
|
||||||
|
|
||||||
|
async move {
|
||||||
|
if let Err(e) = ytd
|
||||||
|
.download(
|
||||||
|
|percentage| {
|
||||||
|
let ds = download_service.clone();
|
||||||
|
let id = id.clone();
|
||||||
|
|
||||||
|
async move {
|
||||||
|
let mut download = ds.get_download(id).await.unwrap().unwrap();
|
||||||
|
download.progress = Some(percentage);
|
||||||
|
let _ = ds.update_download(download).await;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|file_name| {
|
||||||
|
let ds = download_service.clone();
|
||||||
|
let id = id.clone();
|
||||||
|
|
||||||
|
async move {
|
||||||
|
let mut download = ds.get_download(id).await.unwrap().unwrap();
|
||||||
|
download.file_name = Some(file_name);
|
||||||
|
let _ = ds.update_download(download).await;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
error!("Download failed: {}", e);
|
||||||
|
} else {
|
||||||
|
let download = download_service.get_download(id).await.unwrap().unwrap();
|
||||||
|
let _ = download_service.update_download(download).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn update_download(self: Arc<Self>, download: Download) -> anyhow::Result<()> {
|
||||||
|
let mut downloads = self.downloads.lock().await;
|
||||||
|
if let Some(d) = downloads.get_mut(&download.clone().id.unwrap()) {
|
||||||
|
let mut d_mut = d.0.lock().await;
|
||||||
|
*d_mut = download.clone();
|
||||||
|
let _ = d.1.lock().await.send(download);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_download(&self, id: String) -> anyhow::Result<Option<Download>> {
|
||||||
|
let downloads = self.downloads.lock().await;
|
||||||
|
|
||||||
|
if let Some(d) = downloads.get(&id) {
|
||||||
|
let download = d.0.lock().await;
|
||||||
|
|
||||||
|
Ok(Some(download.clone()))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn subscribe_download(&self, id: String) -> tokio::sync::watch::Receiver<Download> {
|
||||||
|
let downloads = self.downloads.lock().await;
|
||||||
|
let download = downloads.get(&id).unwrap();
|
||||||
|
download.2.clone()
|
||||||
|
}
|
||||||
|
}
|
256
crates/scel_core/src/youtube/mod.rs
Normal file
256
crates/scel_core/src/youtube/mod.rs
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
use std::fs::{canonicalize, create_dir_all};
|
||||||
|
use std::future::Future;
|
||||||
|
use std::num::ParseIntError;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::process::{Output, Stdio};
|
||||||
|
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use regex::Regex;
|
||||||
|
use thiserror::Error;
|
||||||
|
use tokio::io::{AsyncBufReadExt, BufReader};
|
||||||
|
use tokio::process::Command;
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum YoutubeDLError {
|
||||||
|
#[error("failed to execute youtube-dl")]
|
||||||
|
IOError(#[from] std::io::Error),
|
||||||
|
#[error("failed to convert path")]
|
||||||
|
UTF8Error(#[from] std::string::FromUtf8Error),
|
||||||
|
#[error("youtube-dl exited with: {0}")]
|
||||||
|
Failure(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
type Result<T> = std::result::Result<T, YoutubeDLError>;
|
||||||
|
|
||||||
|
const YOUTUBE_DL_COMMAND: &str = "yt-dlp";
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Arg {
|
||||||
|
arg: String,
|
||||||
|
input: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Arg {
|
||||||
|
pub fn new(argument: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
arg: argument.to_string(),
|
||||||
|
input: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_with_args(argument: &str, input: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
arg: argument.to_string(),
|
||||||
|
input: Option::from(input.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Arg {
|
||||||
|
fn fmt(&self, fmt: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match &self.input {
|
||||||
|
Some(input) => write!(fmt, "{} {}", self.arg, input),
|
||||||
|
None => write!(fmt, "{}", self.arg),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct YoutubeDL {
|
||||||
|
path: PathBuf,
|
||||||
|
links: Vec<String>,
|
||||||
|
args: Vec<Arg>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct YoutubeDLResult {
|
||||||
|
path: PathBuf,
|
||||||
|
output: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl YoutubeDLResult {
|
||||||
|
fn new(path: &PathBuf) -> Self {
|
||||||
|
Self {
|
||||||
|
path: path.clone(),
|
||||||
|
output: String::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn output_dir(&self) -> &PathBuf {
|
||||||
|
&self.path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl YoutubeDL {
|
||||||
|
pub fn new_multiple_links(
|
||||||
|
dl_path: &PathBuf,
|
||||||
|
args: Vec<Arg>,
|
||||||
|
links: Vec<String>,
|
||||||
|
) -> Result<YoutubeDL> {
|
||||||
|
let path = Path::new(dl_path);
|
||||||
|
|
||||||
|
if !path.exists() {
|
||||||
|
create_dir_all(&path)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !path.is_dir() {
|
||||||
|
return Err(YoutubeDLError::IOError(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::Other,
|
||||||
|
"path is not a directory",
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let path = canonicalize(dl_path)?;
|
||||||
|
Ok(YoutubeDL { path, links, args })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(dl_path: &PathBuf, args: Vec<Arg>, link: &str) -> Result<YoutubeDL> {
|
||||||
|
YoutubeDL::new_multiple_links(dl_path, args, vec![link.to_string()])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn download<F, FutAvailable, FAvailable, Fut>(
|
||||||
|
&self,
|
||||||
|
progress_update_fn: F,
|
||||||
|
file_name_available: FAvailable,
|
||||||
|
) -> Result<YoutubeDLResult>
|
||||||
|
where
|
||||||
|
F: Fn(u32) -> Fut,
|
||||||
|
FAvailable: Fn(String) -> FutAvailable,
|
||||||
|
Fut: Future<Output = ()>,
|
||||||
|
FutAvailable: Future<Output = ()>,
|
||||||
|
{
|
||||||
|
let output = self
|
||||||
|
.spawn_youtube_dl(progress_update_fn, file_name_available)
|
||||||
|
.await?;
|
||||||
|
let mut result = YoutubeDLResult::new(&self.path);
|
||||||
|
|
||||||
|
if !output.status.success() {
|
||||||
|
return Err(YoutubeDLError::Failure(String::from_utf8(output.stderr)?));
|
||||||
|
}
|
||||||
|
result.output = String::from_utf8(output.stdout)?;
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn spawn_youtube_dl<F, FutAvailable, FAvailable, Fut>(
|
||||||
|
&self,
|
||||||
|
progress_update_fn: F,
|
||||||
|
file_name_available: FAvailable,
|
||||||
|
) -> Result<Output>
|
||||||
|
where
|
||||||
|
F: Fn(u32) -> Fut,
|
||||||
|
FAvailable: Fn(String) -> FutAvailable,
|
||||||
|
Fut: Future<Output = ()>,
|
||||||
|
FutAvailable: Future<Output = ()>,
|
||||||
|
{
|
||||||
|
let mut cmd = Command::new(YOUTUBE_DL_COMMAND);
|
||||||
|
cmd.current_dir(&self.path)
|
||||||
|
.env("LC_ALL", "en_US.UTF-8")
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.stderr(Stdio::piped());
|
||||||
|
|
||||||
|
for arg in self.args.iter() {
|
||||||
|
match &arg.input {
|
||||||
|
Some(input) => cmd.arg(&arg.arg).arg(input),
|
||||||
|
None => cmd.arg(&arg.arg),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
for link in self.links.iter() {
|
||||||
|
cmd.arg(&link);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut pr = cmd.spawn()?;
|
||||||
|
|
||||||
|
{
|
||||||
|
let stdout = pr.stdout.as_mut().unwrap();
|
||||||
|
let stdout_reader = BufReader::new(stdout);
|
||||||
|
let mut stdout_lines = stdout_reader.lines();
|
||||||
|
|
||||||
|
let mut have_gotten_file_name = false;
|
||||||
|
while let Ok(Some(line)) = stdout_lines.next_line().await {
|
||||||
|
println!("{}", line.clone());
|
||||||
|
|
||||||
|
if !have_gotten_file_name {
|
||||||
|
if let Some(file_name) = parse_file_name(line.clone()) {
|
||||||
|
file_name_available(file_name).await;
|
||||||
|
have_gotten_file_name = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(Ok(percentage)) = parse_line(line) {
|
||||||
|
progress_update_fn(percentage).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(pr.wait_with_output().await?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_line(line: String) -> Option<core::result::Result<u32, ParseIntError>> {
|
||||||
|
lazy_static! {
|
||||||
|
static ref RE: Regex = Regex::new(r"\[download\]\s+(\d+)").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let capture: regex::Captures = RE.captures(line.as_str())?;
|
||||||
|
if capture.len() != 2 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let str = &capture[1];
|
||||||
|
Some(str.to_string().parse::<u32>())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_file_name(line: String) -> Option<String> {
|
||||||
|
lazy_static! {
|
||||||
|
static ref RE: Regex = Regex::new(r"^\[download\] Destination: (.+)$").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let capture: regex::Captures = RE.captures(line.as_str())?;
|
||||||
|
if capture.len() != 2 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let str = &capture[1];
|
||||||
|
Some(str.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::youtube::{parse_file_name, parse_line};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_line() {
|
||||||
|
let percentage = parse_line(
|
||||||
|
"[download] 95.4% of ~215.85MiB at 9.61MiB/s ETA 00:01 (frag 144/151)".into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(percentage, Some(Ok(95)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_line_get_nothing() {
|
||||||
|
let nothing = parse_line("[download] Got server HTTP error: The read operation timed out. Retrying (attempt 1 of 10) ...".into());
|
||||||
|
|
||||||
|
assert_eq!(nothing, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_file_name() {
|
||||||
|
let file_name = parse_file_name(
|
||||||
|
"[download] Destination: 10 Design Patterns Explained in 10 Minutes.mp4".into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
file_name,
|
||||||
|
Some("10 Design Patterns Explained in 10 Minutes.mp4".into())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_file_name_get_nothing() {
|
||||||
|
let nothing = parse_file_name("[download] No fit: something".into());
|
||||||
|
|
||||||
|
assert_eq!(nothing, None)
|
||||||
|
}
|
||||||
|
}
|
21
cuddle.yaml
Normal file
21
cuddle.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# yaml-language-server: $schema=https://git.front.kjuulh.io/kjuulh/cuddle/raw/branch/main/schemas/base.json
|
||||||
|
|
||||||
|
base: "git@git.front.kjuulh.io:kjuulh/cuddle-rust-service-plan.git"
|
||||||
|
|
||||||
|
vars:
|
||||||
|
service: "scel"
|
||||||
|
registry: kasperhermansen
|
||||||
|
|
||||||
|
clusters:
|
||||||
|
clank-prod:
|
||||||
|
replicas: "3"
|
||||||
|
namespace: prod
|
||||||
|
|
||||||
|
|
||||||
|
deployment:
|
||||||
|
registry: git@git.front.kjuulh.io:kjuulh/clank-clusters
|
||||||
|
env:
|
||||||
|
prod:
|
||||||
|
clusters:
|
||||||
|
- clank-prod
|
||||||
|
|
BIN
data/downloads/The Blimp Extinction.mp4.part
Normal file
BIN
data/downloads/The Blimp Extinction.mp4.part
Normal file
Binary file not shown.
3
renovate.json
Normal file
3
renovate.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json"
|
||||||
|
}
|
@ -1,15 +0,0 @@
|
|||||||
use tracing::{info, Level};
|
|
||||||
use tracing_subscriber::FmtSubscriber;
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
async fn main() -> anyhow::Result<()> {
|
|
||||||
let subscriber = FmtSubscriber::builder()
|
|
||||||
.with_max_level(Level::INFO)
|
|
||||||
.finish();
|
|
||||||
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
|
|
||||||
info!("Starting scel");
|
|
||||||
|
|
||||||
scel_api::Server::new().start().await
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "scel_api"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
axum = { version = "0.5.6" }
|
|
||||||
futures = "0.3.21"
|
|
||||||
tower-http = {version = "0.3.3", features = ["cors"]}
|
|
||||||
async-graphql = { version = "4.0.0" }
|
|
||||||
async-graphql-axum = { version = "4.0.0" }
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
|
||||||
serde_json = "1.0.68"
|
|
||||||
tokio = { version = "1.0", features = ["full"] }
|
|
||||||
tracing = "0.1"
|
|
||||||
tracing-subscriber = { version = "0.3" }
|
|
||||||
anyhow = { version = "1.0.58" }
|
|
@ -1,72 +0,0 @@
|
|||||||
mod mutation;
|
|
||||||
mod query;
|
|
||||||
mod schema;
|
|
||||||
mod subscription;
|
|
||||||
|
|
||||||
use std::net::SocketAddr;
|
|
||||||
|
|
||||||
use async_graphql::{
|
|
||||||
http::{playground_source, GraphQLPlaygroundConfig},
|
|
||||||
Request, Response, Schema,
|
|
||||||
};
|
|
||||||
use async_graphql_axum::GraphQLSubscription;
|
|
||||||
use axum::{
|
|
||||||
http::Method,
|
|
||||||
response::{Html, IntoResponse},
|
|
||||||
routing, Extension, Json, Router,
|
|
||||||
};
|
|
||||||
use mutation::MutationRoot;
|
|
||||||
use query::QueryRoot;
|
|
||||||
use schema::ScelSchema;
|
|
||||||
use subscription::SubscriptionRoot;
|
|
||||||
use tower_http::cors::CorsLayer;
|
|
||||||
|
|
||||||
async fn graphql_playground() -> impl IntoResponse {
|
|
||||||
Html(playground_source(
|
|
||||||
GraphQLPlaygroundConfig::new("/").subscription_endpoint("/ws"),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
async fn graphql_handler(schema: Extension<ScelSchema>, req: Json<Request>) -> Json<Response> {
|
|
||||||
schema.execute(req.0).await.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Server {
|
|
||||||
app: Router,
|
|
||||||
addr: SocketAddr,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Server {
|
|
||||||
pub fn new() -> Server {
|
|
||||||
let schema = Schema::build(QueryRoot, MutationRoot, SubscriptionRoot).finish();
|
|
||||||
|
|
||||||
let cors = vec!["http://localhost:3000"
|
|
||||||
.parse()
|
|
||||||
.expect("Could not parse url")];
|
|
||||||
|
|
||||||
let app = Router::new()
|
|
||||||
.route("/", routing::get(graphql_playground).post(graphql_handler))
|
|
||||||
.route("/ws", GraphQLSubscription::new(schema.clone()))
|
|
||||||
.layer(Extension(schema))
|
|
||||||
.layer(
|
|
||||||
CorsLayer::new()
|
|
||||||
.allow_origin(cors)
|
|
||||||
.allow_headers([axum::http::header::CONTENT_TYPE])
|
|
||||||
.allow_methods([Method::GET, Method::POST, Method::OPTIONS]),
|
|
||||||
);
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
|
||||||
|
|
||||||
return Server { app, addr };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn start(self) -> anyhow::Result<()> {
|
|
||||||
tracing::info!("listening on {}", self.addr);
|
|
||||||
|
|
||||||
match axum::Server::bind(&self.addr)
|
|
||||||
.serve(self.app.into_make_service())
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(e) => Err(e.into()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
use async_graphql::{Context, Object, Result, SimpleObject, ID};
|
|
||||||
|
|
||||||
pub struct MutationRoot;
|
|
||||||
|
|
||||||
#[derive(SimpleObject)]
|
|
||||||
struct RequestDownloadResponse {
|
|
||||||
id: ID,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[Object]
|
|
||||||
impl MutationRoot {
|
|
||||||
async fn request_download(&self, ctx: &Context<'_>) -> Result<RequestDownloadResponse> {
|
|
||||||
Err("not implemented 123".into())
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
use async_graphql::Object;
|
|
||||||
|
|
||||||
pub struct QueryRoot;
|
|
||||||
|
|
||||||
#[Object]
|
|
||||||
impl QueryRoot {
|
|
||||||
async fn hello_world(&self) -> &str {
|
|
||||||
"Hello, world!"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
use async_graphql::{
|
|
||||||
async_stream::stream, futures_util::Stream, Context, Object, Subscription, ID,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct SubscriptionRoot;
|
|
||||||
|
|
||||||
struct DownloadChanged {
|
|
||||||
id: ID,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[Object]
|
|
||||||
impl DownloadChanged {
|
|
||||||
async fn id(&self) -> &ID {
|
|
||||||
&self.id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[Subscription]
|
|
||||||
impl SubscriptionRoot {
|
|
||||||
async fn get_download(&self, ctx: &Context<'_>) -> impl Stream<Item = DownloadChanged> {
|
|
||||||
stream! {
|
|
||||||
yield DownloadChanged {id: "Some-id".into()}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "scel_core"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
@ -1,12 +0,0 @@
|
|||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
#[test]
|
|
||||||
fn it_works() {
|
|
||||||
let result = 2 + 2;
|
|
||||||
assert_eq!(result, 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn something() -> String {
|
|
||||||
"".into()
|
|
||||||
}
|
|
1
web/.dockerignore
Normal file
1
web/.dockerignore
Normal file
@ -0,0 +1 @@
|
|||||||
|
node_modules/
|
24
web/.gitignore
vendored
Normal file
24
web/.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
13
web/index.html
Normal file
13
web/index.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Vite + React + TS</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
22
web/package.json
Normal file
22
web/package.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "web",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "tsc && vite build",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"react": "18.3.1",
|
||||||
|
"react-dom": "18.3.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/react": "18.3.12",
|
||||||
|
"@types/react-dom": "18.3.1",
|
||||||
|
"@vitejs/plugin-react": "2.2.0",
|
||||||
|
"typescript": "4.9.3",
|
||||||
|
"vite": "3.2.4"
|
||||||
|
}
|
||||||
|
}
|
1
web/public/vite.svg
Normal file
1
web/public/vite.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
12
web/src/App.tsx
Normal file
12
web/src/App.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import Body from "./components/body/Body"
|
||||||
|
import Navbar from "./components/navbar/Navbar"
|
||||||
|
import RequestDownload from "./components/request-download/RequestDownload"
|
||||||
|
|
||||||
|
const App = () => <div>
|
||||||
|
<Navbar />
|
||||||
|
<Body>
|
||||||
|
<RequestDownload />
|
||||||
|
</Body>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
export default App
|
1
web/src/assets/react.svg
Normal file
1
web/src/assets/react.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
|
After Width: | Height: | Size: 4.0 KiB |
8
web/src/components/body/Body.tsx
Normal file
8
web/src/components/body/Body.tsx
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { FC, ReactNode } from "react"
|
||||||
|
|
||||||
|
interface BodyProps {
|
||||||
|
children?: ReactNode
|
||||||
|
}
|
||||||
|
const Body: FC<BodyProps> = ({ children }) => <div>{children}</div>
|
||||||
|
|
||||||
|
export default Body
|
10
web/src/components/navbar/Navbar.tsx
Normal file
10
web/src/components/navbar/Navbar.tsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { getServerUrl } from "../../lib/env"
|
||||||
|
|
||||||
|
const Navbar = () => {
|
||||||
|
return <nav>
|
||||||
|
<div>Scel</div>
|
||||||
|
<a href={`${getServerUrl()}/auth/gitea`}>Login</a>
|
||||||
|
</nav>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Navbar
|
7
web/src/components/request-download/RequestDownload.tsx
Normal file
7
web/src/components/request-download/RequestDownload.tsx
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
const RequestDownload = () => {
|
||||||
|
return <div>
|
||||||
|
<input type="text" placeholder="Request download"></input>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RequestDownload
|
3
web/src/lib/env.ts
Normal file
3
web/src/lib/env.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export const getServerUrl = (): string => {
|
||||||
|
return import.meta.env.VITE_SERVER_BASE_URL
|
||||||
|
}
|
9
web/src/main.tsx
Normal file
9
web/src/main.tsx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import ReactDOM from 'react-dom/client'
|
||||||
|
import App from './App'
|
||||||
|
|
||||||
|
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<App />
|
||||||
|
</React.StrictMode>
|
||||||
|
)
|
1
web/src/vite-env.d.ts
vendored
Normal file
1
web/src/vite-env.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/// <reference types="vite/client" />
|
21
web/tsconfig.json
Normal file
21
web/tsconfig.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||||
|
"allowJs": false,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"esModuleInterop": false,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"strict": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "react-jsx"
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"references": [{ "path": "./tsconfig.node.json" }]
|
||||||
|
}
|
9
web/tsconfig.node.json
Normal file
9
web/tsconfig.node.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"allowSyntheticDefaultImports": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
7
web/vite.config.ts
Normal file
7
web/vite.config.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import react from '@vitejs/plugin-react'
|
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react()]
|
||||||
|
})
|
779
web/yarn.lock
Normal file
779
web/yarn.lock
Normal file
@ -0,0 +1,779 @@
|
|||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
"@ampproject/remapping@^2.1.0":
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d"
|
||||||
|
integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/gen-mapping" "^0.1.0"
|
||||||
|
"@jridgewell/trace-mapping" "^0.3.9"
|
||||||
|
|
||||||
|
"@babel/code-frame@^7.18.6":
|
||||||
|
version "7.18.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a"
|
||||||
|
integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==
|
||||||
|
dependencies:
|
||||||
|
"@babel/highlight" "^7.18.6"
|
||||||
|
|
||||||
|
"@babel/compat-data@^7.20.0":
|
||||||
|
version "7.20.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.0.tgz#9b61938c5f688212c7b9ae363a819df7d29d4093"
|
||||||
|
integrity sha512-Gt9jszFJYq7qzXVK4slhc6NzJXnOVmRECWcVjF/T23rNXD9NtWQ0W3qxdg+p9wWIB+VQw3GYV/U2Ha9bRTfs4w==
|
||||||
|
|
||||||
|
"@babel/core@^7.19.6":
|
||||||
|
version "7.19.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.6.tgz#7122ae4f5c5a37c0946c066149abd8e75f81540f"
|
||||||
|
integrity sha512-D2Ue4KHpc6Ys2+AxpIx1BZ8+UegLLLE2p3KJEuJRKmokHOtl49jQ5ny1773KsGLZs8MQvBidAF6yWUJxRqtKtg==
|
||||||
|
dependencies:
|
||||||
|
"@ampproject/remapping" "^2.1.0"
|
||||||
|
"@babel/code-frame" "^7.18.6"
|
||||||
|
"@babel/generator" "^7.19.6"
|
||||||
|
"@babel/helper-compilation-targets" "^7.19.3"
|
||||||
|
"@babel/helper-module-transforms" "^7.19.6"
|
||||||
|
"@babel/helpers" "^7.19.4"
|
||||||
|
"@babel/parser" "^7.19.6"
|
||||||
|
"@babel/template" "^7.18.10"
|
||||||
|
"@babel/traverse" "^7.19.6"
|
||||||
|
"@babel/types" "^7.19.4"
|
||||||
|
convert-source-map "^1.7.0"
|
||||||
|
debug "^4.1.0"
|
||||||
|
gensync "^1.0.0-beta.2"
|
||||||
|
json5 "^2.2.1"
|
||||||
|
semver "^6.3.0"
|
||||||
|
|
||||||
|
"@babel/generator@^7.19.6", "@babel/generator@^7.20.0":
|
||||||
|
version "7.20.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.0.tgz#0bfc5379e0efb05ca6092091261fcdf7ec36249d"
|
||||||
|
integrity sha512-GUPcXxWibClgmYJuIwC2Bc2Lg+8b9VjaJ+HlNdACEVt+Wlr1eoU1OPZjZRm7Hzl0gaTsUZNQfeihvZJhG7oc3w==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.20.0"
|
||||||
|
"@jridgewell/gen-mapping" "^0.3.2"
|
||||||
|
jsesc "^2.5.1"
|
||||||
|
|
||||||
|
"@babel/helper-annotate-as-pure@^7.18.6":
|
||||||
|
version "7.18.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb"
|
||||||
|
integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.18.6"
|
||||||
|
|
||||||
|
"@babel/helper-compilation-targets@^7.19.3":
|
||||||
|
version "7.20.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz#6bf5374d424e1b3922822f1d9bdaa43b1a139d0a"
|
||||||
|
integrity sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/compat-data" "^7.20.0"
|
||||||
|
"@babel/helper-validator-option" "^7.18.6"
|
||||||
|
browserslist "^4.21.3"
|
||||||
|
semver "^6.3.0"
|
||||||
|
|
||||||
|
"@babel/helper-environment-visitor@^7.18.9":
|
||||||
|
version "7.18.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be"
|
||||||
|
integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==
|
||||||
|
|
||||||
|
"@babel/helper-function-name@^7.19.0":
|
||||||
|
version "7.19.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c"
|
||||||
|
integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==
|
||||||
|
dependencies:
|
||||||
|
"@babel/template" "^7.18.10"
|
||||||
|
"@babel/types" "^7.19.0"
|
||||||
|
|
||||||
|
"@babel/helper-hoist-variables@^7.18.6":
|
||||||
|
version "7.18.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678"
|
||||||
|
integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.18.6"
|
||||||
|
|
||||||
|
"@babel/helper-module-imports@^7.18.6":
|
||||||
|
version "7.18.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e"
|
||||||
|
integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.18.6"
|
||||||
|
|
||||||
|
"@babel/helper-module-transforms@^7.19.6":
|
||||||
|
version "7.19.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.19.6.tgz#6c52cc3ac63b70952d33ee987cbee1c9368b533f"
|
||||||
|
integrity sha512-fCmcfQo/KYr/VXXDIyd3CBGZ6AFhPFy1TfSEJ+PilGVlQT6jcbqtHAM4C1EciRqMza7/TpOUZliuSH+U6HAhJw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-environment-visitor" "^7.18.9"
|
||||||
|
"@babel/helper-module-imports" "^7.18.6"
|
||||||
|
"@babel/helper-simple-access" "^7.19.4"
|
||||||
|
"@babel/helper-split-export-declaration" "^7.18.6"
|
||||||
|
"@babel/helper-validator-identifier" "^7.19.1"
|
||||||
|
"@babel/template" "^7.18.10"
|
||||||
|
"@babel/traverse" "^7.19.6"
|
||||||
|
"@babel/types" "^7.19.4"
|
||||||
|
|
||||||
|
"@babel/helper-plugin-utils@^7.18.6":
|
||||||
|
version "7.18.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz#4b8aea3b069d8cb8a72cdfe28ddf5ceca695ef2f"
|
||||||
|
integrity sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==
|
||||||
|
|
||||||
|
"@babel/helper-plugin-utils@^7.19.0":
|
||||||
|
version "7.19.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz#4796bb14961521f0f8715990bee2fb6e51ce21bf"
|
||||||
|
integrity sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==
|
||||||
|
|
||||||
|
"@babel/helper-simple-access@^7.19.4":
|
||||||
|
version "7.19.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.19.4.tgz#be553f4951ac6352df2567f7daa19a0ee15668e7"
|
||||||
|
integrity sha512-f9Xq6WqBFqaDfbCzn2w85hwklswz5qsKlh7f08w4Y9yhJHpnNC0QemtSkK5YyOY8kPGvyiwdzZksGUhnGdaUIg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.19.4"
|
||||||
|
|
||||||
|
"@babel/helper-split-export-declaration@^7.18.6":
|
||||||
|
version "7.18.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075"
|
||||||
|
integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.18.6"
|
||||||
|
|
||||||
|
"@babel/helper-string-parser@^7.19.4":
|
||||||
|
version "7.19.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63"
|
||||||
|
integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==
|
||||||
|
|
||||||
|
"@babel/helper-validator-identifier@^7.18.6":
|
||||||
|
version "7.18.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076"
|
||||||
|
integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==
|
||||||
|
|
||||||
|
"@babel/helper-validator-identifier@^7.19.1":
|
||||||
|
version "7.19.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2"
|
||||||
|
integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==
|
||||||
|
|
||||||
|
"@babel/helper-validator-option@^7.18.6":
|
||||||
|
version "7.18.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8"
|
||||||
|
integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==
|
||||||
|
|
||||||
|
"@babel/helpers@^7.19.4":
|
||||||
|
version "7.20.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.0.tgz#27c8ffa8cc32a2ed3762fba48886e7654dbcf77f"
|
||||||
|
integrity sha512-aGMjYraN0zosCEthoGLdqot1oRsmxVTQRHadsUPz5QM44Zej2PYRz7XiDE7GqnkZnNtLbOuxqoZw42vkU7+XEQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/template" "^7.18.10"
|
||||||
|
"@babel/traverse" "^7.20.0"
|
||||||
|
"@babel/types" "^7.20.0"
|
||||||
|
|
||||||
|
"@babel/highlight@^7.18.6":
|
||||||
|
version "7.18.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf"
|
||||||
|
integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-validator-identifier" "^7.18.6"
|
||||||
|
chalk "^2.0.0"
|
||||||
|
js-tokens "^4.0.0"
|
||||||
|
|
||||||
|
"@babel/parser@^7.18.10", "@babel/parser@^7.19.6", "@babel/parser@^7.20.0":
|
||||||
|
version "7.20.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.0.tgz#b26133c888da4d79b0d3edcf42677bcadc783046"
|
||||||
|
integrity sha512-G9VgAhEaICnz8iiJeGJQyVl6J2nTjbW0xeisva0PK6XcKsga7BIaqm4ZF8Rg1Wbaqmy6znspNqhPaPkyukujzg==
|
||||||
|
|
||||||
|
"@babel/plugin-syntax-jsx@^7.18.6":
|
||||||
|
version "7.18.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0"
|
||||||
|
integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-plugin-utils" "^7.18.6"
|
||||||
|
|
||||||
|
"@babel/plugin-transform-react-jsx-development@^7.18.6":
|
||||||
|
version "7.18.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz#dbe5c972811e49c7405b630e4d0d2e1380c0ddc5"
|
||||||
|
integrity sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/plugin-transform-react-jsx" "^7.18.6"
|
||||||
|
|
||||||
|
"@babel/plugin-transform-react-jsx-self@^7.18.6":
|
||||||
|
version "7.18.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.18.6.tgz#3849401bab7ae8ffa1e3e5687c94a753fc75bda7"
|
||||||
|
integrity sha512-A0LQGx4+4Jv7u/tWzoJF7alZwnBDQd6cGLh9P+Ttk4dpiL+J5p7NSNv/9tlEFFJDq3kjxOavWmbm6t0Gk+A3Ig==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-plugin-utils" "^7.18.6"
|
||||||
|
|
||||||
|
"@babel/plugin-transform-react-jsx-source@^7.19.6":
|
||||||
|
version "7.19.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.19.6.tgz#88578ae8331e5887e8ce28e4c9dc83fb29da0b86"
|
||||||
|
integrity sha512-RpAi004QyMNisst/pvSanoRdJ4q+jMCWyk9zdw/CyLB9j8RXEahodR6l2GyttDRyEVWZtbN+TpLiHJ3t34LbsQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-plugin-utils" "^7.19.0"
|
||||||
|
|
||||||
|
"@babel/plugin-transform-react-jsx@^7.18.6":
|
||||||
|
version "7.18.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.18.6.tgz#2721e96d31df96e3b7ad48ff446995d26bc028ff"
|
||||||
|
integrity sha512-Mz7xMPxoy9kPS/JScj6fJs03TZ/fZ1dJPlMjRAgTaxaS0fUBk8FV/A2rRgfPsVCZqALNwMexD+0Uaf5zlcKPpw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-annotate-as-pure" "^7.18.6"
|
||||||
|
"@babel/helper-module-imports" "^7.18.6"
|
||||||
|
"@babel/helper-plugin-utils" "^7.18.6"
|
||||||
|
"@babel/plugin-syntax-jsx" "^7.18.6"
|
||||||
|
"@babel/types" "^7.18.6"
|
||||||
|
|
||||||
|
"@babel/plugin-transform-react-jsx@^7.19.0":
|
||||||
|
version "7.19.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.19.0.tgz#b3cbb7c3a00b92ec8ae1027910e331ba5c500eb9"
|
||||||
|
integrity sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-annotate-as-pure" "^7.18.6"
|
||||||
|
"@babel/helper-module-imports" "^7.18.6"
|
||||||
|
"@babel/helper-plugin-utils" "^7.19.0"
|
||||||
|
"@babel/plugin-syntax-jsx" "^7.18.6"
|
||||||
|
"@babel/types" "^7.19.0"
|
||||||
|
|
||||||
|
"@babel/template@^7.18.10":
|
||||||
|
version "7.18.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71"
|
||||||
|
integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/code-frame" "^7.18.6"
|
||||||
|
"@babel/parser" "^7.18.10"
|
||||||
|
"@babel/types" "^7.18.10"
|
||||||
|
|
||||||
|
"@babel/traverse@^7.19.6", "@babel/traverse@^7.20.0":
|
||||||
|
version "7.20.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.0.tgz#538c4c6ce6255f5666eba02252a7b59fc2d5ed98"
|
||||||
|
integrity sha512-5+cAXQNARgjRUK0JWu2UBwja4JLSO/rBMPJzpsKb+oBF5xlUuCfljQepS4XypBQoiigL0VQjTZy6WiONtUdScQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/code-frame" "^7.18.6"
|
||||||
|
"@babel/generator" "^7.20.0"
|
||||||
|
"@babel/helper-environment-visitor" "^7.18.9"
|
||||||
|
"@babel/helper-function-name" "^7.19.0"
|
||||||
|
"@babel/helper-hoist-variables" "^7.18.6"
|
||||||
|
"@babel/helper-split-export-declaration" "^7.18.6"
|
||||||
|
"@babel/parser" "^7.20.0"
|
||||||
|
"@babel/types" "^7.20.0"
|
||||||
|
debug "^4.1.0"
|
||||||
|
globals "^11.1.0"
|
||||||
|
|
||||||
|
"@babel/types@^7.18.10", "@babel/types@^7.19.0", "@babel/types@^7.19.4", "@babel/types@^7.20.0":
|
||||||
|
version "7.20.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.0.tgz#52c94cf8a7e24e89d2a194c25c35b17a64871479"
|
||||||
|
integrity sha512-Jlgt3H0TajCW164wkTOTzHkZb075tMQMULzrLUoUeKmO7eFL96GgDxf7/Axhc5CAuKE3KFyVW1p6ysKsi2oXAg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-string-parser" "^7.19.4"
|
||||||
|
"@babel/helper-validator-identifier" "^7.19.1"
|
||||||
|
to-fast-properties "^2.0.0"
|
||||||
|
|
||||||
|
"@babel/types@^7.18.6":
|
||||||
|
version "7.18.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.9.tgz#7148d64ba133d8d73a41b3172ac4b83a1452205f"
|
||||||
|
integrity sha512-WwMLAg2MvJmt/rKEVQBBhIVffMmnilX4oe0sRe7iPOHIGsqpruFHHdrfj4O1CMMtgMtCU4oPafZjDPCRgO57Wg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-validator-identifier" "^7.18.6"
|
||||||
|
to-fast-properties "^2.0.0"
|
||||||
|
|
||||||
|
"@esbuild/android-arm@0.15.12":
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.15.12.tgz#e548b10a5e55b9e10537a049ebf0bc72c453b769"
|
||||||
|
integrity sha512-IC7TqIqiyE0MmvAhWkl/8AEzpOtbhRNDo7aph47We1NbE5w2bt/Q+giAhe0YYeVpYnIhGMcuZY92qDK6dQauvA==
|
||||||
|
|
||||||
|
"@esbuild/linux-loong64@0.15.12":
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.15.12.tgz#475b33a2631a3d8ca8aa95ee127f9a61d95bf9c1"
|
||||||
|
integrity sha512-tZEowDjvU7O7I04GYvWQOS4yyP9E/7YlsB0jjw1Ycukgr2ycEzKyIk5tms5WnLBymaewc6VmRKnn5IJWgK4eFw==
|
||||||
|
|
||||||
|
"@jridgewell/gen-mapping@^0.1.0":
|
||||||
|
version "0.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996"
|
||||||
|
integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/set-array" "^1.0.0"
|
||||||
|
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||||
|
|
||||||
|
"@jridgewell/gen-mapping@^0.3.2":
|
||||||
|
version "0.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9"
|
||||||
|
integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/set-array" "^1.0.1"
|
||||||
|
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||||
|
"@jridgewell/trace-mapping" "^0.3.9"
|
||||||
|
|
||||||
|
"@jridgewell/resolve-uri@^3.0.3":
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
|
||||||
|
integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
|
||||||
|
|
||||||
|
"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1":
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
|
||||||
|
integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
|
||||||
|
|
||||||
|
"@jridgewell/sourcemap-codec@^1.4.10":
|
||||||
|
version "1.4.14"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
|
||||||
|
integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
|
||||||
|
|
||||||
|
"@jridgewell/trace-mapping@^0.3.9":
|
||||||
|
version "0.3.14"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed"
|
||||||
|
integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/resolve-uri" "^3.0.3"
|
||||||
|
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||||
|
|
||||||
|
"@types/prop-types@*":
|
||||||
|
version "15.7.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf"
|
||||||
|
integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==
|
||||||
|
|
||||||
|
"@types/react-dom@18.3.1":
|
||||||
|
version "18.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.1.tgz#1e4654c08a9cdcfb6594c780ac59b55aad42fe07"
|
||||||
|
integrity sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/react" "*"
|
||||||
|
|
||||||
|
"@types/react@*":
|
||||||
|
version "18.0.15"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.15.tgz#d355644c26832dc27f3e6cbf0c4f4603fc4ab7fe"
|
||||||
|
integrity sha512-iz3BtLuIYH1uWdsv6wXYdhozhqj20oD4/Hk2DNXIn1kFsmp9x8d9QB6FnPhfkbhd2PgEONt9Q1x/ebkwjfFLow==
|
||||||
|
dependencies:
|
||||||
|
"@types/prop-types" "*"
|
||||||
|
"@types/scheduler" "*"
|
||||||
|
csstype "^3.0.2"
|
||||||
|
|
||||||
|
"@types/react@18.3.12":
|
||||||
|
version "18.3.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.12.tgz#99419f182ccd69151813b7ee24b792fe08774f60"
|
||||||
|
integrity sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==
|
||||||
|
dependencies:
|
||||||
|
"@types/prop-types" "*"
|
||||||
|
csstype "^3.0.2"
|
||||||
|
|
||||||
|
"@types/scheduler@*":
|
||||||
|
version "0.16.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
|
||||||
|
integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
|
||||||
|
|
||||||
|
"@vitejs/plugin-react@2.2.0":
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-2.2.0.tgz#1b9f63b8b6bc3f56258d20cd19b33f5cc761ce6e"
|
||||||
|
integrity sha512-FFpefhvExd1toVRlokZgxgy2JtnBOdp4ZDsq7ldCWaqGSGn9UhWMAVm/1lxPL14JfNS5yGz+s9yFrQY6shoStA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/core" "^7.19.6"
|
||||||
|
"@babel/plugin-transform-react-jsx" "^7.19.0"
|
||||||
|
"@babel/plugin-transform-react-jsx-development" "^7.18.6"
|
||||||
|
"@babel/plugin-transform-react-jsx-self" "^7.18.6"
|
||||||
|
"@babel/plugin-transform-react-jsx-source" "^7.19.6"
|
||||||
|
magic-string "^0.26.7"
|
||||||
|
react-refresh "^0.14.0"
|
||||||
|
|
||||||
|
ansi-styles@^3.2.1:
|
||||||
|
version "3.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
|
||||||
|
integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
|
||||||
|
dependencies:
|
||||||
|
color-convert "^1.9.0"
|
||||||
|
|
||||||
|
browserslist@^4.21.3:
|
||||||
|
version "4.21.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987"
|
||||||
|
integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==
|
||||||
|
dependencies:
|
||||||
|
caniuse-lite "^1.0.30001400"
|
||||||
|
electron-to-chromium "^1.4.251"
|
||||||
|
node-releases "^2.0.6"
|
||||||
|
update-browserslist-db "^1.0.9"
|
||||||
|
|
||||||
|
caniuse-lite@^1.0.30001400:
|
||||||
|
version "1.0.30001426"
|
||||||
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001426.tgz#58da20446ccd0cb1dfebd11d2350c907ee7c2eaa"
|
||||||
|
integrity sha512-n7cosrHLl8AWt0wwZw/PJZgUg3lV0gk9LMI7ikGJwhyhgsd2Nb65vKvmSexCqq/J7rbH3mFG6yZZiPR5dLPW5A==
|
||||||
|
|
||||||
|
chalk@^2.0.0:
|
||||||
|
version "2.4.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
||||||
|
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
||||||
|
dependencies:
|
||||||
|
ansi-styles "^3.2.1"
|
||||||
|
escape-string-regexp "^1.0.5"
|
||||||
|
supports-color "^5.3.0"
|
||||||
|
|
||||||
|
color-convert@^1.9.0:
|
||||||
|
version "1.9.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
||||||
|
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
|
||||||
|
dependencies:
|
||||||
|
color-name "1.1.3"
|
||||||
|
|
||||||
|
color-name@1.1.3:
|
||||||
|
version "1.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
|
||||||
|
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
|
||||||
|
|
||||||
|
convert-source-map@^1.7.0:
|
||||||
|
version "1.8.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369"
|
||||||
|
integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==
|
||||||
|
dependencies:
|
||||||
|
safe-buffer "~5.1.1"
|
||||||
|
|
||||||
|
csstype@^3.0.2:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.0.tgz#4ddcac3718d787cf9df0d1b7d15033925c8f29f2"
|
||||||
|
integrity sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==
|
||||||
|
|
||||||
|
debug@^4.1.0:
|
||||||
|
version "4.3.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||||
|
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
|
||||||
|
dependencies:
|
||||||
|
ms "2.1.2"
|
||||||
|
|
||||||
|
electron-to-chromium@^1.4.251:
|
||||||
|
version "1.4.284"
|
||||||
|
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592"
|
||||||
|
integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==
|
||||||
|
|
||||||
|
esbuild-android-64@0.15.12:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.15.12.tgz#5e8151d5f0a748c71a7fbea8cee844ccf008e6fc"
|
||||||
|
integrity sha512-MJKXwvPY9g0rGps0+U65HlTsM1wUs9lbjt5CU19RESqycGFDRijMDQsh68MtbzkqWSRdEtiKS1mtPzKneaAI0Q==
|
||||||
|
|
||||||
|
esbuild-android-arm64@0.15.12:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.15.12.tgz#5ee72a6baa444bc96ffcb472a3ba4aba2cc80666"
|
||||||
|
integrity sha512-Hc9SEcZbIMhhLcvhr1DH+lrrec9SFTiRzfJ7EGSBZiiw994gfkVV6vG0sLWqQQ6DD7V4+OggB+Hn0IRUdDUqvA==
|
||||||
|
|
||||||
|
esbuild-darwin-64@0.15.12:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.15.12.tgz#70047007e093fa1b3ba7ef86f9b3fa63db51fe25"
|
||||||
|
integrity sha512-qkmqrTVYPFiePt5qFjP8w/S+GIUMbt6k8qmiPraECUWfPptaPJUGkCKrWEfYFRWB7bY23FV95rhvPyh/KARP8Q==
|
||||||
|
|
||||||
|
esbuild-darwin-arm64@0.15.12:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.12.tgz#41c951f23d9a70539bcca552bae6e5196696ae04"
|
||||||
|
integrity sha512-z4zPX02tQ41kcXMyN3c/GfZpIjKoI/BzHrdKUwhC/Ki5BAhWv59A9M8H+iqaRbwpzYrYidTybBwiZAIWCLJAkw==
|
||||||
|
|
||||||
|
esbuild-freebsd-64@0.15.12:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.12.tgz#a761b5afd12bbedb7d56c612e9cfa4d2711f33f0"
|
||||||
|
integrity sha512-XFL7gKMCKXLDiAiBjhLG0XECliXaRLTZh6hsyzqUqPUf/PY4C6EJDTKIeqqPKXaVJ8+fzNek88285krSz1QECw==
|
||||||
|
|
||||||
|
esbuild-freebsd-arm64@0.15.12:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.12.tgz#6b0839d4d58deabc6cbd96276eb8cbf94f7f335e"
|
||||||
|
integrity sha512-jwEIu5UCUk6TjiG1X+KQnCGISI+ILnXzIzt9yDVrhjug2fkYzlLbl0K43q96Q3KB66v6N1UFF0r5Ks4Xo7i72g==
|
||||||
|
|
||||||
|
esbuild-linux-32@0.15.12:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.15.12.tgz#bd50bfe22514d434d97d5150977496e2631345b4"
|
||||||
|
integrity sha512-uSQuSEyF1kVzGzuIr4XM+v7TPKxHjBnLcwv2yPyCz8riV8VUCnO/C4BF3w5dHiVpCd5Z1cebBtZJNlC4anWpwA==
|
||||||
|
|
||||||
|
esbuild-linux-64@0.15.12:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.15.12.tgz#074bb2b194bf658245f8490f29c01ffcdfa8c931"
|
||||||
|
integrity sha512-QcgCKb7zfJxqT9o5z9ZUeGH1k8N6iX1Y7VNsEi5F9+HzN1OIx7ESxtQXDN9jbeUSPiRH1n9cw6gFT3H4qbdvcA==
|
||||||
|
|
||||||
|
esbuild-linux-arm64@0.15.12:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.12.tgz#3bf789c4396dc032875a122988efd6f3733f28f5"
|
||||||
|
integrity sha512-HtNq5xm8fUpZKwWKS2/YGwSfTF+339L4aIA8yphNKYJckd5hVdhfdl6GM2P3HwLSCORS++++7++//ApEwXEuAQ==
|
||||||
|
|
||||||
|
esbuild-linux-arm@0.15.12:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.15.12.tgz#b91b5a8d470053f6c2c9c8a5e67ec10a71fe4a67"
|
||||||
|
integrity sha512-Wf7T0aNylGcLu7hBnzMvsTfEXdEdJY/hY3u36Vla21aY66xR0MS5I1Hw8nVquXjTN0A6fk/vnr32tkC/C2lb0A==
|
||||||
|
|
||||||
|
esbuild-linux-mips64le@0.15.12:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.12.tgz#2fb54099ada3c950a7536dfcba46172c61e580e2"
|
||||||
|
integrity sha512-Qol3+AvivngUZkTVFgLpb0H6DT+N5/zM3V1YgTkryPYFeUvuT5JFNDR3ZiS6LxhyF8EE+fiNtzwlPqMDqVcc6A==
|
||||||
|
|
||||||
|
esbuild-linux-ppc64le@0.15.12:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.12.tgz#9e3b8c09825fb27886249dfb3142a750df29a1b7"
|
||||||
|
integrity sha512-4D8qUCo+CFKaR0cGXtGyVsOI7w7k93Qxb3KFXWr75An0DHamYzq8lt7TNZKoOq/Gh8c40/aKaxvcZnTgQ0TJNg==
|
||||||
|
|
||||||
|
esbuild-linux-riscv64@0.15.12:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.12.tgz#923d0f5b6e12ee0d1fe116b08e4ae4478fe40693"
|
||||||
|
integrity sha512-G9w6NcuuCI6TUUxe6ka0enjZHDnSVK8bO+1qDhMOCtl7Tr78CcZilJj8SGLN00zO5iIlwNRZKHjdMpfFgNn1VA==
|
||||||
|
|
||||||
|
esbuild-linux-s390x@0.15.12:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.12.tgz#3b1620220482b96266a0c6d9d471d451a1eab86f"
|
||||||
|
integrity sha512-Lt6BDnuXbXeqSlVuuUM5z18GkJAZf3ERskGZbAWjrQoi9xbEIsj/hEzVnSAFLtkfLuy2DE4RwTcX02tZFunXww==
|
||||||
|
|
||||||
|
esbuild-netbsd-64@0.15.12:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.12.tgz#276730f80da646859b1af5a740e7802d8cd73e42"
|
||||||
|
integrity sha512-jlUxCiHO1dsqoURZDQts+HK100o0hXfi4t54MNRMCAqKGAV33JCVvMplLAa2FwviSojT/5ZG5HUfG3gstwAG8w==
|
||||||
|
|
||||||
|
esbuild-openbsd-64@0.15.12:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.12.tgz#bd0eea1dd2ca0722ed489d88c26714034429f8ae"
|
||||||
|
integrity sha512-1o1uAfRTMIWNOmpf8v7iudND0L6zRBYSH45sofCZywrcf7NcZA+c7aFsS1YryU+yN7aRppTqdUK1PgbZVaB1Dw==
|
||||||
|
|
||||||
|
esbuild-sunos-64@0.15.12:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.15.12.tgz#5e56bf9eef3b2d92360d6d29dcde7722acbecc9e"
|
||||||
|
integrity sha512-nkl251DpoWoBO9Eq9aFdoIt2yYmp4I3kvQjba3jFKlMXuqQ9A4q+JaqdkCouG3DHgAGnzshzaGu6xofGcXyPXg==
|
||||||
|
|
||||||
|
esbuild-windows-32@0.15.12:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.15.12.tgz#a4f1a301c1a2fa7701fcd4b91ef9d2620cf293d0"
|
||||||
|
integrity sha512-WlGeBZHgPC00O08luIp5B2SP4cNCp/PcS+3Pcg31kdcJPopHxLkdCXtadLU9J82LCfw4TVls21A6lilQ9mzHrw==
|
||||||
|
|
||||||
|
esbuild-windows-64@0.15.12:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.15.12.tgz#bc2b467541744d653be4fe64eaa9b0dbbf8e07f6"
|
||||||
|
integrity sha512-VActO3WnWZSN//xjSfbiGOSyC+wkZtI8I4KlgrTo5oHJM6z3MZZBCuFaZHd8hzf/W9KPhF0lY8OqlmWC9HO5AA==
|
||||||
|
|
||||||
|
esbuild-windows-arm64@0.15.12:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.12.tgz#9a7266404334a86be800957eaee9aef94c3df328"
|
||||||
|
integrity sha512-Of3MIacva1OK/m4zCNIvBfz8VVROBmQT+gRX6pFTLPngFYcj6TFH/12VveAqq1k9VB2l28EoVMNMUCcmsfwyuA==
|
||||||
|
|
||||||
|
esbuild@^0.15.9:
|
||||||
|
version "0.15.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.15.12.tgz#6c8e22d6d3b7430d165c33848298d3fc9a1f251c"
|
||||||
|
integrity sha512-PcT+/wyDqJQsRVhaE9uX/Oq4XLrFh0ce/bs2TJh4CSaw9xuvI+xFrH2nAYOADbhQjUgAhNWC5LKoUsakm4dxng==
|
||||||
|
optionalDependencies:
|
||||||
|
"@esbuild/android-arm" "0.15.12"
|
||||||
|
"@esbuild/linux-loong64" "0.15.12"
|
||||||
|
esbuild-android-64 "0.15.12"
|
||||||
|
esbuild-android-arm64 "0.15.12"
|
||||||
|
esbuild-darwin-64 "0.15.12"
|
||||||
|
esbuild-darwin-arm64 "0.15.12"
|
||||||
|
esbuild-freebsd-64 "0.15.12"
|
||||||
|
esbuild-freebsd-arm64 "0.15.12"
|
||||||
|
esbuild-linux-32 "0.15.12"
|
||||||
|
esbuild-linux-64 "0.15.12"
|
||||||
|
esbuild-linux-arm "0.15.12"
|
||||||
|
esbuild-linux-arm64 "0.15.12"
|
||||||
|
esbuild-linux-mips64le "0.15.12"
|
||||||
|
esbuild-linux-ppc64le "0.15.12"
|
||||||
|
esbuild-linux-riscv64 "0.15.12"
|
||||||
|
esbuild-linux-s390x "0.15.12"
|
||||||
|
esbuild-netbsd-64 "0.15.12"
|
||||||
|
esbuild-openbsd-64 "0.15.12"
|
||||||
|
esbuild-sunos-64 "0.15.12"
|
||||||
|
esbuild-windows-32 "0.15.12"
|
||||||
|
esbuild-windows-64 "0.15.12"
|
||||||
|
esbuild-windows-arm64 "0.15.12"
|
||||||
|
|
||||||
|
escalade@^3.1.1:
|
||||||
|
version "3.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||||
|
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
|
||||||
|
|
||||||
|
escape-string-regexp@^1.0.5:
|
||||||
|
version "1.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||||
|
integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
|
||||||
|
|
||||||
|
fsevents@~2.3.2:
|
||||||
|
version "2.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
|
||||||
|
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
|
||||||
|
|
||||||
|
function-bind@^1.1.1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||||
|
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
||||||
|
|
||||||
|
gensync@^1.0.0-beta.2:
|
||||||
|
version "1.0.0-beta.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
||||||
|
integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
|
||||||
|
|
||||||
|
globals@^11.1.0:
|
||||||
|
version "11.12.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
|
||||||
|
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
|
||||||
|
|
||||||
|
has-flag@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
||||||
|
integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==
|
||||||
|
|
||||||
|
has@^1.0.3:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
|
||||||
|
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
|
||||||
|
dependencies:
|
||||||
|
function-bind "^1.1.1"
|
||||||
|
|
||||||
|
is-core-module@^2.9.0:
|
||||||
|
version "2.9.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69"
|
||||||
|
integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==
|
||||||
|
dependencies:
|
||||||
|
has "^1.0.3"
|
||||||
|
|
||||||
|
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||||
|
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||||
|
|
||||||
|
jsesc@^2.5.1:
|
||||||
|
version "2.5.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
|
||||||
|
integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
|
||||||
|
|
||||||
|
json5@^2.2.1:
|
||||||
|
version "2.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c"
|
||||||
|
integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
|
||||||
|
|
||||||
|
loose-envify@^1.1.0:
|
||||||
|
version "1.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||||
|
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||||
|
dependencies:
|
||||||
|
js-tokens "^3.0.0 || ^4.0.0"
|
||||||
|
|
||||||
|
magic-string@^0.26.7:
|
||||||
|
version "0.26.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.26.7.tgz#caf7daf61b34e9982f8228c4527474dac8981d6f"
|
||||||
|
integrity sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==
|
||||||
|
dependencies:
|
||||||
|
sourcemap-codec "^1.4.8"
|
||||||
|
|
||||||
|
ms@2.1.2:
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||||
|
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||||
|
|
||||||
|
nanoid@^3.3.4:
|
||||||
|
version "3.3.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
|
||||||
|
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
|
||||||
|
|
||||||
|
node-releases@^2.0.6:
|
||||||
|
version "2.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503"
|
||||||
|
integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==
|
||||||
|
|
||||||
|
path-parse@^1.0.7:
|
||||||
|
version "1.0.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
||||||
|
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
||||||
|
|
||||||
|
picocolors@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
|
||||||
|
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
|
||||||
|
|
||||||
|
postcss@^8.4.18:
|
||||||
|
version "8.4.18"
|
||||||
|
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.18.tgz#6d50046ea7d3d66a85e0e782074e7203bc7fbca2"
|
||||||
|
integrity sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==
|
||||||
|
dependencies:
|
||||||
|
nanoid "^3.3.4"
|
||||||
|
picocolors "^1.0.0"
|
||||||
|
source-map-js "^1.0.2"
|
||||||
|
|
||||||
|
react-dom@18.3.1:
|
||||||
|
version "18.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4"
|
||||||
|
integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==
|
||||||
|
dependencies:
|
||||||
|
loose-envify "^1.1.0"
|
||||||
|
scheduler "^0.23.2"
|
||||||
|
|
||||||
|
react-refresh@^0.14.0:
|
||||||
|
version "0.14.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e"
|
||||||
|
integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==
|
||||||
|
|
||||||
|
react@18.3.1:
|
||||||
|
version "18.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891"
|
||||||
|
integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==
|
||||||
|
dependencies:
|
||||||
|
loose-envify "^1.1.0"
|
||||||
|
|
||||||
|
resolve@^1.22.1:
|
||||||
|
version "1.22.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
|
||||||
|
integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
|
||||||
|
dependencies:
|
||||||
|
is-core-module "^2.9.0"
|
||||||
|
path-parse "^1.0.7"
|
||||||
|
supports-preserve-symlinks-flag "^1.0.0"
|
||||||
|
|
||||||
|
rollup@^2.79.1:
|
||||||
|
version "2.79.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7"
|
||||||
|
integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==
|
||||||
|
optionalDependencies:
|
||||||
|
fsevents "~2.3.2"
|
||||||
|
|
||||||
|
safe-buffer@~5.1.1:
|
||||||
|
version "5.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||||
|
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||||
|
|
||||||
|
scheduler@^0.23.2:
|
||||||
|
version "0.23.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3"
|
||||||
|
integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==
|
||||||
|
dependencies:
|
||||||
|
loose-envify "^1.1.0"
|
||||||
|
|
||||||
|
semver@^6.3.0:
|
||||||
|
version "6.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||||
|
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||||
|
|
||||||
|
source-map-js@^1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
||||||
|
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
||||||
|
|
||||||
|
sourcemap-codec@^1.4.8:
|
||||||
|
version "1.4.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
|
||||||
|
integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
|
||||||
|
|
||||||
|
supports-color@^5.3.0:
|
||||||
|
version "5.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
|
||||||
|
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
|
||||||
|
dependencies:
|
||||||
|
has-flag "^3.0.0"
|
||||||
|
|
||||||
|
supports-preserve-symlinks-flag@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
||||||
|
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
||||||
|
|
||||||
|
to-fast-properties@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
|
||||||
|
integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==
|
||||||
|
|
||||||
|
typescript@4.9.3:
|
||||||
|
version "4.9.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.3.tgz#3aea307c1746b8c384435d8ac36b8a2e580d85db"
|
||||||
|
integrity sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==
|
||||||
|
|
||||||
|
update-browserslist-db@^1.0.9:
|
||||||
|
version "1.0.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3"
|
||||||
|
integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==
|
||||||
|
dependencies:
|
||||||
|
escalade "^3.1.1"
|
||||||
|
picocolors "^1.0.0"
|
||||||
|
|
||||||
|
vite@3.2.4:
|
||||||
|
version "3.2.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/vite/-/vite-3.2.4.tgz#d8c7892dd4268064e04fffbe7d866207dd24166e"
|
||||||
|
integrity sha512-Z2X6SRAffOUYTa+sLy3NQ7nlHFU100xwanq1WDwqaiFiCe+25zdxP1TfCS5ojPV2oDDcXudHIoPnI1Z/66B7Yw==
|
||||||
|
dependencies:
|
||||||
|
esbuild "^0.15.9"
|
||||||
|
postcss "^8.4.18"
|
||||||
|
resolve "^1.22.1"
|
||||||
|
rollup "^2.79.1"
|
||||||
|
optionalDependencies:
|
||||||
|
fsevents "~2.3.2"
|
Loading…
Reference in New Issue
Block a user