Commit dffd63b58af4
tarball50 files changed+4787-1246
@@ -4,7 +4,7 @@
44
/web/dist55
/web/dist-device66
/web/src/worker/pkg7
-/web/.test-dist7
+/web/storybook-static88
/result99
/.direnv1010
/.env@@ -0,0 +1,13 @@
1
+{2
+ "mcpServers": {3
+ "storybook": {4
+ "type": "http",5
+ "url": "http://localhost:6006/mcp"6
+ },7
+ "chrome-devtools": {8
+ "type": "stdio",9
+ "command": "npx",10
+ "args": ["-y", "chrome-devtools-mcp@latest", "--executablePath", "${CHROMIUM_PATH}"]11
+ }12
+ }13
+}@@ -2071,9 +2071,9 @@ dependencies = [
20712071
"futures-util",20722072
"hex",20732073
"http-body-util",2074
- "listenfd",20752074
"macltok",20762075
"malice-core",2076
+ "malice-static",20772077
"matrix-sdk",20782078
"rand_core 0.6.4",20792079
"reqwest",@@ -2095,14 +2095,26 @@ name = "malice-core"
20952095
version = "0.1.0"20962096
dependencies = [20972097
"futures-util",2098
- "http",20992098
"macltok",2100
- "ruma",21012099
"serde",21022100
"serde_json",21032101
]21042102
21052103
[[package]]2104
+name = "malice-static"2105
+version = "0.1.0"2106
+dependencies = [2107
+ "axum",2108
+ "listenfd",2109
+ "reqwest",2110
+ "tempfile",2111
+ "tokio",2112
+ "tower-http",2113
+ "tracing",2114
+ "tracing-subscriber",2115
+]2116
+2117
+[[package]]21062118
name = "maplit"21072119
version = "1.0.2"21082120
source = "registry+https://github.com/rust-lang/crates.io-index"@@ -1,6 +1,6 @@
11
[workspace]22
resolver = "3"3
-members = ["crates/malice-core", "crates/malice-server"]3
+members = ["crates/malice-core", "crates/malice-server", "crates/malice-static"]44
55
[workspace.dependencies]66
macltok = { path = "vendor/macltok" }@@ -0,0 +1,103 @@
1
+# macltok request, keep Matrix protocol knowledge out of hosts2
+3
+## Problem4
+5
+malice should know how to represent Matrix things (show a homeserver field, print ids as strings)6
+and nothing more. Today it carries protocol knowledge macltok should own, and some of it is written7
+twice, once in `malice-server` and once in `malice-worker`. Every other macltok host would have to8
+write the same code. Five requests, ordered by impact.9
+10
+## 1. Avatars as `MediaId`, not MXC URIs11
+12
+`RoomSummary::avatar` and the other `avatar` fields in `model.rs` are `Option<OwnedMxcUri>`, so a host13
+fetches them with `ClientHandle::mxc_media(&MxcUri, MediaSize)`. Attachments go through the opaque14
+`MediaId` and `ClientHandle::media`. Because of that split, malice validates raw `mxc://` strings15
+with `ruma::MxcUri::is_valid` and sends MXC URIs over its HTTP API to the browser and back.16
+17
+Request, register avatars like attachments and expose them as `Option<MediaId>`, or as18
+`MediaDescriptor` if the mimetype or size is known. Then hosts fetch every image through19
+`media(&MediaId, MediaSize)`. `mxc_media` can stay for hosts that want it, but no model field20
+should require it.21
+22
+`set_avatar(Option<OwnedMxcUri>)` is fine as it is if its input comes from an upload outcome23
+and not from the host.24
+25
+## 2. Soft-logout re-login decision26
+27
+malice runs the same flow in `malice-server/src/state.rs` (`login`) and28
+`malice-worker/src/lib.rs` (`Host::login`). It restores the store, and on29
+`Restore::SoftLoggedOut(soft)` checks whether the submitted username is that user. If so it calls30
+`soft.password_login(password)` to keep the device and its keys. Otherwise it does a fresh31
+`PasswordLogin::new(..)`. The username check is copied in both crates.32
+33
+```rust34
+fn username_matches(submitted: &str, user_id: &ruma::OwnedUserId) -> bool {35
+ let submitted = submitted.trim();36
+ submitted == user_id.as_str() || submitted == user_id.localpart()37
+}38
+```39
+40
+That check is Matrix knowledge (a localpart or a full MXID names the same account), and it is41
+only correct when the homeserver also matches.42
+43
+Request, either shape works.44
+45
+```rust46
+impl SoftLogout {47
+ /// whether a login form's homeserver and username name this soft-logged-out account48
+ pub fn matches(&self, homeserver: &str, username: &str) -> bool;49
+}50
+```51
+52
+Or have `Session::login(PasswordLogin, sessions)` resume a soft-logged-out record in `sessions`53
+by itself when it names the same account, so hosts never branch on it. The second shape is54
+preferred because both malice call sites would shrink to one call.55
+56
+## 3. Homeserver input validation, and a discovery bug it causes57
+58
+macltok builds the client with `server_name_or_homeserver_url(login.homeserver.trim())`, which59
+does `.well-known` discovery for a bare server name. malice runs `normalise_homeserver`60
+(`malice-core/src/login.rs`) first, and that prefixes `https://` onto anything without a scheme.61
+So a user typing `example.org`, whose homeserver is `matrix.example.org`, gets62
+`https://example.org` treated as a homeserver URL and discovery never runs. malice will drop its63
+normaliser once macltok covers what it checks.64
+65
+- reject empty input and input containing whitespace66
+- reject schemes other than http and https67
+- reject a userinfo part (`user@host`) and a missing host68
+- reject plain http unless the host opts in, and even then only for loopback hosts (`localhost`,69
+ `127.0.0.1`, `::1`)70
+71
+Suggested shape is a builder option plus a typed error.72
+73
+```rust74
+PasswordLogin::new(homeserver, username, password)75
+ .allow_insecure_loopback(true)76
+```77
+78
+with a distinct `AccountError` variant (or `ErrorKind`) for invalid homeserver input, so a host can79
+answer 400 with the message instead of a generic login failure. The same validation should apply80
+to the OAuth login path.81
+82
+## 4. `AccountError::Operation` hides the homeserver's answer83
+84
+`Operation` displays as `"{context} failed"` and the useful part (the homeserver's errcode and85
+message) is only in `source()`. malice has a `describe_error` helper that walks the source chain to86
+build a readable message. Every host would need it.87
+88
+Request, include the innermost meaningful cause in `Display`, or add an accessor such as89
+`AccountError::user_message() -> String` that renders the chain.90
+91
+## 5. Re-export `ruma`92
+93
+macltok's public API is typed with ruma (`OwnedRoomId`, `OwnedEventId`, `OwnedUserId`,94
+`OwnedRoomOrAliasId`, `OwnedMxcUri`), so hosts must depend on ruma at exactly macltok's version.95
+malice pins `ruma = "0.16"` in two places to match.96
+97
+Request, `pub use ruma;` in `lib.rs`, same as `imbl`. malice will then parse ids through98
+`macltok::ruma` and drop its own ruma dependency.99
+100
+## Not needed101
+102
+`VerificationAction` already derives `Deserialize` under the `serde` feature, so malice will drop its103
+hand-written string match on its own.@@ -75,9 +75,13 @@ From the repository root:
7575
7676
```sh7777
nix develop78
-npm --prefix web ci7978
```8079
80
+The dev shell links `web/node_modules` from a nix build of `web/package-lock.json`,81
+so there is no install step. After changing dependencies in `web/package.json`,82
+refresh the lockfile with `npm --prefix web install --package-lock-only` and83
+re-enter the shell.84
+8185
For live frontend changes, start these in separate terminals inside `nix develop`:8286
8387
```sh@@ -102,15 +106,31 @@ points at another built frontend directory. Local session data defaults to
102106
`local-data/`; set `MALICE_DATA_DIR` to use another directory. Keep its103107
`master.key` and session files private.104108
109
+### Storybook110
+111
+Component stories live next to their components as `web/src/**/*.stories.ts`.112
+Storybook runs inside `nix develop`:113
+114
+```sh115
+cd web116
+npm run storybook117
+npm run build-storybook118
+```119
+120
+Open `http://localhost:6006/`. While it runs, `@storybook/addon-mcp` serves an121
+MCP endpoint at `http://localhost:6006/mcp`, which the repository `.mcp.json`122
+registers for Claude Code in this project only.123
+105124
## Testing106125
107
-In `nix develop`, after `npm --prefix web ci`:126
+In `nix develop`:108127
109128
```sh110129
cargo fmt -- --check111130
cargo clippy --all-targets -- -D warnings112131
cargo test --all-targets113
-npm --prefix web exec -- tsc --noEmit -p web/tsconfig.json132
+npm --prefix web run check133
+npm --prefix web test114134
npm --prefix web run build115135
```116136
@@ -9,10 +9,8 @@ name = "malice_core"
99
[dependencies]1010
macltok = { workspace = true, features = ["serde", "mirror"] }1111
futures-util = { version = "0.3", default-features = false, features = ["std"] }12
-ruma = { workspace = true }1312
serde = { workspace = true }1413
serde_json = { workspace = true }15
-http = { workspace = true }1614
1715
[lints]1816
workspace = true@@ -3,6 +3,7 @@ use serde::Serialize;
33
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]44
pub enum Failure {55
BadRequest,6
+ Unauthorized,67
NotFound,78
Conflict,89
Busy,@@ -1,6 +1,7 @@
1
+use macltok::{AccountError, PasswordLogin};12
use serde::Deserialize;23
3
-use crate::error::CoreError;4
+use crate::error::{CoreError, Failure};45
56
#[derive(Debug, Deserialize)]67
pub struct LoginInput {@@ -13,8 +14,7 @@ pub struct LoginInput {
1314
}1415
1516
impl LoginInput {16
- pub fn validate(self, allow_http: bool) -> Result<LoginInput, CoreError> {17
- let homeserver = normalise_homeserver(&self.homeserver, allow_http)?;17
+ pub fn into_login(self, allow_insecure_loopback: bool) -> Result<PasswordLogin, CoreError> {1818
let username = self.username.trim();1919
if username.is_empty() {2020
return Err(CoreError::bad_request("username is required"));@@ -22,70 +22,31 @@ impl LoginInput {
2222
if self.password.is_empty() {2323
return Err(CoreError::bad_request("password is required"));2424
}25
- Ok(LoginInput {26
- homeserver,27
- username: username.to_owned(),28
- password: self.password,29
- })25
+ Ok(26
+ PasswordLogin::new(self.homeserver.trim(), username, self.password)27
+ .with_device_display_name("malice web")28
+ .allow_insecure_loopback(allow_insecure_loopback),29
+ )3030
}3131
}3232
33
-pub fn normalise_homeserver(raw: &str, allow_http: bool) -> Result<String, CoreError> {34
- let trimmed = raw.trim();35
- if trimmed.is_empty() {36
- return Err(CoreError::bad_request("homeserver is required"));37
- }38
- if trimmed.contains(char::is_whitespace) {39
- return Err(CoreError::bad_request("homeserver must not contain spaces"));40
- }41
- let with_scheme = if trimmed.contains("://") {42
- trimmed.to_owned()43
- } else {44
- format!("https://{trimmed}")33
+pub fn login_error(error: &AccountError, password: &str) -> CoreError {34
+ let (kind, message) = match error {35
+ AccountError::InvalidHomeserver(_) => (Failure::BadRequest, error.to_string()),36
+ AccountError::AlreadyLoggedIn(_) => (Failure::Conflict, error.to_string()),37
+ AccountError::StoreInUse => (Failure::Busy, error.to_string()),38
+ error => match error.server() {39
+ Some(server) if matches!(server.status, 401 | 403) => {40
+ (Failure::Unauthorized, server.message.clone())41
+ }42
+ Some(server) => (Failure::Upstream, server.message.clone()),43
+ None => (Failure::Upstream, error.to_string()),44
+ },4545
};46
- let uri: http::Uri = with_scheme47
- .parse()48
- .map_err(|_| CoreError::bad_request("invalid homeserver"))?;49
- let scheme = uri50
- .scheme_str()51
- .ok_or_else(|| CoreError::bad_request("invalid homeserver"))?;52
- if !scheme.eq_ignore_ascii_case("http") && !scheme.eq_ignore_ascii_case("https") {53
- return Err(CoreError::bad_request("homeserver must use http(s)"));54
- }55
- let authority = uri56
- .authority()57
- .ok_or_else(|| CoreError::bad_request("homeserver must include a host"))?;58
- if authority.as_str().contains('@') || authority.host().is_empty() {59
- return Err(CoreError::bad_request("homeserver must include a host"));60
- }61
- if scheme.eq_ignore_ascii_case("http") {62
- let host = authority.host().trim_end_matches('.');63
- let loopback = host.eq_ignore_ascii_case("localhost")64
- || host == "127.0.0.1"65
- || host == "[::1]"66
- || host == "::1";67
- if !(allow_http && loopback) {68
- return Err(CoreError::bad_request(69
- "insecure http homeservers are not allowed",70
- ));71
- }72
- }73
- Ok(with_scheme)74
-}75
-76
-/// macltok's `AccountError` displays only its context, the homeserver's answer is in the sources77
-pub fn describe_error(error: &(dyn std::error::Error + 'static)) -> String {78
- let mut message = error.to_string();79
- let mut source = error.source();80
- while let Some(cause) = source {81
- message.push_str(", ");82
- message.push_str(&cause.to_string());83
- source = cause.source();84
- }85
- message46
+ CoreError::new(kind, sanitise_auth_error(&message, password))8647
}8748
88
-pub fn sanitise_auth_error(message: &str, password: &str) -> String {49
+fn sanitise_auth_error(message: &str, password: &str) -> String {8950
let message = if password.is_empty() {9051
message.to_owned()9152
} else {@@ -1,25 +1,27 @@
1
+use macltok::ruma::{OwnedEventId, OwnedRoomId, OwnedRoomOrAliasId};2
+13
use crate::error::CoreError;24
3
-pub fn parse_room_id(raw: &str) -> Result<ruma::OwnedRoomId, CoreError> {5
+pub fn parse_room_id(raw: &str) -> Result<OwnedRoomId, CoreError> {46
let trimmed = raw.trim();57
if trimmed.is_empty() {68
return Err(CoreError::bad_request("room_id is required"));79
}8
- ruma::OwnedRoomId::try_from(trimmed).map_err(|_| CoreError::bad_request("invalid room_id"))10
+ OwnedRoomId::try_from(trimmed).map_err(|_| CoreError::bad_request("invalid room_id"))911
}1012
11
-pub fn parse_event_id(raw: &str) -> Result<ruma::OwnedEventId, CoreError> {13
+pub fn parse_event_id(raw: &str) -> Result<OwnedEventId, CoreError> {1214
let trimmed = raw.trim();1315
if trimmed.is_empty() {1416
return Err(CoreError::bad_request("event_id is required"));1517
}16
- ruma::OwnedEventId::try_from(trimmed).map_err(|_| CoreError::bad_request("invalid event_id"))18
+ OwnedEventId::try_from(trimmed).map_err(|_| CoreError::bad_request("invalid event_id"))1719
}1820
19
-pub fn parse_room_or_alias(raw: &str) -> Result<ruma::OwnedRoomOrAliasId, CoreError> {21
+pub fn parse_room_or_alias(raw: &str) -> Result<OwnedRoomOrAliasId, CoreError> {2022
let trimmed = raw.trim();2123
if trimmed.is_empty() {2224
return Err(CoreError::bad_request("room is required"));2325
}24
- ruma::OwnedRoomOrAliasId::try_from(trimmed).map_err(|_| CoreError::bad_request("invalid room"))26
+ OwnedRoomOrAliasId::try_from(trimmed).map_err(|_| CoreError::bad_request("invalid room"))2527
}@@ -277,30 +277,18 @@ pub async fn dispatch(
277277
Ok(Reply::Done)278278
}279279
Request::Verify { action } => {280
- let action = match action.as_str() {281
- "Accept" => VerificationAction::Accept,282
- "Confirm" => VerificationAction::Confirm,283
- "Reject" => VerificationAction::Reject,284
- "Cancel" => VerificationAction::Cancel,285
- _ => return Err(CoreError::bad_request("invalid verification action")),286
- };287280
handle.verify(action).await?;288281
Ok(Reply::Done)289282
}290
- Request::Avatar { mxc } => {291
- let mxc_ref = <&ruma::MxcUri>::from(mxc.as_str());292
- if !mxc_ref.is_valid() {293
- return Err(CoreError::bad_request("invalid mxc URI"));294
- }283
+ Request::Avatar { media_id } => {284
+ let media_id = parse_media_id(media_id)?;295285
let size = MediaSize::Thumbnail {296286
width: AVATAR_SIZE,297287
height: AVATAR_SIZE,298288
};299
- let bytes = handle.mxc_media(mxc_ref, size).await?.bytes.to_vec();289
+ let bytes = handle.media(&media_id, size).await?.bytes.to_vec();300290
let Some(content_type) = image_content_type(&bytes) else {301
- return Err(CoreError::unsupported(302
- "MXC content is not a supported image",303
- ));291
+ return Err(CoreError::unsupported("avatar is not a supported image"));304292
};305293
Ok(Reply::Avatar {306294
bytes,@@ -308,10 +296,7 @@ pub async fn dispatch(
308296
})309297
}310298
Request::Media { media_id, size } => {311
- if media_id.is_empty() || media_id.len() > 512 {312
- return Err(CoreError::bad_request("invalid media_id"));313
- }314
- let media_id = MediaId::from(media_id);299
+ let media_id = parse_media_id(media_id)?;315300
let size = match size.as_str() {316301
"Thumbnail" => MediaSize::Thumbnail {317302
width: THUMBNAIL_SIZE,@@ -13,11 +13,11 @@ path = "src/lib.rs"
1313
1414
[dependencies]1515
malice-core = { path = "../malice-core" }16
+malice-static = { path = "../malice-static" }1617
macltok = { workspace = true, features = ["sqlite", "serde", "mirror"] }1718
axum = { version = "0.8", features = ["macros", "multipart"] }1819
futures-util = { version = "0.3", default-features = false, features = ["std"] }1920
hex = "0.4"20
-listenfd = "1"2121
rand_core = { version = "0.6", features = ["getrandom"] }2222
ruma = { workspace = true }2323
serde = { workspace = true }@@ -1,73 +0,0 @@
1
-//! Idle-exit tracking for the socket-activated static-only server: counts2
-//! in-flight requests and the time of the last one, so the process can shut3
-//! itself down once nothing has happened for `MALICE_IDLE_EXIT_SECS`.4
-5
-use std::{6
- sync::{7
- Arc,8
- atomic::{AtomicUsize, Ordering},9
- },10
- time::{Duration, Instant},11
-};12
-13
-use axum::{extract::State, middleware::Next};14
-15
-#[derive(Clone)]16
-pub struct IdleTracker {17
- in_flight: Arc<AtomicUsize>,18
- last_activity: Arc<std::sync::Mutex<Instant>>,19
-}20
-21
-impl IdleTracker {22
- pub fn new() -> Self {23
- Self {24
- in_flight: Arc::new(AtomicUsize::new(0)),25
- last_activity: Arc::new(std::sync::Mutex::new(Instant::now())),26
- }27
- }28
-29
- fn touch(&self) {30
- *self31
- .last_activity32
- .lock()33
- .expect("idle tracker mutex poisoned") = Instant::now();34
- }35
-36
- /// Resolves once no request has started or finished, and none is still37
- /// in flight, for at least `idle`.38
- pub async fn wait_idle(&self, idle: Duration) {39
- loop {40
- tokio::time::sleep(idle.min(Duration::from_millis(200))).await;41
- if self.in_flight.load(Ordering::SeqCst) != 0 {42
- continue;43
- }44
- let elapsed = self45
- .last_activity46
- .lock()47
- .expect("idle tracker mutex poisoned")48
- .elapsed();49
- if elapsed >= idle {50
- return;51
- }52
- }53
- }54
-}55
-56
-impl Default for IdleTracker {57
- fn default() -> Self {58
- Self::new()59
- }60
-}61
-62
-pub async fn track(63
- State(idle): State<IdleTracker>,64
- request: axum::extract::Request,65
- next: Next,66
-) -> axum::response::Response {67
- idle.in_flight.fetch_add(1, Ordering::SeqCst);68
- idle.touch();69
- let response = next.run(request).await;70
- idle.touch();71
- idle.in_flight.fetch_sub(1, Ordering::SeqCst);72
- response73
-}@@ -1,5 +1,4 @@
11
pub mod csrf;22
pub mod error;3
-pub mod idle;43
pub mod routes;54
pub mod state;@@ -1,12 +1,10 @@
1
-use std::{future::Future, net::SocketAddr, path::PathBuf, time::Duration};1
+use std::path::PathBuf;22
3
-use axum::{Router, middleware};4
-use listenfd::ListenFd;53
use malice::{6
- idle::IdleTracker,7
- routes::{router, static_router},4
+ routes::router,85
state::{AppState, ensure_dirs, load_or_create_master_key},96
};7
+use malice_static::{bind_listener, serve};108
119
fn env_flag(name: &str, default: bool) -> bool {1210
match std::env::var(name) {@@ -28,19 +26,6 @@ fn data_dir() -> PathBuf {
2826
.unwrap_or_else(|_| PathBuf::from("local-data"))2927
}3028
31
-fn bind_addr() -> SocketAddr {32
- std::env::var("MALICE_BIND")33
- .unwrap_or_else(|_| "127.0.0.1:3000".to_owned())34
- .parse()35
- .expect("MALICE_BIND must be host:port")36
-}37
-38
-fn idle_exit_secs() -> Option<u64> {39
- std::env::var("MALICE_IDLE_EXIT_SECS")40
- .ok()41
- .and_then(|value| value.trim().parse().ok())42
-}43
-4429
fn web_dir() -> Option<String> {4530
if let Ok(dir) = std::env::var("MALICE_WEB_DIR") {4631
assert!(@@ -57,66 +42,17 @@ fn web_dir() -> Option<String> {
5742
.then(|| local.to_string_lossy().into_owned())5843
}5944
60
-/// Takes over a systemd-activated listener from fd 3 when present, so the61
-/// socket unit can hold the port before the process ever starts. Falls back62
-/// to a plain bind otherwise.63
-async fn bind_listener() -> tokio::net::TcpListener {64
- let mut listenfd = ListenFd::from_env();65
- if let Some(listener) = listenfd66
- .take_tcp_listener(0)67
- .expect("inspecting inherited sockets")68
- {69
- listener70
- .set_nonblocking(true)71
- .expect("setting inherited socket nonblocking");72
- return tokio::net::TcpListener::from_std(listener)73
- .expect("adopting inherited socket into tokio");74
- }75
- let addr = bind_addr();76
- tracing::info!("listening on {addr}");77
- tokio::net::TcpListener::bind(addr)78
- .await79
- .expect("binding the listener must succeed")80
-}81
-82
-/// Serves `app` on `listener`, exiting on ctrl-c or, when83
-/// `MALICE_IDLE_EXIT_SECS` is set, after that long with no request in flight84
-/// or started. `on_shutdown` runs after the exit signal either way.85
-async fn serve(86
- listener: tokio::net::TcpListener,87
- app: Router,88
- on_shutdown: impl Future<Output = ()> + Send + 'static,89
-) {90
- let idle = idle_exit_secs().map(|secs| (IdleTracker::new(), secs));91
- let app = match &idle {92
- Some((tracker, _)) => app.layer(middleware::from_fn_with_state(93
- tracker.clone(),94
- malice::idle::track,95
- )),96
- None => app,97
- };98
- axum::serve(listener, app)99
- .with_graceful_shutdown(async move {100
- match idle {101
- Some((tracker, secs)) => {102
- tokio::select! {103
- _ = tokio::signal::ctrl_c() => {}104
- _ = tracker.wait_idle(Duration::from_secs(secs)) => {105
- tracing::info!("idle for {secs}s with no requests, exiting");106
- }107
- }108
- }109
- None => {110
- let _ = tokio::signal::ctrl_c().await;111
- }112
- }113
- on_shutdown.await;114
- })115
- .await116
- .expect("serving must succeed");117
-}45
+#[tokio::main]46
+async fn main() {47
+ tracing_subscriber::fmt()48
+ .with_env_filter(49
+ tracing_subscriber::EnvFilter::try_from_default_env()50
+ .unwrap_or_else(|_| "malice=info,tower_http=info".into()),51
+ )52
+ .with_target(false)53
+ .compact()54
+ .init();11855
119
-async fn run_hosted() {12056
let data_dir = data_dir();12157
ensure_dirs(&data_dir);12258
let master_key =@@ -133,27 +69,3 @@ async fn run_hosted() {
13369
)13470
.await;13571
}136
-137
-async fn run_static_only() {138
- let app = static_router(web_dir());139
- let listener = bind_listener().await;140
- serve(listener, app, async {}).await;141
-}142
-143
-#[tokio::main]144
-async fn main() {145
- tracing_subscriber::fmt()146
- .with_env_filter(147
- tracing_subscriber::EnvFilter::try_from_default_env()148
- .unwrap_or_else(|_| "malice=info,tower_http=info".into()),149
- )150
- .with_target(false)151
- .compact()152
- .init();153
-154
- if env_flag("MALICE_STATIC_ONLY", false) {155
- run_static_only().await;156
- } else {157
- run_hosted().await;158
- }159
-}@@ -3,11 +3,10 @@ use std::sync::Arc;
33
use axum::{44
Router,55
extract::{DefaultBodyLimit, Multipart, Query, State},6
- http::{HeaderMap, HeaderName, HeaderValue, StatusCode, header},6
+ http::{HeaderMap, StatusCode},77
middleware,8
- middleware::Next,98
response::{IntoResponse, Response, Sse, sse::Event as SseEvent},10
- routing::{any, get, post},9
+ routing::{get, post},1110
};1211
use futures_util::StreamExt;1312
use macltok::Retain;@@ -789,47 +788,3 @@ pub fn router(state: AppState, web_dir: Option<String>) -> Router {
789788
None => router.fallback(static_shell),790789
}791790
}792
-793
-async fn api_not_found() -> StatusCode {794
- StatusCode::NOT_FOUND795
-}796
-797
-fn is_no_cache_path(path: &str) -> bool {798
- matches!(path, "/" | "/index.html" | "/sw.js")799
-}800
-801
-/// index.html and sw.js must never be cached, or a stale service worker or802
-/// app shell survives a rebuild; the rest of the bundle is hashed and can be803
-/// cached freely.804
-async fn static_headers(request: axum::extract::Request, next: Next) -> Response {805
- let no_cache = is_no_cache_path(request.uri().path());806
- let mut response = next.run(request).await;807
- if no_cache {808
- let headers = response.headers_mut();809
- headers.insert(header::CACHE_CONTROL, HeaderValue::from_static("no-cache"));810
- headers.insert(811
- HeaderName::from_static("service-worker-allowed"),812
- HeaderValue::from_static("/"),813
- );814
- }815
- response816
-}817
-818
-/// Serves only the built frontend: no `/api` routes, no session state, no819
-/// data dir. Used for the socket-activated on-device build.820
-pub fn static_router(web_dir: Option<String>) -> Router {821
- let router = Router::new()822
- .route("/api", any(api_not_found))823
- .route("/api/{*rest}", any(api_not_found))824
- .layer(TraceLayer::new_for_http());825
- match web_dir {826
- Some(dir) => {827
- let files =828
- ServeDir::new(&dir).not_found_service(ServeFile::new(format!("{dir}/index.html")));829
- router830
- .fallback_service(files)831
- .layer(middleware::from_fn(static_headers))832
- }833
- None => router.fallback(static_shell),834
- }835
-}@@ -1,139 +0,0 @@
1
-use std::{2
- net::TcpListener,3
- path::PathBuf,4
- process::{Child, Command, Stdio},5
- time::Duration,6
-};7
-8
-use reqwest::{Client, StatusCode, header};9
-use tempfile::TempDir;10
-11
-struct Server(Child);12
-13
-impl Drop for Server {14
- fn drop(&mut self) {15
- let _ = self.0.kill();16
- let _ = self.0.wait();17
- }18
-}19
-20
-fn server_binary() -> PathBuf {21
- option_env!("CARGO_BIN_EXE_malice")22
- .map(PathBuf::from)23
- .unwrap_or_else(|| {24
- std::env::current_exe()25
- .expect("integration test executable")26
- .parent()27
- .expect("cargo deps directory")28
- .parent()29
- .expect("cargo target directory")30
- .join("malice")31
- })32
-}33
-34
-fn unused_port() -> u16 {35
- TcpListener::bind("127.0.0.1:0")36
- .expect("bind ephemeral port")37
- .local_addr()38
- .expect("read ephemeral port")39
- .port()40
-}41
-42
-async fn start(port: u16, web_dir: &TempDir, idle_secs: u64, client: &Client) -> Server {43
- let child = Command::new(server_binary())44
- .env("MALICE_BIND", format!("127.0.0.1:{port}"))45
- .env("MALICE_STATIC_ONLY", "1")46
- .env("MALICE_WEB_DIR", web_dir.path())47
- .env("MALICE_IDLE_EXIT_SECS", idle_secs.to_string())48
- .stdout(Stdio::null())49
- .stderr(Stdio::inherit())50
- .spawn()51
- .expect("start Malice backend");52
- let mut server = Server(child);53
- tokio::time::timeout(Duration::from_secs(30), async {54
- loop {55
- if let Some(status) = server.0.try_wait().expect("poll backend") {56
- panic!("Malice exited before it started serving: {status}");57
- }58
- if client59
- .get(format!("http://127.0.0.1:{port}/"))60
- .send()61
- .await62
- .is_ok_and(|response| response.status().is_success())63
- {64
- break;65
- }66
- tokio::time::sleep(Duration::from_millis(100)).await;67
- }68
- })69
- .await70
- .expect("Malice did not start");71
- server72
-}73
-74
-#[tokio::test]75
-async fn static_only_serves_the_bundle_and_exits_when_idle() {76
- let web_dir = tempfile::tempdir().expect("temporary web dir");77
- std::fs::write(web_dir.path().join("index.html"), "<html>malice</html>")78
- .expect("write index.html");79
- std::fs::write(web_dir.path().join("sw.js"), "// service worker").expect("write sw.js");80
- std::fs::write(web_dir.path().join("style.css"), "body {}").expect("write style.css");81
-82
- let client = Client::new();83
- let port = unused_port();84
- let base = format!("http://127.0.0.1:{port}");85
- let mut server = start(port, &web_dir, 1, &client).await;86
-87
- let index = client.get(&base).send().await.unwrap();88
- assert_eq!(index.status(), StatusCode::OK);89
- assert_eq!(90
- index.headers().get(header::CACHE_CONTROL).unwrap(),91
- "no-cache"92
- );93
- assert_eq!(index.headers().get("service-worker-allowed").unwrap(), "/");94
- assert_eq!(index.text().await.unwrap(), "<html>malice</html>");95
-96
- let sw = client.get(format!("{base}/sw.js")).send().await.unwrap();97
- assert_eq!(sw.status(), StatusCode::OK);98
- assert_eq!(sw.headers().get(header::CACHE_CONTROL).unwrap(), "no-cache");99
- assert_eq!(sw.headers().get("service-worker-allowed").unwrap(), "/");100
-101
- let asset = client102
- .get(format!("{base}/style.css"))103
- .send()104
- .await105
- .unwrap();106
- assert_eq!(asset.status(), StatusCode::OK);107
- assert!(asset.headers().get(header::CACHE_CONTROL).is_none());108
-109
- assert_eq!(110
- client111
- .get(format!("{base}/api/rooms"))112
- .send()113
- .await114
- .unwrap()115
- .status(),116
- StatusCode::NOT_FOUND,117
- );118
- assert_eq!(119
- client120
- .get(format!("{base}/api/"))121
- .send()122
- .await123
- .unwrap()124
- .status(),125
- StatusCode::NOT_FOUND,126
- );127
-128
- let status = tokio::time::timeout(Duration::from_secs(10), async {129
- loop {130
- if let Some(status) = server.0.try_wait().expect("poll backend") {131
- return status;132
- }133
- tokio::time::sleep(Duration::from_millis(50)).await;134
- }135
- })136
- .await137
- .expect("Malice did not exit once idle");138
- assert!(status.success(), "idle exit should be clean: {status}");139
-}@@ -0,0 +1,27 @@
1
+[package]2
+name = "malice-static"3
+version = "0.1.0"4
+edition = "2024"5
+6
+[[bin]]7
+name = "malice-static"8
+path = "src/main.rs"9
+10
+[lib]11
+name = "malice_static"12
+path = "src/lib.rs"13
+14
+[dependencies]15
+axum = { version = "0.8", default-features = false, features = ["http1", "tokio", "tracing"] }16
+listenfd = "1"17
+tokio = { workspace = true, features = ["macros", "net", "rt-multi-thread", "signal", "time"] }18
+tower-http = { version = "0.6", features = ["fs", "trace"] }19
+tracing = { workspace = true }20
+tracing-subscriber = { version = "0.3", features = ["env-filter"] }21
+22
+[dev-dependencies]23
+reqwest = { version = "0.13", default-features = false }24
+tempfile = "3"25
+26
+[lints]27
+workspace = true@@ -0,0 +1,73 @@
1
+//! Idle-exit tracking for the socket-activated static-only server: counts2
+//! in-flight requests and the time of the last one, so the process can shut3
+//! itself down once nothing has happened for `MALICE_IDLE_EXIT_SECS`.4
+5
+use std::{6
+ sync::{7
+ Arc,8
+ atomic::{AtomicUsize, Ordering},9
+ },10
+ time::{Duration, Instant},11
+};12
+13
+use axum::{extract::State, middleware::Next};14
+15
+#[derive(Clone)]16
+pub struct IdleTracker {17
+ in_flight: Arc<AtomicUsize>,18
+ last_activity: Arc<std::sync::Mutex<Instant>>,19
+}20
+21
+impl IdleTracker {22
+ pub fn new() -> Self {23
+ Self {24
+ in_flight: Arc::new(AtomicUsize::new(0)),25
+ last_activity: Arc::new(std::sync::Mutex::new(Instant::now())),26
+ }27
+ }28
+29
+ fn touch(&self) {30
+ *self31
+ .last_activity32
+ .lock()33
+ .expect("idle tracker mutex poisoned") = Instant::now();34
+ }35
+36
+ /// Resolves once no request has started or finished, and none is still37
+ /// in flight, for at least `idle`.38
+ pub async fn wait_idle(&self, idle: Duration) {39
+ loop {40
+ tokio::time::sleep(idle.min(Duration::from_millis(200))).await;41
+ if self.in_flight.load(Ordering::SeqCst) != 0 {42
+ continue;43
+ }44
+ let elapsed = self45
+ .last_activity46
+ .lock()47
+ .expect("idle tracker mutex poisoned")48
+ .elapsed();49
+ if elapsed >= idle {50
+ return;51
+ }52
+ }53
+ }54
+}55
+56
+impl Default for IdleTracker {57
+ fn default() -> Self {58
+ Self::new()59
+ }60
+}61
+62
+pub async fn track(63
+ State(idle): State<IdleTracker>,64
+ request: axum::extract::Request,65
+ next: Next,66
+) -> axum::response::Response {67
+ idle.in_flight.fetch_add(1, Ordering::SeqCst);68
+ idle.touch();69
+ let response = next.run(request).await;70
+ idle.touch();71
+ idle.in_flight.fetch_sub(1, Ordering::SeqCst);72
+ response73
+}@@ -0,0 +1,142 @@
1
+pub mod idle;2
+3
+use std::{future::Future, net::SocketAddr, time::Duration};4
+5
+use axum::{6
+ Router,7
+ http::{HeaderName, HeaderValue, StatusCode, header},8
+ middleware,9
+ middleware::Next,10
+ response::{IntoResponse, Response},11
+ routing::any,12
+};13
+use listenfd::ListenFd;14
+use tower_http::{15
+ services::{ServeDir, ServeFile},16
+ trace::TraceLayer,17
+};18
+19
+use crate::idle::IdleTracker;20
+21
+fn bind_addr() -> SocketAddr {22
+ std::env::var("MALICE_BIND")23
+ .unwrap_or_else(|_| "127.0.0.1:3000".to_owned())24
+ .parse()25
+ .expect("MALICE_BIND must be host:port")26
+}27
+28
+fn idle_exit_secs() -> Option<u64> {29
+ std::env::var("MALICE_IDLE_EXIT_SECS")30
+ .ok()31
+ .and_then(|value| value.trim().parse().ok())32
+}33
+34
+/// Takes over a systemd-activated listener from fd 3 when present, so the35
+/// socket unit can hold the port before the process ever starts. Falls back36
+/// to a plain bind otherwise.37
+pub async fn bind_listener() -> tokio::net::TcpListener {38
+ let mut listenfd = ListenFd::from_env();39
+ if let Some(listener) = listenfd40
+ .take_tcp_listener(0)41
+ .expect("inspecting inherited sockets")42
+ {43
+ listener44
+ .set_nonblocking(true)45
+ .expect("setting inherited socket nonblocking");46
+ return tokio::net::TcpListener::from_std(listener)47
+ .expect("adopting inherited socket into tokio");48
+ }49
+ let addr = bind_addr();50
+ tracing::info!("listening on {addr}");51
+ tokio::net::TcpListener::bind(addr)52
+ .await53
+ .expect("binding the listener must succeed")54
+}55
+56
+/// Serves `app` on `listener`, exiting on ctrl-c or, when57
+/// `MALICE_IDLE_EXIT_SECS` is set, after that long with no request in flight58
+/// or started. `on_shutdown` runs after the exit signal either way.59
+pub async fn serve(60
+ listener: tokio::net::TcpListener,61
+ app: Router,62
+ on_shutdown: impl Future<Output = ()> + Send + 'static,63
+) {64
+ let idle = idle_exit_secs().map(|secs| (IdleTracker::new(), secs));65
+ let app = match &idle {66
+ Some((tracker, _)) => {67
+ app.layer(middleware::from_fn_with_state(tracker.clone(), idle::track))68
+ }69
+ None => app,70
+ };71
+ axum::serve(listener, app)72
+ .with_graceful_shutdown(async move {73
+ match idle {74
+ Some((tracker, secs)) => {75
+ tokio::select! {76
+ _ = tokio::signal::ctrl_c() => {}77
+ _ = tracker.wait_idle(Duration::from_secs(secs)) => {78
+ tracing::info!("idle for {secs}s with no requests, exiting");79
+ }80
+ }81
+ }82
+ None => {83
+ let _ = tokio::signal::ctrl_c().await;84
+ }85
+ }86
+ on_shutdown.await;87
+ })88
+ .await89
+ .expect("serving must succeed");90
+}91
+92
+async fn api_not_found() -> StatusCode {93
+ StatusCode::NOT_FOUND94
+}95
+96
+async fn missing_frontend() -> Response {97
+ (98
+ StatusCode::SERVICE_UNAVAILABLE,99
+ "frontend assets missing; set MALICE_WEB_DIR or use the Nix package",100
+ )101
+ .into_response()102
+}103
+104
+fn is_no_cache_path(path: &str) -> bool {105
+ matches!(path, "/" | "/index.html" | "/sw.js")106
+}107
+108
+/// index.html and sw.js must never be cached, or a stale service worker or109
+/// app shell survives a rebuild; the rest of the bundle is hashed and can be110
+/// cached freely.111
+async fn static_headers(request: axum::extract::Request, next: Next) -> Response {112
+ let no_cache = is_no_cache_path(request.uri().path());113
+ let mut response = next.run(request).await;114
+ if no_cache {115
+ let headers = response.headers_mut();116
+ headers.insert(header::CACHE_CONTROL, HeaderValue::from_static("no-cache"));117
+ headers.insert(118
+ HeaderName::from_static("service-worker-allowed"),119
+ HeaderValue::from_static("/"),120
+ );121
+ }122
+ response123
+}124
+125
+/// Serves only the built frontend: no `/api` routes, no session state, no126
+/// data dir. Used for the socket-activated on-device build.127
+pub fn static_router(web_dir: Option<String>) -> Router {128
+ let router = Router::new()129
+ .route("/api", any(api_not_found))130
+ .route("/api/{*rest}", any(api_not_found))131
+ .layer(TraceLayer::new_for_http());132
+ match web_dir {133
+ Some(dir) => {134
+ let files =135
+ ServeDir::new(&dir).not_found_service(ServeFile::new(format!("{dir}/index.html")));136
+ router137
+ .fallback_service(files)138
+ .layer(middleware::from_fn(static_headers))139
+ }140
+ None => router.fallback(missing_frontend),141
+ }142
+}@@ -0,0 +1,25 @@
1
+use malice_static::{bind_listener, serve, static_router};2
+3
+fn web_dir() -> Option<String> {4
+ let dir = std::env::var("MALICE_WEB_DIR").ok()?;5
+ assert!(6
+ std::path::Path::new(&dir).join("index.html").is_file(),7
+ "MALICE_WEB_DIR must point to built frontend assets containing index.html"8
+ );9
+ Some(dir)10
+}11
+12
+#[tokio::main]13
+async fn main() {14
+ tracing_subscriber::fmt()15
+ .with_env_filter(16
+ tracing_subscriber::EnvFilter::try_from_default_env()17
+ .unwrap_or_else(|_| "malice_static=info,tower_http=info".into()),18
+ )19
+ .with_target(false)20
+ .compact()21
+ .init();22
+23
+ let app = static_router(web_dir());24
+ serve(bind_listener().await, app, async {}).await;25
+}@@ -0,0 +1,138 @@
1
+use std::{2
+ net::TcpListener,3
+ path::PathBuf,4
+ process::{Child, Command, Stdio},5
+ time::Duration,6
+};7
+8
+use reqwest::{Client, StatusCode, header};9
+use tempfile::TempDir;10
+11
+struct Server(Child);12
+13
+impl Drop for Server {14
+ fn drop(&mut self) {15
+ let _ = self.0.kill();16
+ let _ = self.0.wait();17
+ }18
+}19
+20
+fn server_binary() -> PathBuf {21
+ option_env!("CARGO_BIN_EXE_malice-static")22
+ .map(PathBuf::from)23
+ .unwrap_or_else(|| {24
+ std::env::current_exe()25
+ .expect("integration test executable")26
+ .parent()27
+ .expect("cargo deps directory")28
+ .parent()29
+ .expect("cargo target directory")30
+ .join("malice-static")31
+ })32
+}33
+34
+fn unused_port() -> u16 {35
+ TcpListener::bind("127.0.0.1:0")36
+ .expect("bind ephemeral port")37
+ .local_addr()38
+ .expect("read ephemeral port")39
+ .port()40
+}41
+42
+async fn start(port: u16, web_dir: &TempDir, idle_secs: u64, client: &Client) -> Server {43
+ let child = Command::new(server_binary())44
+ .env("MALICE_BIND", format!("127.0.0.1:{port}"))45
+ .env("MALICE_WEB_DIR", web_dir.path())46
+ .env("MALICE_IDLE_EXIT_SECS", idle_secs.to_string())47
+ .stdout(Stdio::null())48
+ .stderr(Stdio::inherit())49
+ .spawn()50
+ .expect("start Malice backend");51
+ let mut server = Server(child);52
+ tokio::time::timeout(Duration::from_secs(30), async {53
+ loop {54
+ if let Some(status) = server.0.try_wait().expect("poll backend") {55
+ panic!("Malice exited before it started serving: {status}");56
+ }57
+ if client58
+ .get(format!("http://127.0.0.1:{port}/"))59
+ .send()60
+ .await61
+ .is_ok_and(|response| response.status().is_success())62
+ {63
+ break;64
+ }65
+ tokio::time::sleep(Duration::from_millis(100)).await;66
+ }67
+ })68
+ .await69
+ .expect("Malice did not start");70
+ server71
+}72
+73
+#[tokio::test]74
+async fn static_only_serves_the_bundle_and_exits_when_idle() {75
+ let web_dir = tempfile::tempdir().expect("temporary web dir");76
+ std::fs::write(web_dir.path().join("index.html"), "<html>malice</html>")77
+ .expect("write index.html");78
+ std::fs::write(web_dir.path().join("sw.js"), "// service worker").expect("write sw.js");79
+ std::fs::write(web_dir.path().join("style.css"), "body {}").expect("write style.css");80
+81
+ let client = Client::new();82
+ let port = unused_port();83
+ let base = format!("http://127.0.0.1:{port}");84
+ let mut server = start(port, &web_dir, 1, &client).await;85
+86
+ let index = client.get(&base).send().await.unwrap();87
+ assert_eq!(index.status(), StatusCode::OK);88
+ assert_eq!(89
+ index.headers().get(header::CACHE_CONTROL).unwrap(),90
+ "no-cache"91
+ );92
+ assert_eq!(index.headers().get("service-worker-allowed").unwrap(), "/");93
+ assert_eq!(index.text().await.unwrap(), "<html>malice</html>");94
+95
+ let sw = client.get(format!("{base}/sw.js")).send().await.unwrap();96
+ assert_eq!(sw.status(), StatusCode::OK);97
+ assert_eq!(sw.headers().get(header::CACHE_CONTROL).unwrap(), "no-cache");98
+ assert_eq!(sw.headers().get("service-worker-allowed").unwrap(), "/");99
+100
+ let asset = client101
+ .get(format!("{base}/style.css"))102
+ .send()103
+ .await104
+ .unwrap();105
+ assert_eq!(asset.status(), StatusCode::OK);106
+ assert!(asset.headers().get(header::CACHE_CONTROL).is_none());107
+108
+ assert_eq!(109
+ client110
+ .get(format!("{base}/api/rooms"))111
+ .send()112
+ .await113
+ .unwrap()114
+ .status(),115
+ StatusCode::NOT_FOUND,116
+ );117
+ assert_eq!(118
+ client119
+ .get(format!("{base}/api/"))120
+ .send()121
+ .await122
+ .unwrap()123
+ .status(),124
+ StatusCode::NOT_FOUND,125
+ );126
+127
+ let status = tokio::time::timeout(Duration::from_secs(10), async {128
+ loop {129
+ if let Some(status) = server.0.try_wait().expect("poll backend") {130
+ return status;131
+ }132
+ tokio::time::sleep(Duration::from_millis(50)).await;133
+ }134
+ })135
+ .await136
+ .expect("Malice did not exit once idle");137
+ assert!(status.success(), "idle exit should be clean: {status}");138
+}@@ -10,16 +10,36 @@
1010
};1111
1212
outputs =13
- { self, nixpkgs, fenix }:13
+ {14
+ self,15
+ nixpkgs,16
+ fenix,17
+ }:1418
let1519
systems = [1620
"x86_64-linux"1721
"aarch64-linux"1822
];1923
forAllSystems = nixpkgs.lib.genAttrs systems;24
+ cleanSrc =25
+ root:26
+ nixpkgs.lib.cleanSourceWith {27
+ src = root;28
+ filter =29
+ path: type:30
+ nixpkgs.lib.cleanSourceFilter path type31
+ && !(32
+ type == "directory"33
+ && builtins.elem (baseNameOf path) [34
+ "target"35
+ "node_modules"36
+ "dist"37
+ "dist-device"38
+ ]39
+ );40
+ };2041
workerLock = builtins.fromTOML (builtins.readFile ./crates/malice-worker/Cargo.lock);21
- lockedVersion =22
- name: (nixpkgs.lib.findFirst (p: p.name == name) null workerLock.package).version;42
+ lockedVersion = name: (nixpkgs.lib.findFirst (p: p.name == name) null workerLock.package).version;2343
# wasm-bindgen-test-runner refuses a module built by any other wasm-bindgen version2444
wasmBindgenCli =2545
pkgs:@@ -48,6 +68,42 @@
4868
toolchains.stable.rust-src4969
toolchains.targets.wasm32-unknown-unknown.stable.rust-std5070
];71
+ webNodeModules =72
+ pkgs:73
+ pkgs.importNpmLock.buildNodeModules {74
+ npmRoot = ./web;75
+ nodejs = pkgs.nodejs_22;76
+ };77
+ buildWeb =78
+ pkgs:79
+ {80
+ pname,81
+ task,82
+ outDir,83
+ postPatch ? "",84
+ }:85
+ pkgs.stdenvNoCC.mkDerivation {86
+ inherit pname postPatch;87
+ version = "0.1.0";88
+ src = cleanSrc ./web;89
+ npmDeps = webNodeModules pkgs;90
+ nativeBuildInputs = [91
+ pkgs.nodejs_2292
+ pkgs.importNpmLock.hooks.linkNodeModulesHook93
+ ];94
+ buildPhase = ''95
+ runHook preBuild96
+ export HOME=$TMPDIR97
+ npm run ${task}98
+ runHook postBuild99
+ '';100
+ installPhase = ''101
+ runHook preInstall102
+ mkdir -p $out/share/malice103
+ cp -R ${outDir}/. $out/share/malice/104
+ runHook postInstall105
+ '';106
+ };51107
in52108
{53109
packages = forAllSystems (@@ -58,31 +114,47 @@
58114
cargo = wasmToolchain system;59115
rustc = wasmToolchain system;60116
};61
- web = pkgs.buildNpmPackage {117
+ web = buildWeb pkgs {62118
pname = "malice-web";63
- version = "0.1.0";64
- src = ./web;65
- npmDepsHash = "sha256-Q00XwHH/+kfZTAPBKUlkx3hAtYvSpDw2opj22nGTIMY=";66
- installPhase = ''67
- runHook preInstall68
- mkdir -p $out/share/malice69
- cp -R dist/. $out/share/malice/70
- runHook postInstall71
- '';119
+ task = "build";120
+ outDir = "dist";72121
};73122
backend = pkgs.rustPlatform.buildRustPackage {74123
pname = "malice-server";75124
version = "0.1.0";76
- src = ./.;125
+ src = cleanSrc ./.;77126
cargoLock.lockFile = ./Cargo.lock;78127
nativeBuildInputs = [ pkgs.pkg-config ];79128
buildInputs = [ pkgs.sqlite ];129
+ cargoBuildFlags = [130
+ "-p"131
+ "malice"132
+ ];133
+ cargoTestFlags = [134
+ "-p"135
+ "malice"136
+ ];80137
# preBuild = "export NIX_BUILD_CORES=2";81138
preCheck = ''82139
cargo build --release --bin malice --target ${pkgs.stdenv.hostPlatform.rust.rustcTarget} --offline --locked83140
'';84141
SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";85142
};143
+ staticServer = pkgs.rustPlatform.buildRustPackage {144
+ pname = "malice-static";145
+ version = "0.1.0";146
+ src = cleanSrc ./.;147
+ cargoLock.lockFile = ./Cargo.lock;148
+ cargoBuildFlags = [149
+ "-p"150
+ "malice-static"151
+ ];152
+ cargoTestFlags = [153
+ "-p"154
+ "malice-static"155
+ ];156
+ meta.mainProgram = "malice-static";157
+ };86158
server = pkgs.symlinkJoin {87159
name = "malice";88160
paths = [@@ -99,10 +171,13 @@
99171
workerWasm = wasmPlatform.buildRustPackage {100172
pname = "malice-worker-wasm";101173
version = "0.1.0";102
- src = self;174
+ src = cleanSrc ./.;103175
cargoRoot = "crates/malice-worker";104176
cargoLock.lockFile = ./crates/malice-worker/Cargo.lock;105
- nativeBuildInputs = [ (wasmBindgenCli pkgs) ];177
+ nativeBuildInputs = [178
+ (wasmBindgenCli pkgs)179
+ pkgs.removeReferencesTo180
+ ];106181
buildPhase = ''107182
runHook preBuild108183
cd crates/malice-worker@@ -110,44 +185,42 @@
110185
mkdir -p $out111186
wasm-bindgen --target web --out-dir $out --out-name malice_worker \112187
target/wasm32-unknown-unknown/release/malice_worker.wasm188
+ remove-references-to -t ${wasmToolchain system} $out/*.wasm113189
runHook postBuild114190
'';115191
doCheck = false;116192
installPhase = "true";193
+ disallowedReferences = [ (wasmToolchain system) ];117194
};118
- web-device = pkgs.buildNpmPackage {195
+ web-device = buildWeb pkgs {119196
pname = "malice-web-device";120
- version = "0.1.0";121
- src = ./web;122
- npmDepsHash = "sha256-Q00XwHH/+kfZTAPBKUlkx3hAtYvSpDw2opj22nGTIMY=";197
+ task = "build:device";198
+ outDir = "dist-device";123199
postPatch = ''124200
mkdir -p src/worker/pkg125201
cp -R ${workerWasm}/. src/worker/pkg/126202
'';127
- npmBuildScript = "build:device";128
- installPhase = ''129
- runHook preInstall130
- mkdir -p $out/share/malice131
- cp -R dist-device/. $out/share/malice/132
- runHook postInstall133
- '';134203
};135204
local = pkgs.symlinkJoin {136205
name = "malice-local";137206
paths = [138
- backend207
+ staticServer139208
web-device140209
];141210
nativeBuildInputs = [ pkgs.makeWrapper ];142211
postBuild = ''143
- wrapProgram $out/bin/malice \144
- --set MALICE_WEB_DIR ${web-device}/share/malice \145
- --set MALICE_STATIC_ONLY 1212
+ wrapProgram $out/bin/malice-static \213
+ --set MALICE_WEB_DIR ${web-device}/share/malice146214
'';147215
};148216
in149217
{150
- inherit web server web-device local;218
+ inherit219
+ web220
+ server221
+ web-device222
+ local223
+ ;151224
default = server;152225
}153226
);@@ -164,16 +237,26 @@
164237
(wasmBindgenCli pkgs)165238
pkgs.rust-analyzer166239
pkgs.nodejs_22240
+ pkgs.importNpmLock.hooks.linkNodeModulesHook167241
pkgs.pkg-config168242
pkgs.sqlite169243
pkgs.firefox170244
pkgs.geckodriver245
+ pkgs.chromium171246
pkgs.matrix-continuwuity172247
pkgs.nushell173248
];249
+ CHROMIUM_PATH = nixpkgs.lib.getExe pkgs.chromium;250
+ npmDeps = webNodeModules pkgs;251
+ # the hook's own npmRoot would be a store path, so link into the checkout's web/ instead252
+ shellHook = ''253
+ npmRoot="$(git rev-parse --show-toplevel 2>/dev/null || pwd)/web" linkNodeModulesHook254
+ '';174255
# fenix's rustc links through its bundled rust-lld, which skips nix's ld-wrapper and so175256
# the store rpaths, leaving the native server unable to find libsqlite3 at run time176
- "CARGO_TARGET_${nixpkgs.lib.toUpper (builtins.replaceStrings [ "-" ] [ "_" ] pkgs.stdenv.hostPlatform.config)}_RUSTFLAGS" =257
+ "CARGO_TARGET_${258
+ nixpkgs.lib.toUpper (builtins.replaceStrings [ "-" ] [ "_" ] pkgs.stdenv.hostPlatform.config)259
+ }_RUSTFLAGS" =177260
"-C linker-features=-lld";178261
};179262
}@@ -205,7 +288,7 @@
205288
worker-browser = wasmPlatform.buildRustPackage {206289
pname = "malice-worker-browser-check";207290
version = "0.1.0";208
- src = self;291
+ src = cleanSrc ./.;209292
cargoRoot = "crates/malice-worker";210293
cargoLock.lockFile = ./crates/malice-worker/Cargo.lock;211294
nativeBuildInputs = [@@ -72,7 +72,7 @@ in
7272
package = mkOption {7373
type = types.package;7474
default = self.packages.${system}.local;75
- description = "The malice binary wrapped for the on-device build (MALICE_WEB_DIR and MALICE_STATIC_ONLY set).";75
+ description = "The malice-static binary wrapped for the on-device build (MALICE_WEB_DIR set).";7676
};7777
7878
port = mkOption {@@ -141,18 +141,17 @@ in
141141
};142142
systemd.user.services.malice = {143143
description = "Malice on-device Matrix client";144
- environment = {145
- MALICE_STATIC_ONLY = "1";146
- MALICE_IDLE_EXIT_SECS = "300";147
- };144
+ environment.MALICE_IDLE_EXIT_SECS = "300";148145
serviceConfig = {149
- ExecStart = lib.getExe' deviceCfg.package "malice";146
+ ExecStart = lib.getExe' deviceCfg.package "malice-static";150147
};151148
};152149
environment.systemPackages = [153150
malicOpen154
- malicDesktopItem155
- ];151
+ ]152
+ ++ (153
+ if ((builtins.stringLength deviceCfg.browser) != 0) then (lib.singleton malicDesktopItem) else [ ]154
+ );156155
})157156
];158157
}@@ -25,7 +25,8 @@ use tokio::sync::{broadcast, mpsc};
2525
use url::Url;2626
2727
use crate::{28
- ClientHandle, Engine, EngineConfig, EngineError, ErrorKind, EventStream, SessionStore,28
+ ClientHandle, Engine, EngineConfig, EngineError, ErrorKind, EventStream, ServerError,29
+ SessionStore,2930
engine::{Persistence, StoreLock},3031
error::SourceError,3132
};@@ -54,6 +55,8 @@ pub struct PasswordLogin {
5455
pub device_display_name: Option<String>,5556
/// set after a soft logout so the store's keys still belong to us5657
pub device_id: Option<OwnedDeviceId>,58
+ /// let plain http through, for loopback hosts only59
+ pub allow_insecure_loopback: bool,5760
}5861
5962
impl PasswordLogin {@@ -69,6 +72,7 @@ impl PasswordLogin {
6972
password: password.into(),7073
device_display_name: None,7174
device_id: None,75
+ allow_insecure_loopback: false,7276
}7377
}7478
@@ -83,6 +87,12 @@ impl PasswordLogin {
8387
self.device_id = Some(device_id);8488
self8589
}90
+91
+ #[must_use]92
+ pub fn allow_insecure_loopback(mut self, allow: bool) -> Self {93
+ self.allow_insecure_loopback = allow;94
+ self95
+ }8696
}8797
8898
#[non_exhaustive]@@ -94,6 +104,8 @@ pub struct OAuthLogin {
94104
pub client_id: Option<String>,95105
pub device_id: Option<OwnedDeviceId>,96106
pub application_type: OAuthApplicationType,107
+ /// let plain http through, for loopback hosts only108
+ pub allow_insecure_loopback: bool,97109
}98110
99111
impl OAuthLogin {@@ -112,6 +124,7 @@ impl OAuthLogin {
112124
client_id: None,113125
device_id: None,114126
application_type,127
+ allow_insecure_loopback: false,115128
}116129
}117130
@@ -133,6 +146,12 @@ impl OAuthLogin {
133146
self.device_id = Some(device_id);134147
self135148
}149
+150
+ #[must_use]151
+ pub fn allow_insecure_loopback(mut self, allow: bool) -> Self {152
+ self.allow_insecure_loopback = allow;153
+ self154
+ }136155
}137156
138157
#[derive(Clone, Copy, Debug, Eq, PartialEq)]@@ -297,6 +316,28 @@ impl SessionRecord {
297316
&self.homeserver298317
}299318
319
+ pub(crate) fn user_id(&self) -> &OwnedUserId {320
+ match &self.authentication {321
+ AuthenticationRecord::Matrix(session) => &session.meta.user_id,322
+ AuthenticationRecord::OAuth { user, .. } => &user.meta.user_id,323
+ AuthenticationRecord::SoftLoggedOut { meta, .. } => &meta.user_id,324
+ }325
+ }326
+327
+ pub(crate) fn soft_logout(&self) -> Option<SoftLogout> {328
+ let AuthenticationRecord::SoftLoggedOut { meta, client_id } = &self.authentication else {329
+ return None;330
+ };331
+ Some(SoftLogout {332
+ homeserver: self.homeserver.clone(),333
+ user_id: meta.user_id.clone(),334
+ device_id: meta.device_id.clone(),335
+ client_id: client_id336
+ .as_ref()337
+ .map(|client_id| client_id.as_str().to_owned()),338
+ })339
+ }340
+300341
pub(crate) fn soft_logged_out(self) -> Self {301342
let authentication = match self.authentication {302343
AuthenticationRecord::Matrix(session) => AuthenticationRecord::SoftLoggedOut {@@ -340,6 +381,28 @@ impl SoftLogout {
340381
pub fn password_login(&self, password: impl Into<String>) -> PasswordLogin {341382
PasswordLogin::new(self.homeserver.clone(), self.user_id.as_str(), password)342383
.with_device_id(self.device_id.clone())384
+ .allow_insecure_loopback(true)385
+ }386
+387
+ #[must_use]388
+ pub fn oauth_login(389
+ &self,390
+ redirect_uri: impl Into<String>,391
+ client_uri: impl Into<String>,392
+ application_type: OAuthApplicationType,393
+ ) -> OAuthLogin {394
+ let login = OAuthLogin::new(395
+ self.homeserver.clone(),396
+ redirect_uri,397
+ client_uri,398
+ application_type,399
+ )400
+ .with_device_id(self.device_id.clone())401
+ .allow_insecure_loopback(true);402
+ match &self.client_id {403
+ Some(client_id) => login.with_client_id(client_id.clone()),404
+ None => login,405
+ }343406
}344407
}345408
@@ -348,6 +411,8 @@ pub enum AccountError {
348411
#[error("{context} failed")]349412
Operation {350413
context: &'static str,414
+ kind: ErrorKind,415
+ server: Option<ServerError>,351416
#[source]352417
source: Box<SourceError>,353418
},@@ -357,6 +422,12 @@ pub enum AccountError {
357422
UnsupportedAuthentication,358423
#[error("the OAuth callback was already submitted")]359424
OAuthCallbackAlreadySubmitted,425
+ /// what was typed can't name a homeserver, so nothing was sent anywhere426
+ #[error("that isn't a usable homeserver, {0}")]427
+ InvalidHomeserver(&'static str),428
+ /// `Accounts` already has a live login for them. a second would be another device429
+ #[error("{0} is already logged in")]430
+ AlreadyLoggedIn(OwnedUserId),360431
/// an IndexedDB delete is waiting on the store's other connections. it goes through361432
/// once they close, and opening the store again waits behind it362433
#[error("the store is still open elsewhere, it will be deleted once that closes")]@@ -376,6 +447,18 @@ pub enum AccountError {
376447
Engine(#[from] EngineError),377448
}378449
450
+impl AccountError {451
+ /// what the homeserver said, when it refused452
+ #[must_use]453
+ pub fn server(&self) -> Option<&ServerError> {454
+ match self {455
+ Self::Operation { server, .. } => server.as_ref(),456
+ Self::Unsaved { source, .. } => source.server(),457
+ _ => None,458
+ }459
+ }460
+}461
+379462
/// a live login whose record never reached its `SessionStore`380463
pub struct UnsavedSession {381464
session: Session,@@ -416,9 +499,19 @@ impl Session {
416499
login: PasswordLogin,417500
sessions: Arc<dyn SessionStore>,418501
) -> Result<Self, AccountError> {502
+ homeserver_input(&login.homeserver, login.allow_insecure_loopback)?;419503
let store_lock = sessions.store().lock().await?;504
+ Self::login_password_locked(login, sessions, store_lock).await505
+ }506
+507
+ pub(crate) async fn login_password_locked(508
+ login: PasswordLogin,509
+ sessions: Arc<dyn SessionStore>,510
+ store_lock: StoreLock,511
+ ) -> Result<Self, AccountError> {512
+ let homeserver = homeserver_input(&login.homeserver, login.allow_insecure_loopback)?;420513
let client = matrix_client_builder(sessions.store())421
- .server_name_or_homeserver_url(login.homeserver.trim())514
+ .server_name_or_homeserver_url(homeserver)422515
.build()423516
.await424517
.map_err(|error| account_error("building the Matrix client", error))?;@@ -445,13 +538,23 @@ impl Session {
445538
login: OAuthLogin,446539
sessions: Arc<dyn SessionStore>,447540
) -> Result<PendingOAuthLogin, AccountError> {541
+ homeserver_input(&login.homeserver, login.allow_insecure_loopback)?;542
+ let store_lock = sessions.store().lock().await?;543
+ Self::begin_oauth_locked(login, sessions, store_lock).await544
+ }545
+546
+ pub(crate) async fn begin_oauth_locked(547
+ login: OAuthLogin,548
+ sessions: Arc<dyn SessionStore>,549
+ store_lock: StoreLock,550
+ ) -> Result<PendingOAuthLogin, AccountError> {448551
let redirect_uri = Url::parse(login.redirect_uri.trim())449552
.map_err(|error| account_error("parsing the OAuth redirect URI", error))?;450553
let client_uri = Url::parse(login.client_uri.trim())451554
.map_err(|error| account_error("parsing the OAuth client URI", error))?;452
- let store_lock = sessions.store().lock().await?;555
+ let homeserver = homeserver_input(&login.homeserver, login.allow_insecure_loopback)?;453556
let client = matrix_client_builder(sessions.store())454
- .server_name_or_homeserver_url(login.homeserver.trim())557
+ .server_name_or_homeserver_url(homeserver)455558
.build()456559
.await457560
.map_err(|error| account_error("building the Matrix client", error))?;@@ -678,12 +781,54 @@ fn matrix_client_builder(store: &StoreConfig) -> ClientBuilder {
678781
}679782
}680783
784
+/// a bare server name goes through untouched, since that's what makes the sdk try `.well-known`785
+pub(crate) fn homeserver_input(786
+ input: &str,787
+ allow_insecure_loopback: bool,788
+) -> Result<&str, AccountError> {789
+ let input = input.trim();790
+ let invalid = |reason| Err(AccountError::InvalidHomeserver(reason));791
+ if input.is_empty() {792
+ return invalid("it's empty");793
+ }794
+ if input.contains(char::is_whitespace) {795
+ return invalid("it has spaces in it");796
+ }797
+ if !input.contains("://") {798
+ return match <&ruma::ServerName>::try_from(input) {799
+ Ok(_) => Ok(input),800
+ Err(_) => invalid("it's neither a server name nor a url"),801
+ };802
+ }803
+ let Ok(url) = Url::parse(input) else {804
+ return invalid("it isn't a valid url");805
+ };806
+ if !url.username().is_empty() || url.password().is_some() {807
+ return invalid("it has a username in it");808
+ }809
+ let loopback = match url.host() {810
+ None => return invalid("it has no host"),811
+ Some(url::Host::Domain(domain)) => domain.eq_ignore_ascii_case("localhost"),812
+ Some(url::Host::Ipv4(address)) => address.is_loopback(),813
+ Some(url::Host::Ipv6(address)) => address.is_loopback(),814
+ };815
+ match url.scheme() {816
+ "https" => Ok(input),817
+ "http" if allow_insecure_loopback && loopback => Ok(input),818
+ "http" if allow_insecure_loopback => invalid("plain http only reaches loopback hosts"),819
+ "http" => invalid("it isn't https"),820
+ _ => invalid("only http and https are spoken"),821
+ }822
+}823
+681824
pub(crate) fn account_error(682825
context: &'static str,683826
source: impl std::error::Error + SendOutsideWasm + SyncOutsideWasm + 'static,684827
) -> AccountError {685828
AccountError::Operation {686829
context,830
+ kind: crate::error::classify(&source),831
+ server: ServerError::find(&source),687832
source: Box::new(source),688833
}689834
}@@ -0,0 +1,407 @@
1
+use std::sync::Arc;2
+#[cfg(feature = "sqlite")]3
+use std::{collections::BTreeSet, path::PathBuf};4
+5
+use ruma::TransactionId;6
+7
+use crate::{8
+ AccountError, EncryptedSessionStore, OAuthLogin, PasswordLogin, PendingOAuthLogin, Restore,9
+ Session, SessionRecord, SessionStore, SoftLogout, StoreConfig, account::homeserver_input,10
+ engine::StoreLock,11
+};12
+13
+/// every account one owner has, a store each under one root and one passphrase. whoever holds14
+/// the set can resume any soft-logged-out device in it with just its password, and the device's15
+/// store has its e2ee keys, so a set belongs to one person and never to a whole machine16
+pub struct Accounts {17
+ root: Root,18
+ passphrase: String,19
+}20
+21
+enum Root {22
+ #[cfg(feature = "sqlite")]23
+ Directory(PathBuf),24
+ #[cfg(feature = "indexeddb")]25
+ Prefix(String),26
+}27
+28
+/// one account's record and store29
+#[derive(Clone)]30
+pub struct Account {31
+ id: String,32
+ sessions: Arc<EncryptedSessionStore>,33
+}34
+35
+impl Account {36
+ /// stable for the account's life, and safe in a cookie or a url37
+ #[must_use]38
+ pub fn id(&self) -> &str {39
+ &self.id40
+ }41
+42
+ /// for `Termination::retain`. a discarded account drops out of `Accounts::list`43
+ #[must_use]44
+ pub fn sessions(&self) -> Arc<dyn SessionStore> {45
+ self.sessions.clone()46
+ }47
+48
+ pub async fn restore(&self) -> Result<Option<Restore>, AccountError> {49
+ Session::restore(self.sessions()).await50
+ }51
+}52
+53
+impl std::fmt::Debug for Account {54
+ fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {55
+ formatter56
+ .debug_struct("Account")57
+ .field("id", &self.id)58
+ .finish_non_exhaustive()59
+ }60
+}61
+62
+enum Found {63
+ Nobody,64
+ SoftLoggedOut(Account, SoftLogout),65
+}66
+67
+impl Accounts {68
+ /// each account is a store directory under `root` with its record beside it69
+ #[cfg(feature = "sqlite")]70
+ #[must_use]71
+ pub fn sqlite(root: impl Into<PathBuf>, passphrase: impl Into<String>) -> Self {72
+ Self {73
+ root: Root::Directory(root.into()),74
+ passphrase: passphrase.into(),75
+ }76
+ }77
+78
+ /// each account is a store named `<prefix>::<id>`, listed in `<prefix>::macltok-accounts`79
+ #[cfg(feature = "indexeddb")]80
+ #[must_use]81
+ pub fn indexeddb(prefix: impl Into<String>, passphrase: impl Into<String>) -> Self {82
+ Self {83
+ root: Root::Prefix(prefix.into()),84
+ passphrase: passphrase.into(),85
+ }86
+ }87
+88
+ /// `None` for anything `Account::id` couldn't have been89
+ #[must_use]90
+ pub fn account(&self, id: &str) -> Option<Account> {91
+ let valid =92
+ !id.is_empty() && id.len() <= 64 && id.bytes().all(|b| b.is_ascii_alphanumeric());93
+ valid.then(|| self.open(id.to_owned()))94
+ }95
+96
+ /// every account with a record. a store left without one, by a login that died halfway or a97
+ /// discard that couldn't finish, is deleted on the way past98
+ pub async fn list(&self) -> Result<Vec<Account>, AccountError> {99
+ let mut accounts = Vec::new();100
+ for account in self.slots().await? {101
+ match account.sessions.load().await {102
+ Ok(None) => self.sweep(&account).await,103
+ Ok(Some(_)) | Err(_) => accounts.push(account),104
+ }105
+ }106
+ Ok(accounts)107
+ }108
+109
+ /// a soft-logged-out account the login names is resumed as its own device, keeping its keys.110
+ /// anyone else gets a new account111
+ pub async fn login_password(112
+ &self,113
+ login: PasswordLogin,114
+ ) -> Result<(Account, Session), AccountError> {115
+ homeserver_input(&login.homeserver, login.allow_insecure_loopback)?;116
+ let found = self117
+ .find(|record| record_names(record, &login.homeserver, &login.username))118
+ .await?;119
+ match found {120
+ Found::SoftLoggedOut(account, soft) => {121
+ let store_lock = account.sessions.store().lock().await?;122
+ let login = PasswordLogin {123
+ device_display_name: login.device_display_name,124
+ ..soft.password_login(login.password)125
+ };126
+ let session =127
+ Session::login_password_locked(login, account.sessions(), store_lock).await?;128
+ Ok((account, session))129
+ }130
+ Found::Nobody => {131
+ let (account, store_lock) = self.fresh().await?;132
+ let login = PasswordLogin {133
+ device_id: None,134
+ ..login135
+ };136
+ match Session::login_password_locked(login, account.sessions(), store_lock).await {137
+ Ok(session) => Ok((account, session)),138
+ Err(error) => Err(self.abandon(&account, error).await),139
+ }140
+ }141
+ }142
+ }143
+144
+ /// resumes the soft-logged-out account whose device `login` names, as145
+ /// `SoftLogout::oauth_login` sets it. without one it's a new account, since which account an146
+ /// OAuth login is for isn't known until it finishes147
+ pub async fn begin_oauth(148
+ &self,149
+ login: OAuthLogin,150
+ ) -> Result<(Account, PendingOAuthLogin), AccountError> {151
+ homeserver_input(&login.homeserver, login.allow_insecure_loopback)?;152
+ let device_id = login.device_id.clone();153
+ let found = self154
+ .find(|record| {155
+ record156
+ .soft_logout()157
+ .is_some_and(|soft| device_id.as_ref() == Some(&soft.device_id))158
+ })159
+ .await?;160
+ match found {161
+ Found::SoftLoggedOut(account, soft) => {162
+ let store_lock = account.sessions.store().lock().await?;163
+ let login = OAuthLogin {164
+ homeserver: soft.homeserver,165
+ client_id: login.client_id.or(soft.client_id),166
+ allow_insecure_loopback: true,167
+ ..login168
+ };169
+ let pending =170
+ Session::begin_oauth_locked(login, account.sessions(), store_lock).await?;171
+ Ok((account, pending))172
+ }173
+ Found::Nobody => {174
+ let (account, store_lock) = self.fresh().await?;175
+ let login = OAuthLogin {176
+ device_id: None,177
+ ..login178
+ };179
+ match Session::begin_oauth_locked(login, account.sessions(), store_lock).await {180
+ Ok(pending) => Ok((account, pending)),181
+ Err(error) => Err(self.abandon(&account, error).await),182
+ }183
+ }184
+ }185
+ }186
+187
+ /// a live login for the same person is refused rather than given a second device188
+ async fn find(&self, resumes: impl Fn(&SessionRecord) -> bool) -> Result<Found, AccountError> {189
+ for account in self.slots().await? {190
+ let Ok(Some(record)) = account.sessions.load().await else {191
+ continue;192
+ };193
+ if !resumes(&record) {194
+ continue;195
+ }196
+ return match record.soft_logout() {197
+ Some(soft) => Ok(Found::SoftLoggedOut(account, soft)),198
+ None => Err(AccountError::AlreadyLoggedIn(record.user_id().clone())),199
+ };200
+ }201
+ Ok(Found::Nobody)202
+ }203
+204
+ /// locked before anything else can see it, so `list` never sweeps a login still under way205
+ async fn fresh(&self) -> Result<(Account, StoreLock), AccountError> {206
+ let account = self.open(TransactionId::new().to_string());207
+ let store_lock = account.sessions.store().lock().await?;208
+ #[cfg(feature = "indexeddb")]209
+ {210
+ let Root::Prefix(prefix) = &self.root;211
+ index::add(prefix, &account.id).await?;212
+ }213
+ Ok((account, store_lock))214
+ }215
+216
+ /// a failed first login leaves nothing behind. one whose record didn't save has a live device217
+ /// on the server, so that stays for `UnsavedSession::save`218
+ async fn abandon(&self, account: &Account, error: AccountError) -> AccountError {219
+ if !matches!(error, AccountError::Unsaved { .. }) {220
+ self.sweep(account).await;221
+ }222
+ error223
+ }224
+225
+ /// best effort, since whatever it leaves is found and swept again by the next `list`226
+ async fn sweep(&self, account: &Account) {227
+ let Ok(_store_lock) = account.sessions.store().lock().await else {228
+ return;229
+ };230
+ if !matches!(account.sessions.load().await, Ok(None)) {231
+ return;232
+ }233
+ if account.sessions.discard().await.is_err() {234
+ return;235
+ }236
+ #[cfg(feature = "indexeddb")]237
+ {238
+ let Root::Prefix(prefix) = &self.root;239
+ let _ = index::remove(prefix, &account.id).await;240
+ }241
+ }242
+243
+ fn open(&self, id: String) -> Account {244
+ let sessions = match &self.root {245
+ #[cfg(feature = "sqlite")]246
+ Root::Directory(root) => EncryptedSessionStore::file(247
+ root.join(format!("{id}.session")),248
+ StoreConfig::sqlite(root.join(&id), self.passphrase.clone()),249
+ ),250
+ #[cfg(feature = "indexeddb")]251
+ Root::Prefix(prefix) => EncryptedSessionStore::indexeddb(StoreConfig::indexeddb(252
+ format!("{prefix}::{id}"),253
+ self.passphrase.clone(),254
+ )),255
+ };256
+ Account {257
+ id,258
+ sessions: Arc::new(sessions),259
+ }260
+ }261
+262
+ async fn slots(&self) -> Result<Vec<Account>, AccountError> {263
+ let ids = match &self.root {264
+ #[cfg(feature = "sqlite")]265
+ Root::Directory(root) => directory_slots(root)?,266
+ #[cfg(feature = "indexeddb")]267
+ Root::Prefix(prefix) => index::list(prefix).await?,268
+ };269
+ Ok(ids.iter().filter_map(|id| self.account(id)).collect())270
+ }271
+}272
+273
+/// a localpart or a full user id names the same account, but only on the same server. the server274
+/// is compared by name as well as by url, so a delegated `example.org` still finds the account275
+/// discovery took to `matrix.example.org`276
+fn record_names(record: &SessionRecord, homeserver: &str, username: &str) -> bool {277
+ let user_id = record.user_id();278
+ let username = username.trim();279
+ let user = if username.starts_with('@') {280
+ username.eq_ignore_ascii_case(user_id.as_str())281
+ } else {282
+ username.eq_ignore_ascii_case(user_id.localpart())283
+ };284
+ let typed = authority(homeserver);285
+ user && (typed.eq_ignore_ascii_case(user_id.server_name().as_str())286
+ || typed.eq_ignore_ascii_case(authority(record.homeserver())))287
+}288
+289
+fn authority(homeserver: &str) -> &str {290
+ let homeserver = homeserver.trim();291
+ let rest = homeserver292
+ .split_once("://")293
+ .map_or(homeserver, |(_, rest)| rest);294
+ rest.split('/').next().unwrap_or(rest)295
+}296
+297
+#[cfg(feature = "sqlite")]298
+fn directory_slots(root: &std::path::Path) -> Result<BTreeSet<String>, AccountError> {299
+ use std::io::ErrorKind;300
+301
+ let entries = match std::fs::read_dir(root) {302
+ Ok(entries) => entries,303
+ Err(error) if error.kind() == ErrorKind::NotFound => return Ok(BTreeSet::new()),304
+ Err(error) => return Err(crate::account::account_error("listing the accounts", error)),305
+ };306
+ let mut ids = BTreeSet::new();307
+ for entry in entries {308
+ let entry =309
+ entry.map_err(|error| crate::account::account_error("listing the accounts", error))?;310
+ let name = entry.file_name();311
+ let Some(name) = name.to_str() else {312
+ continue;313
+ };314
+ if entry.path().is_dir() {315
+ ids.insert(name.to_owned());316
+ } else if let Some(id) = name.strip_suffix(".session") {317
+ ids.insert(id.to_owned());318
+ }319
+ }320
+ Ok(ids)321
+}322
+323
+/// a key per account, so two tabs adding at once can't lose one to the other324
+#[cfg(feature = "indexeddb")]325
+mod index {326
+ use std::collections::BTreeSet;327
+328
+ use indexed_db_futures::{329
+ Build,330
+ database::Database,331
+ error::{Error, OpenDbError},332
+ prelude::*,333
+ transaction::{Transaction, TransactionMode},334
+ };335
+336
+ use crate::{AccountError, account::account_error};337
+338
+ const ACCOUNTS: &str = "accounts";339
+340
+ fn name(prefix: &str) -> String {341
+ format!("{prefix}::macltok-accounts")342
+ }343
+344
+ async fn open(prefix: &str) -> Result<Database, OpenDbError> {345
+ Database::open(&name(prefix))346
+ .with_version(1u32)347
+ .with_on_upgrade_needed(|_, transaction: &Transaction<'_>| -> Result<(), Error> {348
+ transaction.db().create_object_store(ACCOUNTS).build()?;349
+ Ok(())350
+ })351
+ .build()?352
+ .await353
+ }354
+355
+ pub(super) async fn list(prefix: &str) -> Result<BTreeSet<String>, AccountError> {356
+ let failed = |error| account_error("listing the accounts", error);357
+ let database = open(prefix).await.map_err(failed)?;358
+ let ids = keys(&database).await;359
+ database.close();360
+ ids.map_err(|error| account_error("listing the accounts", error))361
+ }362
+363
+ pub(super) async fn add(prefix: &str, id: &str) -> Result<(), AccountError> {364
+ let failed = |error| account_error("adding the account", error);365
+ let database = open(prefix).await.map_err(failed)?;366
+ let added = write(&database, |store| {367
+ store.put(true).with_key(id).build()?;368
+ Ok(())369
+ })370
+ .await;371
+ database.close();372
+ added.map_err(|error| account_error("adding the account", error))373
+ }374
+375
+ pub(super) async fn remove(prefix: &str, id: &str) -> Result<(), AccountError> {376
+ let failed = |error| account_error("removing the account", error);377
+ let database = open(prefix).await.map_err(failed)?;378
+ let removed = write(&database, |store| {379
+ store.delete(id).build()?;380
+ Ok(())381
+ })382
+ .await;383
+ database.close();384
+ removed.map_err(|error| account_error("removing the account", error))385
+ }386
+387
+ async fn keys(database: &Database) -> Result<BTreeSet<String>, Error> {388
+ let transaction = database389
+ .transaction(ACCOUNTS)390
+ .with_mode(TransactionMode::Readonly)391
+ .build()?;392
+ let store = transaction.object_store(ACCOUNTS)?;393
+ store.get_all_keys::<String>().await?.collect()394
+ }395
+396
+ async fn write(397
+ database: &Database,398
+ change: impl FnOnce(&indexed_db_futures::object_store::ObjectStore<'_>) -> Result<(), Error>,399
+ ) -> Result<(), Error> {400
+ let transaction = database401
+ .transaction(ACCOUNTS)402
+ .with_mode(TransactionMode::Readwrite)403
+ .build()?;404
+ change(&transaction.object_store(ACCOUNTS)?)?;405
+ transaction.commit().await406
+ }407
+}@@ -35,7 +35,7 @@ use super::executor::EngineBoxFuture;
3535
use crate::{3636
AttachmentEncryption, AttachmentUpload, Error, ErrorKind, Media, MediaFile, MediaId, MediaKind,3737
MediaLocation, MediaSize, TimelineId,38
- normalise::{MediaRegistration, MediaScope},38
+ normalise::{MediaRegistration, MediaScope, MediaSourceInfo},3939
upload::prepare_upload,4040
};4141
@@ -137,6 +137,9 @@ impl MediaService {
137137
}138138
139139
async fn registered(&self, media_id: &MediaId) -> Result<MediaRegistration, Error> {140
+ if let Some(uri) = media_id.as_plain() {141
+ return plain_registration(media_id, uri);142
+ }140143
self.registry141144
.lock()142145
.await@@ -150,24 +153,6 @@ impl MediaService {
150153
})151154
}152155
153
- pub(crate) async fn mxc_media(&self, uri: &MxcUri, size: MediaSize) -> Result<Media, Error> {154
- if !uri.is_valid() {155
- return Err(Error::new(ErrorKind::Invalid, "mxc uri is malformed"));156
- }157
- let format = match size {158
- MediaSize::Full => MediaFormat::File,159
- MediaSize::Thumbnail { width, height } => thumbnail_format(width, height),160
- };161
- self.fetch_or_file(162
- MediaRequestParameters {163
- source: MediaSource::Plain(uri.to_owned()),164
- format,165
- },166
- None,167
- )168
- .await169
- }170
-171156
/// plenty of servers won't thumbnail everything, and the file itself is the next best172157
/// thing. the byte cap still holds either way173158
async fn fetch_or_file(@@ -233,6 +218,22 @@ struct ChosenSource {
233218
declared_size: Option<u64>,234219
}235220
221
+fn plain_registration(media_id: &MediaId, uri: &MxcUri) -> Result<MediaRegistration, Error> {222
+ if !uri.is_valid() {223
+ return Err(Error::new(ErrorKind::Invalid, "mxc uri is malformed"));224
+ }225
+ Ok(MediaRegistration {226
+ id: media_id.clone(),227
+ kind: MediaKind::Image,228
+ full: MediaSourceInfo {229
+ source: MediaSource::Plain(uri.to_owned()),230
+ mimetype: None,231
+ declared_size: None,232
+ },233
+ thumbnail: None,234
+ })235
+}236
+236237
fn choose_source(media: MediaRegistration, size: MediaSize) -> Result<ChosenSource, Error> {237238
let (source, format, mimetype, declared_size) = match size {238239
MediaSize::Full => (@@ -33,6 +33,8 @@ pub struct Error {
3333
pub message: String,3434
/// set when the server wants interactive auth before it'll do the thing3535
pub challenge: Option<Box<InteractiveAuthChallenge>>,36
+ /// set when the homeserver refused with a matrix error37
+ pub server: Option<ServerError>,3638
#[source]3739
#[cfg_attr(feature = "serde", serde(skip))]3840
source: Option<Arc<SourceError>>,@@ -68,12 +70,76 @@ pub enum ErrorKind {
6870
Other,6971
}7072
73
+/// the homeserver's own answer, worth showing a person as it stands74
+#[derive(Clone, Debug, Eq, PartialEq)]75
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]76
+#[non_exhaustive]77
+pub struct ServerError {78
+ pub status: u16,79
+ pub errcode: String,80
+ pub message: String,81
+}82
+83
+impl ServerError {84
+ pub(crate) fn find(source: &(dyn std::error::Error + 'static)) -> Option<Self> {85
+ let mut current = Some(source);86
+ while let Some(error) = current {87
+ let api = if let Some(error) = error.downcast_ref::<matrix_sdk::Error>() {88
+ error.as_client_api_error()89
+ } else if let Some(error) = error.downcast_ref::<HttpError>() {90
+ error.as_client_api_error()91
+ } else {92
+ error.downcast_ref::<ruma::api::error::Error>()93
+ };94
+ if let Some(api) = api95
+ && let ruma::api::error::ErrorBody::Standard(body) = &api.body96
+ {97
+ return Some(Self {98
+ status: api.status_code.as_u16(),99
+ errcode: body.kind.errcode().to_string(),100
+ message: body.message.clone(),101
+ });102
+ }103
+ current = error.source();104
+ }105
+ None106
+ }107
+}108
+109
+impl std::fmt::Display for ServerError {110
+ fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {111
+ write!(formatter, "{} ({})", self.message, self.errcode)112
+ }113
+}114
+115
+#[cfg(any(feature = "sqlite", feature = "indexeddb"))]116
+pub(crate) fn classify(source: &(dyn std::error::Error + 'static)) -> ErrorKind {117
+ let mut current = Some(source);118
+ while let Some(error) = current {119
+ if let Some(error) = error.downcast_ref::<matrix_sdk::Error>() {120
+ return classify_sdk_error(error);121
+ }122
+ if let Some(error) = error.downcast_ref::<HttpError>() {123
+ return classify_http_error(error);124
+ }125
+ if let Some(error) = error.downcast_ref::<OAuthError>() {126
+ return classify_oauth_error(error);127
+ }128
+ if let Some(error) = error.downcast_ref::<RefreshTokenError>() {129
+ return classify_refresh_token_error(error);130
+ }131
+ current = error.source();132
+ }133
+ ErrorKind::Other134
+}135
+71136
impl Error {72137
pub(crate) fn new(kind: ErrorKind, message: impl Into<String>) -> Self {73138
Self {74139
kind,75140
message: message.into(),76141
challenge: None,142
+ server: None,77143
source: None,78144
}79145
}@@ -84,6 +150,7 @@ impl Error {
84150
source: impl std::error::Error + SendOutsideWasm + SyncOutsideWasm + 'static,85151
) -> Self {86152
Self {153
+ server: ServerError::find(&source),87154
source: Some(Arc::new(source)),88155
..Self::new(kind, message)89156
}@@ -174,6 +241,7 @@ impl PartialEq for Error {
174241
self.kind == other.kind175242
&& self.message == other.message176243
&& self.challenge == other.challenge244
+ && self.server == other.server177245
}178246
}179247
@@ -21,6 +21,8 @@ compile_error!("indexeddb only exists in a browser, use sqlite");
2121
#[cfg(any(feature = "sqlite", feature = "indexeddb"))]2222
mod account;2323
#[cfg(any(feature = "sqlite", feature = "indexeddb"))]24
+mod accounts;25
+#[cfg(any(feature = "sqlite", feature = "indexeddb"))]2426
mod session_store;2527
#[cfg(any(feature = "sqlite", feature = "indexeddb"))]2628
mod store_lock;@@ -31,10 +33,12 @@ pub use account::{
3133
Session, SessionRecord, SoftLogout, StoreConfig, UnsavedSession,3234
};3335
#[cfg(any(feature = "sqlite", feature = "indexeddb"))]36
+pub use accounts::{Account, Accounts};37
+#[cfg(any(feature = "sqlite", feature = "indexeddb"))]3438
pub use session_store::{EncryptedSessionStore, SessionStore};3539
3640
pub use engine::{Engine, EngineConfig, EngineError};37
-pub use error::{Error, ErrorKind};41
+pub use error::{Error, ErrorKind, ServerError};3842
pub use imbl;3943
#[cfg(feature = "mirror")]4044
pub use mirror::{@@ -58,6 +62,7 @@ pub use model::{
5862
UploadOutcome, UploadThumbnail, UtdCause, VerificationAction, VerificationFailure,5963
VerificationState, VerificationTarget,6064
};65
+pub use ruma;6166
pub use transport::{ClientHandle, EventStream, Pending, SpaceHierarchy};6267
pub use uiaa::{6368
InteractiveAuth, InteractiveAuthChallenge, InteractiveAuthFailure, InteractiveAuthFlow,@@ -2,8 +2,8 @@ use std::{fmt, sync::Arc};
22
33
use imbl::Vector;44
use ruma::{5
- OwnedDeviceId, OwnedEventId, OwnedMxcUri, OwnedRoomAliasId, OwnedRoomId, OwnedRoomOrAliasId,6
- OwnedServerName, OwnedTransactionId, OwnedUserId,5
+ MxcUri, OwnedDeviceId, OwnedEventId, OwnedMxcUri, OwnedRoomAliasId, OwnedRoomId,6
+ OwnedRoomOrAliasId, OwnedServerName, OwnedTransactionId, OwnedUserId,77
events::{88
AnyGlobalAccountDataEventContent, AnyRoomAccountDataEventContent, AnySyncTimelineEvent,99
GlobalAccountDataEventType, RoomAccountDataEventType,@@ -786,7 +786,7 @@ pub struct RoomSummary {
786786
pub direct: bool,787787
pub favourite: bool,788788
pub low_priority: bool,789
- pub avatar: Option<OwnedMxcUri>,789
+ pub avatar: Option<MediaId>,790790
pub latest_event_timestamp_ms: Option<u64>,791791
pub latest_event: Option<LatestEvent>,792792
pub notification_mode: Option<RoomNotificationMode>,@@ -812,7 +812,7 @@ pub struct RoomSummary {
812812
pub struct RoomHero {813813
pub user_id: OwnedUserId,814814
pub display_name: Option<String>,815
- pub avatar: Option<OwnedMxcUri>,815
+ pub avatar: Option<MediaId>,816816
}817817
818818
/// enough for a room list preview line. `kind` and `body` are only set for messages,@@ -834,7 +834,7 @@ pub struct LatestEvent {
834834
pub struct Profile {835835
pub user_id: OwnedUserId,836836
pub display_name: Option<String>,837
- pub avatar: Option<OwnedMxcUri>,837
+ pub avatar: Option<MediaId>,838838
}839839
840840
/// one room in a space's hierarchy, as the server describes it, which may be a room you're not in@@ -845,7 +845,7 @@ pub struct SpaceChild {
845845
pub room_id: OwnedRoomId,846846
pub name: String,847847
pub topic: Option<String>,848
- pub avatar: Option<OwnedMxcUri>,848
+ pub avatar: Option<MediaId>,849849
pub canonical_alias: Option<OwnedRoomAliasId>,850850
pub joined_members: u64,851851
pub space: bool,@@ -903,7 +903,7 @@ pub struct PushNotification {
903903
pub struct PushNotificationSender {904904
pub user_id: OwnedUserId,905905
pub display_name: Option<String>,906
- pub avatar_url: Option<OwnedMxcUri>,906
+ pub avatar_url: Option<MediaId>,907907
pub name_ambiguous: bool,908908
}909909
@@ -913,7 +913,7 @@ pub struct PushNotificationSender {
913913
pub struct PushNotificationRoom {914914
pub room_id: OwnedRoomId,915915
pub name: String,916
- pub avatar_url: Option<OwnedMxcUri>,916
+ pub avatar_url: Option<MediaId>,917917
pub canonical_alias: Option<OwnedRoomAliasId>,918918
pub topic: Option<String>,919919
pub encrypted: Option<bool>,@@ -1107,7 +1107,7 @@ pub struct MemberSummary {
11071107
pub user_id: OwnedUserId,11081108
pub name: String,11091109
pub display_name: Option<String>,1110
- pub avatar: Option<OwnedMxcUri>,1110
+ pub avatar: Option<MediaId>,11111111
pub membership: MemberMembership,11121112
pub own: bool,11131113
pub name_ambiguous: bool,@@ -1422,7 +1422,7 @@ impl From<OwnedEventId> for EventRef {
14221422
pub struct Sender {14231423
pub user_id: OwnedUserId,14241424
pub display_name: Option<String>,1425
- pub avatar: Option<OwnedMxcUri>,1425
+ pub avatar: Option<MediaId>,14261426
/// someone else in the room goes by the same name, so show the user id too14271427
pub name_ambiguous: bool,14281428
}@@ -1458,12 +1458,12 @@ pub enum TimelineContent {
14581458
Profile {14591459
user_id: OwnedUserId,14601460
display_name: Option<Change<Option<String>>>,1461
- avatar: Option<Change<Option<OwnedMxcUri>>>,1461
+ avatar: Option<Change<Option<MediaId>>>,14621462
},14631463
/// `None` means it was cleared, or the event was redacted14641464
RoomName(Option<String>),14651465
RoomTopic(Option<String>),1466
- RoomAvatar(Option<OwnedMxcUri>),1466
+ RoomAvatar(Option<MediaId>),14671467
EncryptionEnabled,14681468
RoomCreated,14691469
RoomUpgraded {@@ -1635,6 +1635,15 @@ impl MediaId {
16351635
Self(value)16361636
}16371637
1638
+ /// plain media carries no keys, so it needs no registering and never expires1639
+ pub(crate) fn plain<U: AsRef<str> + ?Sized>(uri: &U) -> Self {1640
+ Self(uri.as_ref().to_owned())1641
+ }1642
+1643
+ pub(crate) fn as_plain(&self) -> Option<&MxcUri> {1644
+ self.0.starts_with("mxc://").then(|| self.0.as_str().into())1645
+ }1646
+16381647
#[must_use]16391648
pub fn as_str(&self) -> &str {16401649
&self.0@@ -1,14 +1,14 @@
11
use matrix_sdk::room::RoomMember;22
use ruma::events::room::member::MembershipState;33
4
-use crate::{MemberMembership, MemberSummary};4
+use crate::{MediaId, MemberMembership, MemberSummary};55
66
pub(crate) fn member_summary(member: RoomMember) -> MemberSummary {77
MemberSummary {88
user_id: member.user_id().to_owned(),99
name: member.name().to_owned(),1010
display_name: member.display_name().map(ToOwned::to_owned),11
- avatar: member.avatar_url().map(ToOwned::to_owned),11
+ avatar: member.avatar_url().map(MediaId::plain),1212
membership: match member.membership() {1313
MembershipState::Join => MemberMembership::Joined,1414
MembershipState::Invite => MemberMembership::Invited,@@ -3,7 +3,7 @@ mod member;
33
mod room;44
mod timeline;55
6
-pub(crate) use media::{MediaRegistration, MediaScope};6
+pub(crate) use media::{MediaRegistration, MediaScope, MediaSourceInfo};77
pub(crate) use member::member_summary;88
pub(crate) use room::notification_mode;99
pub(crate) use room::{room_summaries, space_child};@@ -14,7 +14,7 @@ use ruma::OwnedRoomId;
1414
1515
use super::message_kind;1616
use crate::{17
- LatestEvent, MessageKind, RoomHero, RoomMembership, RoomNotificationMode, RoomSummary,17
+ LatestEvent, MediaId, MessageKind, RoomHero, RoomMembership, RoomNotificationMode, RoomSummary,1818
SendState, SpaceChild,1919
};2020
@@ -70,7 +70,7 @@ async fn room_summary(room: &Room, spaces: &SpaceService) -> RoomSummary {
7070
direct: room.is_direct().await.unwrap_or(false),7171
favourite: room.is_favourite(),7272
low_priority: room.is_low_priority(),73
- avatar: room.avatar_url(),73
+ avatar: room.avatar_url().as_deref().map(MediaId::plain),7474
latest_event_timestamp_ms: room7575
.latest_event_timestamp()7676
.map(|value| value.get().into()),@@ -87,7 +87,7 @@ async fn room_summary(room: &Room, spaces: &SpaceService) -> RoomSummary {
8787
.map(|hero| RoomHero {8888
user_id: hero.user_id,8989
display_name: hero.display_name,90
- avatar: hero.avatar_url,90
+ avatar: hero.avatar_url.as_deref().map(MediaId::plain),9191
})9292
.collect(),9393
successor: room.successor_room().map(|successor| successor.room_id),@@ -197,7 +197,7 @@ pub(crate) fn space_child(room: SpaceRoom) -> SpaceChild {
197197
name: room.display_name,198198
room_id: room.room_id,199199
topic: room.topic,200
- avatar: room.avatar_url,200
+ avatar: room.avatar_url.as_deref().map(MediaId::plain),201201
canonical_alias: room.canonical_alias,202202
joined_members: room.num_joined_members,203203
space: room.room_type == Some(ruma::room::RoomType::Space),@@ -19,9 +19,9 @@ use ruma::{
1919
};2020
2121
use crate::{22
- Change, MembershipChange, Message, MessageKind, MessageMentions, Reaction, ReplyDetails,23
- ReplyReference, SendState, Sender, ThreadSummary, TimelineContent, TimelineDiff, TimelineEvent,24
- TimelineItem, TimelineItemId, UtdCause,22
+ Change, MediaId, MembershipChange, Message, MessageKind, MessageMentions, Reaction,23
+ ReplyDetails, ReplyReference, SendState, Sender, ThreadSummary, TimelineContent, TimelineDiff,24
+ TimelineEvent, TimelineItem, TimelineItemId, UtdCause,2525
};2626
2727
use super::media::{@@ -198,8 +198,8 @@ fn content(content: &TimelineItemContent, media_identity: Option<&str>) -> Timel
198198
new: change.new.clone(),199199
}),200200
avatar: change.avatar_url_change().map(|change| Change {201
- old: change.old.clone(),202
- new: change.new.clone(),201
+ old: change.old.as_deref().map(MediaId::plain),202
+ new: change.new.as_deref().map(MediaId::plain),203203
}),204204
},205205
TimelineItemContent::OtherState(state) => match state.content() {@@ -210,7 +210,7 @@ fn content(content: &TimelineItemContent, media_identity: Option<&str>) -> Timel
210210
original(change).and_then(|content| non_empty(&content.topic)),211211
),212212
AnyOtherStateEventContentChange::RoomAvatar(change) => TimelineContent::RoomAvatar(213
- original(change).and_then(|content| content.url.clone()),213
+ original(change).and_then(|content| content.url.as_deref().map(MediaId::plain)),214214
),215215
AnyOtherStateEventContentChange::RoomEncryption(_) => {216216
TimelineContent::EncryptionEnabled@@ -380,7 +380,7 @@ fn sender(user_id: &UserId, profile: &TimelineDetails<Profile>) -> Sender {
380380
Sender {381381
user_id: user_id.to_owned(),382382
display_name: profile.and_then(|profile| profile.display_name.clone()),383
- avatar: profile.and_then(|profile| profile.avatar_url.clone()),383
+ avatar: profile.and_then(|profile| profile.avatar_url.as_deref().map(MediaId::plain)),384384
name_ambiguous: profile.is_some_and(|profile| profile.display_name_ambiguous),385385
}386386
}@@ -15,7 +15,7 @@ use matrix_sdk_ui::{
1515
sync_service::SyncService,1616
};1717
use ruma::{18
- EventId, MxcUri, OwnedDeviceId, OwnedEventId, OwnedMxcUri, OwnedRoomId, OwnedRoomOrAliasId,18
+ EventId, OwnedDeviceId, OwnedEventId, OwnedMxcUri, OwnedRoomId, OwnedRoomOrAliasId,1919
OwnedServerName, OwnedTransactionId, OwnedUserId, RoomId, UserId,2020
events::{2121
AnyGlobalAccountDataEventContent, AnyRoomAccountDataEvent, AnyRoomAccountDataEventContent,@@ -555,7 +555,8 @@ impl ClientHandle {
555555
.await556556
}557557
558
- /// bytes for media a retained timeline showed you. concurrent asks share one download558
+ /// bytes for an avatar, or for media a retained timeline showed you. concurrent asks share559
+ /// one download559560
pub async fn media(&self, media_id: &MediaId, size: MediaSize) -> Result<Media, Error> {560561
self.media.timeline_media(media_id, size).await561562
}@@ -570,11 +571,6 @@ impl ClientHandle {
570571
self.media.media_location(media_id, size).await571572
}572573
573
- /// bytes for any plain mxc uri, avatars mostly. same byte cap as everything else574
- pub async fn mxc_media(&self, uri: &MxcUri, size: MediaSize) -> Result<Media, Error> {575
- self.media.mxc_media(uri, size).await576
- }577
-578574
/// the space graph builds on first use and then keeps itself current579575
async fn spaces(&self) -> &SpaceService {580576
self.spaces@@ -908,7 +904,11 @@ fn profile(
908904
Ok(Profile {909905
user_id,910906
display_name: response.get_static::<DisplayName>().map_err(malformed)?,911
- avatar: response.get_static::<AvatarUrl>().map_err(malformed)?,907
+ avatar: response908
+ .get_static::<AvatarUrl>()909
+ .map_err(malformed)?910
+ .as_deref()911
+ .map(MediaId::plain),912912
})913913
}914914
@@ -1069,13 +1069,13 @@ fn normalise_push_notification(
10691069
sender: PushNotificationSender {10701070
user_id: item.event.sender().to_owned(),10711071
display_name: item.sender_display_name,1072
- avatar_url: item.sender_avatar_url.map(Into::into),1072
+ avatar_url: item.sender_avatar_url.as_deref().map(MediaId::plain),10731073
name_ambiguous: item.is_sender_name_ambiguous,10741074
},10751075
room: PushNotificationRoom {10761076
room_id: room_id.to_owned(),10771077
name: item.room_computed_display_name,1078
- avatar_url: item.room_avatar_url.map(Into::into),1078
+ avatar_url: item.room_avatar_url.as_deref().map(MediaId::plain),10791079
canonical_alias: item10801080
.room_canonical_alias10811081
.as_deref()@@ -0,0 +1,10 @@
1
+import type { StorybookConfig } from '@storybook/svelte-vite';2
+3
+const config: StorybookConfig = {4
+ stories: ['../src/**/*.stories.ts'],5
+ addons: ['@storybook/addon-docs', '@storybook/addon-mcp'],6
+ framework: '@storybook/svelte-vite',7
+ core: { disableTelemetry: true }8
+};9
+10
+export default config;@@ -0,0 +1,10 @@
1
+import type { Preview } from '@storybook/svelte-vite';2
+import '../src/app.css';3
+4
+const preview: Preview = {5
+ parameters: {6
+ layout: 'padded'7
+ }8
+};9
+10
+export default preview;@@ -0,0 +1,10 @@
1
+[14:57:10.321] [INFO] storybook v10.6.12
+[14:57:11.856] [ERROR] [38;2;241;97;97mError: Unable to find a usable package manager within NPM, PNPM, Yarn and Yarn 2[39m3
+ at JsPackageManagerFactory.getPackageManagerType (file:///nix/store/2dvvvgj00fsbkrkpfnc20fh8rf6q2sjg-malice-web-node-modules-0.1.0/node_modules/storybook/dist/_node-chunks/chunk-A5M3SXLF.js:17262:11)4
+ at JsPackageManagerFactory.getPackageManager (file:///nix/store/2dvvvgj00fsbkrkpfnc20fh8rf6q2sjg-malice-web-node-modules-0.1.0/node_modules/storybook/dist/_node-chunks/chunk-A5M3SXLF.js:17281:35)5
+ at buildDevStandalone (file:///nix/store/2dvvvgj00fsbkrkpfnc20fh8rf6q2sjg-malice-web-node-modules-0.1.0/node_modules/storybook/dist/core-server/index.js:9242:48)6
+ at async withTelemetry (file:///nix/store/2dvvvgj00fsbkrkpfnc20fh8rf6q2sjg-malice-web-node-modules-0.1.0/node_modules/storybook/dist/_node-chunks/chunk-IRB26IIA.js:142:12)7
+ at async dev (file:///nix/store/2dvvvgj00fsbkrkpfnc20fh8rf6q2sjg-malice-web-node-modules-0.1.0/node_modules/storybook/dist/bin/core.js:4877:3)8
+ at async _Command.<anonymous> (file:///nix/store/2dvvvgj00fsbkrkpfnc20fh8rf6q2sjg-malice-web-node-modules-0.1.0/node_modules/storybook/dist/bin/core.js:4985:3)9
+[14:57:11.857] [WARN] Broken build, fix the error above.10
+You may need to refresh the browser.@@ -8,31 +8,98 @@
88
"name": "malice-web",99
"version": "0.1.0",1010
"dependencies": {11
- "svelte": "^4.2.19"11
+ "svelte": "^5.39.0"1212
},1313
"devDependencies": {14
- "@sveltejs/vite-plugin-svelte": "^3.1.2",15
- "typescript": "~5.6.3",14
+ "@storybook/addon-docs": "^10.6.1",15
+ "@storybook/addon-mcp": "^10.6.1",16
+ "@storybook/svelte-vite": "^10.6.1",17
+ "@sveltejs/vite-plugin-svelte": "^4.0.4",18
+ "storybook": "^10.6.1",19
+ "typescript": "~6.0.3",1620
"vite": "^5.4.11"1721
}1822
},19
- "node_modules/@ampproject/remapping": {20
- "version": "2.3.0",21
- "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",22
- "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",23
- "license": "Apache-2.0",23
+ "node_modules/@adobe/css-tools": {24
+ "version": "4.5.0",25
+ "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.5.0.tgz",26
+ "integrity": "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==",27
+ "dev": true,28
+ "license": "MIT"29
+ },30
+ "node_modules/@babel/code-frame": {31
+ "version": "7.29.7",32
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",33
+ "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",34
+ "dev": true,35
+ "license": "MIT",2436
"dependencies": {25
- "@jridgewell/gen-mapping": "^0.3.5",26
- "@jridgewell/trace-mapping": "^0.3.24"37
+ "@babel/helper-validator-identifier": "^7.29.7",38
+ "js-tokens": "^4.0.0",39
+ "picocolors": "^1.1.1"2740
},2841
"engines": {29
- "node": ">=6.0.0"42
+ "node": ">=6.9.0"43
+ }44
+ },45
+ "node_modules/@babel/helper-validator-identifier": {46
+ "version": "7.29.7",47
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",48
+ "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",49
+ "dev": true,50
+ "license": "MIT",51
+ "engines": {52
+ "node": ">=6.9.0"53
+ }54
+ },55
+ "node_modules/@babel/runtime": {56
+ "version": "7.29.10",57
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.10.tgz",58
+ "integrity": "sha512-NpugTzbKgGrNe45Ui32cN8vCFFMxVtP/9rtfwv0nP5FRDAjvYBxJcLVpYA9mr1jxP6cnIT7x9LUzuDTbWYYNRA==",59
+ "dev": true,60
+ "license": "MIT",61
+ "engines": {62
+ "node": ">=6.9.0"63
+ }64
+ },65
+ "node_modules/@emnapi/core": {66
+ "version": "1.9.2",67
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz",68
+ "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==",69
+ "dev": true,70
+ "license": "MIT",71
+ "optional": true,72
+ "dependencies": {73
+ "@emnapi/wasi-threads": "1.2.1",74
+ "tslib": "^2.4.0"75
+ }76
+ },77
+ "node_modules/@emnapi/runtime": {78
+ "version": "1.9.2",79
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz",80
+ "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==",81
+ "dev": true,82
+ "license": "MIT",83
+ "optional": true,84
+ "dependencies": {85
+ "tslib": "^2.4.0"86
+ }87
+ },88
+ "node_modules/@emnapi/wasi-threads": {89
+ "version": "1.2.1",90
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz",91
+ "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==",92
+ "dev": true,93
+ "license": "MIT",94
+ "optional": true,95
+ "dependencies": {96
+ "tslib": "^2.4.0"3097
}3198
},3299
"node_modules/@esbuild/aix-ppc64": {33
- "version": "0.21.5",34
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",35
- "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",100
+ "version": "0.28.2",101
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz",102
+ "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==",36103
"cpu": [37104
"ppc64"38105
],@@ -43,13 +110,13 @@
43110
"aix"44111
],45112
"engines": {46
- "node": ">=12"113
+ "node": ">=18"47114
}48115
},49116
"node_modules/@esbuild/android-arm": {50
- "version": "0.21.5",51
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",52
- "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",117
+ "version": "0.28.2",118
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz",119
+ "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==",53120
"cpu": [54121
"arm"55122
],@@ -60,13 +127,13 @@
60127
"android"61128
],62129
"engines": {63
- "node": ">=12"130
+ "node": ">=18"64131
}65132
},66133
"node_modules/@esbuild/android-arm64": {67
- "version": "0.21.5",68
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",69
- "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",134
+ "version": "0.28.2",135
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz",136
+ "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==",70137
"cpu": [71138
"arm64"72139
],@@ -77,13 +144,13 @@
77144
"android"78145
],79146
"engines": {80
- "node": ">=12"147
+ "node": ">=18"81148
}82149
},83150
"node_modules/@esbuild/android-x64": {84
- "version": "0.21.5",85
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",86
- "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",151
+ "version": "0.28.2",152
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz",153
+ "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==",87154
"cpu": [88155
"x64"89156
],@@ -94,13 +161,13 @@
94161
"android"95162
],96163
"engines": {97
- "node": ">=12"164
+ "node": ">=18"98165
}99166
},100167
"node_modules/@esbuild/darwin-arm64": {101
- "version": "0.21.5",102
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",103
- "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",168
+ "version": "0.28.2",169
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz",170
+ "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==",104171
"cpu": [105172
"arm64"106173
],@@ -111,13 +178,13 @@
111178
"darwin"112179
],113180
"engines": {114
- "node": ">=12"181
+ "node": ">=18"115182
}116183
},117184
"node_modules/@esbuild/darwin-x64": {118
- "version": "0.21.5",119
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",120
- "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",185
+ "version": "0.28.2",186
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz",187
+ "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==",121188
"cpu": [122189
"x64"123190
],@@ -128,13 +195,13 @@
128195
"darwin"129196
],130197
"engines": {131
- "node": ">=12"198
+ "node": ">=18"132199
}133200
},134201
"node_modules/@esbuild/freebsd-arm64": {135
- "version": "0.21.5",136
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",137
- "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",202
+ "version": "0.28.2",203
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz",204
+ "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==",138205
"cpu": [139206
"arm64"140207
],@@ -145,13 +212,13 @@
145212
"freebsd"146213
],147214
"engines": {148
- "node": ">=12"215
+ "node": ">=18"149216
}150217
},151218
"node_modules/@esbuild/freebsd-x64": {152
- "version": "0.21.5",153
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",154
- "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",219
+ "version": "0.28.2",220
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz",221
+ "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==",155222
"cpu": [156223
"x64"157224
],@@ -162,13 +229,13 @@
162229
"freebsd"163230
],164231
"engines": {165
- "node": ">=12"232
+ "node": ">=18"166233
}167234
},168235
"node_modules/@esbuild/linux-arm": {169
- "version": "0.21.5",170
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",171
- "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",236
+ "version": "0.28.2",237
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz",238
+ "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==",172239
"cpu": [173240
"arm"174241
],@@ -179,13 +246,13 @@
179246
"linux"180247
],181248
"engines": {182
- "node": ">=12"249
+ "node": ">=18"183250
}184251
},185252
"node_modules/@esbuild/linux-arm64": {186
- "version": "0.21.5",187
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",188
- "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",253
+ "version": "0.28.2",254
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz",255
+ "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==",189256
"cpu": [190257
"arm64"191258
],@@ -196,13 +263,13 @@
196263
"linux"197264
],198265
"engines": {199
- "node": ">=12"266
+ "node": ">=18"200267
}201268
},202269
"node_modules/@esbuild/linux-ia32": {203
- "version": "0.21.5",204
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",205
- "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",270
+ "version": "0.28.2",271
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz",272
+ "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==",206273
"cpu": [207274
"ia32"208275
],@@ -213,13 +280,13 @@
213280
"linux"214281
],215282
"engines": {216
- "node": ">=12"283
+ "node": ">=18"217284
}218285
},219286
"node_modules/@esbuild/linux-loong64": {220
- "version": "0.21.5",221
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",222
- "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",287
+ "version": "0.28.2",288
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz",289
+ "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==",223290
"cpu": [224291
"loong64"225292
],@@ -230,13 +297,13 @@
230297
"linux"231298
],232299
"engines": {233
- "node": ">=12"300
+ "node": ">=18"234301
}235302
},236303
"node_modules/@esbuild/linux-mips64el": {237
- "version": "0.21.5",238
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",239
- "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",304
+ "version": "0.28.2",305
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz",306
+ "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==",240307
"cpu": [241308
"mips64el"242309
],@@ -247,13 +314,13 @@
247314
"linux"248315
],249316
"engines": {250
- "node": ">=12"317
+ "node": ">=18"251318
}252319
},253320
"node_modules/@esbuild/linux-ppc64": {254
- "version": "0.21.5",255
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",256
- "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",321
+ "version": "0.28.2",322
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz",323
+ "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==",257324
"cpu": [258325
"ppc64"259326
],@@ -264,13 +331,13 @@
264331
"linux"265332
],266333
"engines": {267
- "node": ">=12"334
+ "node": ">=18"268335
}269336
},270337
"node_modules/@esbuild/linux-riscv64": {271
- "version": "0.21.5",272
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",273
- "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",338
+ "version": "0.28.2",339
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz",340
+ "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==",274341
"cpu": [275342
"riscv64"276343
],@@ -281,13 +348,13 @@
281348
"linux"282349
],283350
"engines": {284
- "node": ">=12"351
+ "node": ">=18"285352
}286353
},287354
"node_modules/@esbuild/linux-s390x": {288
- "version": "0.21.5",289
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",290
- "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",355
+ "version": "0.28.2",356
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz",357
+ "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==",291358
"cpu": [292359
"s390x"293360
],@@ -298,13 +365,13 @@
298365
"linux"299366
],300367
"engines": {301
- "node": ">=12"368
+ "node": ">=18"302369
}303370
},304371
"node_modules/@esbuild/linux-x64": {305
- "version": "0.21.5",306
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",307
- "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",372
+ "version": "0.28.2",373
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz",374
+ "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==",308375
"cpu": [309376
"x64"310377
],@@ -315,13 +382,30 @@
315382
"linux"316383
],317384
"engines": {318
- "node": ">=12"385
+ "node": ">=18"386
+ }387
+ },388
+ "node_modules/@esbuild/netbsd-arm64": {389
+ "version": "0.28.2",390
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz",391
+ "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==",392
+ "cpu": [393
+ "arm64"394
+ ],395
+ "dev": true,396
+ "license": "MIT",397
+ "optional": true,398
+ "os": [399
+ "netbsd"400
+ ],401
+ "engines": {402
+ "node": ">=18"319403
}320404
},321405
"node_modules/@esbuild/netbsd-x64": {322
- "version": "0.21.5",323
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",324
- "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",406
+ "version": "0.28.2",407
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz",408
+ "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==",325409
"cpu": [326410
"x64"327411
],@@ -332,13 +416,30 @@
332416
"netbsd"333417
],334418
"engines": {335
- "node": ">=12"419
+ "node": ">=18"420
+ }421
+ },422
+ "node_modules/@esbuild/openbsd-arm64": {423
+ "version": "0.28.2",424
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz",425
+ "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==",426
+ "cpu": [427
+ "arm64"428
+ ],429
+ "dev": true,430
+ "license": "MIT",431
+ "optional": true,432
+ "os": [433
+ "openbsd"434
+ ],435
+ "engines": {436
+ "node": ">=18"336437
}337438
},338439
"node_modules/@esbuild/openbsd-x64": {339
- "version": "0.21.5",340
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",341
- "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",440
+ "version": "0.28.2",441
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz",442
+ "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==",342443
"cpu": [343444
"x64"344445
],@@ -349,13 +450,30 @@
349450
"openbsd"350451
],351452
"engines": {352
- "node": ">=12"453
+ "node": ">=18"454
+ }455
+ },456
+ "node_modules/@esbuild/openharmony-arm64": {457
+ "version": "0.28.2",458
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz",459
+ "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==",460
+ "cpu": [461
+ "arm64"462
+ ],463
+ "dev": true,464
+ "license": "MIT",465
+ "optional": true,466
+ "os": [467
+ "openharmony"468
+ ],469
+ "engines": {470
+ "node": ">=18"353471
}354472
},355473
"node_modules/@esbuild/sunos-x64": {356
- "version": "0.21.5",357
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",358
- "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",474
+ "version": "0.28.2",475
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz",476
+ "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==",359477
"cpu": [360478
"x64"361479
],@@ -366,13 +484,13 @@
366484
"sunos"367485
],368486
"engines": {369
- "node": ">=12"487
+ "node": ">=18"370488
}371489
},372490
"node_modules/@esbuild/win32-arm64": {373
- "version": "0.21.5",374
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",375
- "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",491
+ "version": "0.28.2",492
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz",493
+ "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==",376494
"cpu": [377495
"arm64"378496
],@@ -383,13 +501,13 @@
383501
"win32"384502
],385503
"engines": {386
- "node": ">=12"504
+ "node": ">=18"387505
}388506
},389507
"node_modules/@esbuild/win32-ia32": {390
- "version": "0.21.5",391
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",392
- "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",508
+ "version": "0.28.2",509
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz",510
+ "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==",393511
"cpu": [394512
"ia32"395513
],@@ -400,13 +518,13 @@
400518
"win32"401519
],402520
"engines": {403
- "node": ">=12"521
+ "node": ">=18"404522
}405523
},406524
"node_modules/@esbuild/win32-x64": {407
- "version": "0.21.5",408
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",409
- "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",525
+ "version": "0.28.2",526
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz",527
+ "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==",410528
"cpu": [411529
"x64"412530
],@@ -417,7 +535,7 @@
417535
"win32"418536
],419537
"engines": {420
- "node": ">=12"538
+ "node": ">=18"421539
}422540
},423541
"node_modules/@jridgewell/gen-mapping": {@@ -430,6 +548,16 @@
430548
"@jridgewell/trace-mapping": "^0.3.24"431549
}432550
},551
+ "node_modules/@jridgewell/remapping": {552
+ "version": "2.3.5",553
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",554
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",555
+ "license": "MIT",556
+ "dependencies": {557
+ "@jridgewell/gen-mapping": "^0.3.5",558
+ "@jridgewell/trace-mapping": "^0.3.24"559
+ }560
+ },433561
"node_modules/@jridgewell/resolve-uri": {434562
"version": "3.1.2",435563
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",@@ -455,6 +583,24 @@
455583
"@jridgewell/sourcemap-codec": "^1.4.14"456584
}457585
},586
+ "node_modules/@mdx-js/react": {587
+ "version": "3.1.1",588
+ "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.1.tgz",589
+ "integrity": "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==",590
+ "dev": true,591
+ "license": "MIT",592
+ "dependencies": {593
+ "@types/mdx": "^2.0.0"594
+ },595
+ "funding": {596
+ "type": "opencollective",597
+ "url": "https://opencollective.com/unified"598
+ },599
+ "peerDependencies": {600
+ "@types/react": ">=16",601
+ "react": ">=16"602
+ }603
+ },458604
"node_modules/@napi-rs/lzma-linux-x64-gnu": {459605
"version": "1.5.1",460606
"resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz",@@ -472,10 +618,32 @@
472618
"node": "^22.20 || ^24.12 || >=25"473619
}474620
},475
- "node_modules/@rollup/rollup-android-arm-eabi": {476
- "version": "4.63.4",477
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.63.4.tgz",478
- "integrity": "sha512-I+BSHzTAhKN2n7ZwGZsegGcZjDpLqFOMAtJz/u6uFGe0pUFbq56dEHjqJV/ZUdRJtNXNxA+hREUatZBvMR3Oiw==",621
+ "node_modules/@napi-rs/wasm-runtime": {622
+ "version": "1.2.5",623
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.5.tgz",624
+ "integrity": "sha512-HshSvXzmBxNzqejd3k/KemgQ3hdREUYFRRrgxOZ+gPljDIsO2SDZrVZMd4Z/HsxudQbE62OVyVFE8z9BCurfjA==",625
+ "dev": true,626
+ "license": "MIT",627
+ "optional": true,628
+ "dependencies": {629
+ "@tybys/wasm-util": "^0.10.3"630
+ },631
+ "engines": {632
+ "node": "^20.19.0 || ^22.13.0 || >=23.5.0"633
+ },634
+ "funding": {635
+ "type": "github",636
+ "url": "https://github.com/sponsors/Brooooooklyn"637
+ },638
+ "peerDependencies": {639
+ "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4",640
+ "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4"641
+ }642
+ },643
+ "node_modules/@oxc-parser/binding-android-arm-eabi": {644
+ "version": "0.127.0",645
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm-eabi/-/binding-android-arm-eabi-0.127.0.tgz",646
+ "integrity": "sha512-0LC7ye4hvqbIKxAzThzvswgHLFu2AURKzYLeSVvLdu2TBOYWQDmHnTqPLeA597BcUCxiLqLsS4CJ5uoI5WYWCQ==",479647
"cpu": [480648
"arm"481649
],@@ -484,12 +652,15 @@
484652
"optional": true,485653
"os": [486654
"android"487
- ]655
+ ],656
+ "engines": {657
+ "node": "^20.19.0 || >=22.12.0"658
+ }488659
},489
- "node_modules/@rollup/rollup-android-arm64": {490
- "version": "4.63.4",491
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.63.4.tgz",492
- "integrity": "sha512-pu3BdjS2LtEzRu2elmGzS3fIeWSZy4BMDIaLNwjorO76+k2d0LMluijhsDx3KQyQBQ/lLUZCQA9/s6csvUfuhw==",660
+ "node_modules/@oxc-parser/binding-android-arm64": {661
+ "version": "0.127.0",662
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm64/-/binding-android-arm64-0.127.0.tgz",663
+ "integrity": "sha512-b5jtVTH6AU5CJXHNdj7Jj9IEiR9yVjjnwHzPJhGyHGPdcsZSzBCkS9GBbV33niRMvKthDwQRFRJfI4a+k4PvYg==",493664
"cpu": [494665
"arm64"495666
],@@ -498,12 +669,15 @@
498669
"optional": true,499670
"os": [500671
"android"501
- ]672
+ ],673
+ "engines": {674
+ "node": "^20.19.0 || >=22.12.0"675
+ }502676
},503
- "node_modules/@rollup/rollup-darwin-arm64": {504
- "version": "4.63.4",505
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.63.4.tgz",506
- "integrity": "sha512-xfSrj9MHnWK9GaSqT9U0ImHtH/N8WZlHLx4cZHiuLcqs640hvZ3hLPd5UR2AZS57FaE8HrRUSpltbZdWRxHiDA==",677
+ "node_modules/@oxc-parser/binding-darwin-arm64": {678
+ "version": "0.127.0",679
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.127.0.tgz",680
+ "integrity": "sha512-obCE8B7ISKkJidjlhv9xRGJPOSDG2Yu6PRga9Ruaz35uintHxbp1Ki/Yc71wx4rj3Edrm0a1kzG1TAwit0wFpg==",507681
"cpu": [508682
"arm64"509683
],@@ -512,12 +686,15 @@
512686
"optional": true,513687
"os": [514688
"darwin"515
- ]689
+ ],690
+ "engines": {691
+ "node": "^20.19.0 || >=22.12.0"692
+ }516693
},517
- "node_modules/@rollup/rollup-darwin-x64": {518
- "version": "4.63.4",519
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.63.4.tgz",520
- "integrity": "sha512-bqU99PLJb/dqb3S0GIMdeuyAEETSUgZBoqXYd3Sd+WCsV+MmPhnN6JrotWyir31+QgH7EvvE5/mwGJlEoci8Fw==",694
+ "node_modules/@oxc-parser/binding-darwin-x64": {695
+ "version": "0.127.0",696
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-x64/-/binding-darwin-x64-0.127.0.tgz",697
+ "integrity": "sha512-JL6Xb5IwPQT8rUzlpsX7E+AgfcdNklXNPFp8pjCQQ5MQOQo5rtEB2ui+3Hgg9Sn7Y9Egj6YOLLiHhLpdAe12Aw==",521698
"cpu": [522699
"x64"523700
],@@ -526,26 +703,15 @@
526703
"optional": true,527704
"os": [528705
"darwin"529
- ]530
- },531
- "node_modules/@rollup/rollup-freebsd-arm64": {532
- "version": "4.63.4",533
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.63.4.tgz",534
- "integrity": "sha512-JinsFZ5G40oXQb+sUuiA5x689vhr6dDYK0H0NL+rwKdL6CqnmYN8PE4ZwfRSoIjrCxqTQG/SLfTtSvHeGxoVlw==",535
- "cpu": [536
- "arm64"537706
],538
- "dev": true,539
- "license": "MIT",540
- "optional": true,541
- "os": [542
- "freebsd"543
- ]707
+ "engines": {708
+ "node": "^20.19.0 || >=22.12.0"709
+ }544710
},545
- "node_modules/@rollup/rollup-freebsd-x64": {546
- "version": "4.63.4",547
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.63.4.tgz",548
- "integrity": "sha512-GAdA4UxpiNm27cLHr2GqXBpAD0x9FqwYBY7/YSP0Ss0/PNi4k8gbviqpIpYbVSRBaS2ZcegXEzgTQMbRNCwxCw==",711
+ "node_modules/@oxc-parser/binding-freebsd-x64": {712
+ "version": "0.127.0",713
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.127.0.tgz",714
+ "integrity": "sha512-SDQ/3MQFw58fqQz3Z1PhSKFF3JoCF4gmlNjziDm8X02tTahCw0qJbd7FGPDKw1i4VTBZene9JPyC3mHtSvi+wA==",549715
"cpu": [550716
"x64"551717
],@@ -554,12 +720,15 @@
554720
"optional": true,555721
"os": [556722
"freebsd"557
- ]723
+ ],724
+ "engines": {725
+ "node": "^20.19.0 || >=22.12.0"726
+ }558727
},559
- "node_modules/@rollup/rollup-linux-arm-gnueabihf": {560
- "version": "4.63.4",561
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.63.4.tgz",562
- "integrity": "sha512-qDd6NoA1znaLjp4jR5U/KWCdLAKDJNB8W9ChbbDaKbo0xA+Atln5HK6LFCZ4oJQpemtRZA288DCirFRjrspptw==",728
+ "node_modules/@oxc-parser/binding-linux-arm-gnueabihf": {729
+ "version": "0.127.0",730
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.127.0.tgz",731
+ "integrity": "sha512-Av+D1MIqzV0YMGPT9we2SIZaMKD7Cxs4CvXSx/yxaWHewZjYEjScpOf5igc8IILASViw4WTnjlwUdI1KzVtDHQ==",563732
"cpu": [564733
"arm"565734
],@@ -568,12 +737,15 @@
568737
"optional": true,569738
"os": [570739
"linux"571
- ]740
+ ],741
+ "engines": {742
+ "node": "^20.19.0 || >=22.12.0"743
+ }572744
},573
- "node_modules/@rollup/rollup-linux-arm-musleabihf": {574
- "version": "4.63.4",575
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.63.4.tgz",576
- "integrity": "sha512-WtB5Tz5KTNINb8ZA+8sQ7bmjuS1JrRT7YverYIhUGdWWDlpzVWmIwuZE+jidkEXUn1l0zrEkaIMa8dHF3NGcsA==",745
+ "node_modules/@oxc-parser/binding-linux-arm-musleabihf": {746
+ "version": "0.127.0",747
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.127.0.tgz",748
+ "integrity": "sha512-Cs2fdJ8cPpFdeebj6p4dag8A4+56hPvZ0AhQQzlaLswGz1tz7bXt1nETLeorrM9+AMcWFFkqxcXwDGfTVidY8g==",577749
"cpu": [578750
"arm"579751
],@@ -582,12 +754,15 @@
582754
"optional": true,583755
"os": [584756
"linux"585
- ]757
+ ],758
+ "engines": {759
+ "node": "^20.19.0 || >=22.12.0"760
+ }586761
},587
- "node_modules/@rollup/rollup-linux-arm64-gnu": {588
- "version": "4.63.4",589
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.63.4.tgz",590
- "integrity": "sha512-VcQ3L1tjnkKzWjryAVaFhHEWcqOfICX9uxVVoDzm2t0DpgKRHd2zOpVrJc0xsWeBZcBFyYROCIBdyR/fS174pg==",762
+ "node_modules/@oxc-parser/binding-linux-arm64-gnu": {763
+ "version": "0.127.0",764
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.127.0.tgz",765
+ "integrity": "sha512-qdOfTcT6SY8gsJrrV92uyEUyjqMGPpIB5JZUG6QN5dukYd+7/j0kX6MwK1DgQj39jtUYixxPiaRUiEN1+0CXgQ==",591766
"cpu": [592767
"arm64"593768
],@@ -596,12 +771,15 @@
596771
"optional": true,597772
"os": [598773
"linux"599
- ]774
+ ],775
+ "engines": {776
+ "node": "^20.19.0 || >=22.12.0"777
+ }600778
},601
- "node_modules/@rollup/rollup-linux-arm64-musl": {602
- "version": "4.63.4",603
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.63.4.tgz",604
- "integrity": "sha512-6+ZQX6P5s0cMDN2Ypb8Lbm2+/sZYmZjdaYny992ujUU9UKi/4CWoJWsl1pNvjWJHNHGK51m+jKGLlh1ylb2ifQ==",779
+ "node_modules/@oxc-parser/binding-linux-arm64-musl": {780
+ "version": "0.127.0",781
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.127.0.tgz",782
+ "integrity": "sha512-EoTCZneNFU/P2qrpEM+RHmQwt+CvDkyGESG6qhr7KaegXLZwePfbrkCDfAk8/rhxbDUVGsZILX+2tqPzFtoFWA==",605783
"cpu": [606784
"arm64"607785
],@@ -610,110 +788,256 @@
610788
"optional": true,611789
"os": [612790
"linux"613
- ]791
+ ],792
+ "engines": {793
+ "node": "^20.19.0 || >=22.12.0"794
+ }614795
},615
- "node_modules/@rollup/rollup-linux-loong64-gnu": {616
- "version": "4.63.4",617
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.63.4.tgz",618
- "integrity": "sha512-D72ZnvkFkBXOfzMMQLcwfPLyGkKb7HZ9/mf97B7v6/P5Lbv4oFOtSY/uHbS8lH6uKUOxoKiuokdb50XZSzzbJw==",796
+ "node_modules/@oxc-parser/binding-linux-ppc64-gnu": {797
+ "version": "0.127.0",798
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.127.0.tgz",799
+ "integrity": "sha512-zALjmZYgxFLHjXeudcDF0xFGNydTAtkAeXAr2EuC17ywCyFxcmQra4w0BMde0Yi/re4Bi4iwEoEXtYN7l6eBLQ==",619800
"cpu": [620
- "loong64"801
+ "ppc64"621802
],622803
"dev": true,623804
"license": "MIT",624805
"optional": true,625806
"os": [626807
"linux"627
- ]808
+ ],809
+ "engines": {810
+ "node": "^20.19.0 || >=22.12.0"811
+ }628812
},629
- "node_modules/@rollup/rollup-linux-loong64-musl": {630
- "version": "4.63.4",631
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.63.4.tgz",632
- "integrity": "sha512-piU6BxeqA3O9KSu3kRCIQQtNqFFaTu21SEV4FwaRZowpnj3bLaWPZHw+xFqCs0XlJ+aOH3PTRWGoglH+mKA/OA==",813
+ "node_modules/@oxc-parser/binding-linux-riscv64-gnu": {814
+ "version": "0.127.0",815
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.127.0.tgz",816
+ "integrity": "sha512-fPP8M6zQLS7Jz7o9d5ArUSuAuSK3e+WCYVrCpdzeCOejidtZExJ9tjhDrAd3HEPqARBCPmdpqxESPFqy44vkBQ==",633817
"cpu": [634
- "loong64"818
+ "riscv64"635819
],636820
"dev": true,637821
"license": "MIT",638822
"optional": true,639823
"os": [640824
"linux"641
- ]825
+ ],826
+ "engines": {827
+ "node": "^20.19.0 || >=22.12.0"828
+ }642829
},643
- "node_modules/@rollup/rollup-linux-ppc64-gnu": {644
- "version": "4.63.4",645
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.63.4.tgz",646
- "integrity": "sha512-/5PGpHwqt2EEEOUs1XwzubE/ucr0dWDQ+to3zqi4Ds7EWpwtQ79wXc4JBoxqj/OwpawTsKWzJxHfSuBOq3DrWA==",830
+ "node_modules/@oxc-parser/binding-linux-riscv64-musl": {831
+ "version": "0.127.0",832
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.127.0.tgz",833
+ "integrity": "sha512-7IcC4Ao02oGpfnjt+X/oF4U2mllo2qoSkw5xxiXNKL9MCTsTiAC6616beOuehdxGcnz1bRoPC1RQ2f1GQDdN+g==",647834
"cpu": [648
- "ppc64"835
+ "riscv64"649836
],650837
"dev": true,651838
"license": "MIT",652839
"optional": true,653840
"os": [654841
"linux"655
- ]842
+ ],843
+ "engines": {844
+ "node": "^20.19.0 || >=22.12.0"845
+ }656846
},657
- "node_modules/@rollup/rollup-linux-ppc64-musl": {658
- "version": "4.63.4",659
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.63.4.tgz",660
- "integrity": "sha512-cX3beZDLWt7G2oJF+nhChiT+qtaihs+S2xi7ziGmVB+2pwPng6D0Ed0HmElQOgv2UsUmSJJLGwpBao/3TDx3VA==",847
+ "node_modules/@oxc-parser/binding-linux-s390x-gnu": {848
+ "version": "0.127.0",849
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.127.0.tgz",850
+ "integrity": "sha512-pbXIhiNFHoqWeqDNLiJ9JkpHz1IM9k4DXa66x+1GTWMG7iLxtkXgE53iiuKSXwmk3zIYmaPVfBvgcAhS583K4Q==",661851
"cpu": [662
- "ppc64"852
+ "s390x"663853
],664854
"dev": true,665855
"license": "MIT",666856
"optional": true,667857
"os": [668858
"linux"669
- ]859
+ ],860
+ "engines": {861
+ "node": "^20.19.0 || >=22.12.0"862
+ }670863
},671
- "node_modules/@rollup/rollup-linux-riscv64-gnu": {672
- "version": "4.63.4",673
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.63.4.tgz",674
- "integrity": "sha512-1uz2mGWHyptR7DgHHrlbdRAjXK7v7elGZ9lMja910/RP+ZYbX6xAmCiU9UZSX4hqmgtHMv6lr5l3kq1HIOpcag==",864
+ "node_modules/@oxc-parser/binding-linux-x64-gnu": {865
+ "version": "0.127.0",866
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.127.0.tgz",867
+ "integrity": "sha512-MYCguB9RvBvlSd6gbuNI7QwiLoCCAlGnlRJFPrzLI6U1/9wkC/WK6LtBAUln55H1Ctqw45PWmqrobKoMhsYQzQ==",675868
"cpu": [676
- "riscv64"869
+ "x64"677870
],678871
"dev": true,679872
"license": "MIT",680873
"optional": true,681874
"os": [682875
"linux"683
- ]876
+ ],877
+ "engines": {878
+ "node": "^20.19.0 || >=22.12.0"879
+ }684880
},685
- "node_modules/@rollup/rollup-linux-riscv64-musl": {686
- "version": "4.63.4",687
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.63.4.tgz",688
- "integrity": "sha512-nLS8topojxyz7SRpKR2IODRpQ0XPZ+xaOXvT3+hqK/Uy8Lo5HFgkkIBiIrCu5tL5YqzTvgovGw55PwpahTAGig==",881
+ "node_modules/@oxc-parser/binding-linux-x64-musl": {882
+ "version": "0.127.0",883
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.127.0.tgz",884
+ "integrity": "sha512-5eY0B/bxf1xIUxb4NOTvOI3KWtBQfPWYyKAzgcrCt0mDibSZygVpO1Pz8bkeiSZ5Jj9+M09dkggG3H8I5d0Uyg==",689885
"cpu": [690
- "riscv64"886
+ "x64"691887
],692888
"dev": true,693889
"license": "MIT",694890
"optional": true,695891
"os": [696892
"linux"893
+ ],894
+ "engines": {895
+ "node": "^20.19.0 || >=22.12.0"896
+ }897
+ },898
+ "node_modules/@oxc-parser/binding-openharmony-arm64": {899
+ "version": "0.127.0",900
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-openharmony-arm64/-/binding-openharmony-arm64-0.127.0.tgz",901
+ "integrity": "sha512-Gld0ajrFTUXNtdw20fVBuTQx66FA75nIVg+//pPfR3sXkuABB4mTBhl3r9JNzrJpgW//qiwxf0nWXUWGJSL3UQ==",902
+ "cpu": [903
+ "arm64"904
+ ],905
+ "dev": true,906
+ "license": "MIT",907
+ "optional": true,908
+ "os": [909
+ "openharmony"910
+ ],911
+ "engines": {912
+ "node": "^20.19.0 || >=22.12.0"913
+ }914
+ },915
+ "node_modules/@oxc-parser/binding-wasm32-wasi": {916
+ "version": "0.127.0",917
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-wasm32-wasi/-/binding-wasm32-wasi-0.127.0.tgz",918
+ "integrity": "sha512-T6KVD7rhLzFlwGRXMnxUFfkCZD8FHnb968wVXW1mXzgRFc5RNXOBY2mPPDZ77x5Ln76ltLMgtPg0cOkU1NSrEQ==",919
+ "cpu": [920
+ "wasm32"921
+ ],922
+ "dev": true,923
+ "license": "MIT",924
+ "optional": true,925
+ "dependencies": {926
+ "@emnapi/core": "1.9.2",927
+ "@emnapi/runtime": "1.9.2",928
+ "@napi-rs/wasm-runtime": "^1.1.4"929
+ },930
+ "engines": {931
+ "node": "^20.19.0 || >=22.12.0"932
+ }933
+ },934
+ "node_modules/@oxc-parser/binding-win32-arm64-msvc": {935
+ "version": "0.127.0",936
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.127.0.tgz",937
+ "integrity": "sha512-Ujvw4X+LD1CCGULcsQcvb4YNVoBGqt+JHgNNzGGaCImELiZLk477ifUH53gIbE7EKd933NdTi25JWEr9K2HwXw==",938
+ "cpu": [939
+ "arm64"940
+ ],941
+ "dev": true,942
+ "license": "MIT",943
+ "optional": true,944
+ "os": [945
+ "win32"946
+ ],947
+ "engines": {948
+ "node": "^20.19.0 || >=22.12.0"949
+ }950
+ },951
+ "node_modules/@oxc-parser/binding-win32-ia32-msvc": {952
+ "version": "0.127.0",953
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.127.0.tgz",954
+ "integrity": "sha512-0cwxKO7KHQQQfo4Uf4B2SQrhgm+cJaP9OvFFhx52Tkg4bezsacu83GB2/In5bC415Ueeym+kXdnge/57rbSfTw==",955
+ "cpu": [956
+ "ia32"957
+ ],958
+ "dev": true,959
+ "license": "MIT",960
+ "optional": true,961
+ "os": [962
+ "win32"963
+ ],964
+ "engines": {965
+ "node": "^20.19.0 || >=22.12.0"966
+ }967
+ },968
+ "node_modules/@oxc-parser/binding-win32-x64-msvc": {969
+ "version": "0.127.0",970
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.127.0.tgz",971
+ "integrity": "sha512-rOrnSQSCbhI2kowr9XxE7m9a8oQXnBHjnS6j95LxxAnEZ0+Fz20WlRXG4ondQb+ejjt2KOsa65sE6++L6kUd+w==",972
+ "cpu": [973
+ "x64"974
+ ],975
+ "dev": true,976
+ "license": "MIT",977
+ "optional": true,978
+ "os": [979
+ "win32"980
+ ],981
+ "engines": {982
+ "node": "^20.19.0 || >=22.12.0"983
+ }984
+ },985
+ "node_modules/@oxc-project/types": {986
+ "version": "0.127.0",987
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.127.0.tgz",988
+ "integrity": "sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==",989
+ "dev": true,990
+ "license": "MIT",991
+ "funding": {992
+ "url": "https://github.com/sponsors/Boshen"993
+ }994
+ },995
+ "node_modules/@oxc-resolver/binding-android-arm-eabi": {996
+ "version": "11.21.2",997
+ "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-android-arm-eabi/-/binding-android-arm-eabi-11.21.2.tgz",998
+ "integrity": "sha512-xQoCRv+gKax9KTdwdaQNnAFOai8neay7g3jExDIORzhbrejwGSJaZNTdOJHR5ziLg2joMxOCMOFMo4zuxza2uQ==",999
+ "cpu": [1000
+ "arm"1001
+ ],1002
+ "dev": true,1003
+ "license": "MIT",1004
+ "optional": true,1005
+ "os": [1006
+ "android"6971007
]6981008
},699
- "node_modules/@rollup/rollup-linux-s390x-gnu": {700
- "version": "4.63.4",701
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.63.4.tgz",702
- "integrity": "sha512-gs7DRKotr3l3q+jGPQBjH0ng1FjlEDm5ueQrkw5JtQvtLyEIcLASqAEaor56BhkKRzk+IcQzrcanBdb/bBQn8g==",1009
+ "node_modules/@oxc-resolver/binding-android-arm64": {1010
+ "version": "11.21.2",1011
+ "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-android-arm64/-/binding-android-arm64-11.21.2.tgz",1012
+ "integrity": "sha512-HF5oiE2L05yInPYCFD/4uxSrEZW4SuIfn99Y6L1xnJnzl066JR+MJs2rIdstw8A2MPlAKH+13dpFPNycjqzvGg==",7031013
"cpu": [704
- "s390x"1014
+ "arm64"7051015
],7061016
"dev": true,7071017
"license": "MIT",7081018
"optional": true,7091019
"os": [710
- "linux"1020
+ "android"7111021
]7121022
},713
- "node_modules/@rollup/rollup-linux-x64-gnu": {714
- "version": "4.63.4",715
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.63.4.tgz",716
- "integrity": "sha512-791ET7W17NnScOZM7h4dX5hYspxE28htPFsb1awY/NRR8+PRNkS53e475rDdxXXDrP+kwnCcNWg9CX5ztn/Aqw==",1023
+ "node_modules/@oxc-resolver/binding-darwin-arm64": {1024
+ "version": "11.21.2",1025
+ "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-11.21.2.tgz",1026
+ "integrity": "sha512-UX4u49CVCAD8QZNELaW8eMGgMAGwFWYEPbvNsh+3r/gs4NX3KfpiACMVwRQT0EuH3uat9hM5Zl+Ppm9pJD8tgg==",1027
+ "cpu": [1028
+ "arm64"1029
+ ],1030
+ "dev": true,1031
+ "license": "MIT",1032
+ "optional": true,1033
+ "os": [1034
+ "darwin"1035
+ ]1036
+ },1037
+ "node_modules/@oxc-resolver/binding-darwin-x64": {1038
+ "version": "11.21.2",1039
+ "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-11.21.2.tgz",1040
+ "integrity": "sha512-J9xPx7YBkrRmJ+xl561ztnMWEc1aOyjEIxBiGX1dVb3u7bGSnfObfcZk+Pd+uM0HZAPNsQ1xvD8j52A/uOSqNQ==",7171041
"cpu": [7181042
"x64"7191043
],@@ -721,13 +1045,13 @@
7211045
"license": "MIT",7221046
"optional": true,7231047
"os": [724
- "linux"1048
+ "darwin"7251049
]7261050
},727
- "node_modules/@rollup/rollup-linux-x64-musl": {728
- "version": "4.63.4",729
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.63.4.tgz",730
- "integrity": "sha512-iwZQRcmj7g88g3tzefIrQY7qvmuA/cfYwhrDtTBhsmukO4U2huVO5W+86XacUMRvdSFVAc6kZUZy21JaRwiB9w==",1051
+ "node_modules/@oxc-resolver/binding-freebsd-x64": {1052
+ "version": "11.21.2",1053
+ "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-11.21.2.tgz",1054
+ "integrity": "sha512-fRlt7OvSaQkWj6+EDTVxawVxOlqJB2QSnBfkeCyK4RTvsGctbw3BiH2Tb7DzMs7bikc4BRBpvWP5zF9K8b54Zg==",7311055
"cpu": [7321056
"x64"7331057
],@@ -735,27 +1059,41 @@
7351059
"license": "MIT",7361060
"optional": true,7371061
"os": [1062
+ "freebsd"1063
+ ]1064
+ },1065
+ "node_modules/@oxc-resolver/binding-linux-arm-gnueabihf": {1066
+ "version": "11.21.2",1067
+ "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-11.21.2.tgz",1068
+ "integrity": "sha512-gK+vPUcPQITkGwBKpZGrcDHSlU6eDGl7AQacxS2CEKAZIBHWkOVFeJwLZ4tYnA1acJqRM5lt7yYwPCVqGHIJ7A==",1069
+ "cpu": [1070
+ "arm"1071
+ ],1072
+ "dev": true,1073
+ "license": "MIT",1074
+ "optional": true,1075
+ "os": [7381076
"linux"7391077
]7401078
},741
- "node_modules/@rollup/rollup-openbsd-x64": {742
- "version": "4.63.4",743
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.63.4.tgz",744
- "integrity": "sha512-dVHFp9gRWrdTpnqQuGfCwd7hOQDatK1VCP2iWhLY/cGrOQs/ucFzJ6A5SRqbXX12ZDI8EUuejSM5kwg+ja7Png==",1079
+ "node_modules/@oxc-resolver/binding-linux-arm-musleabihf": {1080
+ "version": "11.21.2",1081
+ "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-11.21.2.tgz",1082
+ "integrity": "sha512-L/Rgas7SrOKy/z7IH+HxSFRqVO4PuLDKLEGKvnhoCBBq3UJ0YzGBou3qMzaAGgkJwsIvX2pBF+7ojzfUhLiZxQ==",7451083
"cpu": [746
- "x64"1084
+ "arm"7471085
],7481086
"dev": true,7491087
"license": "MIT",7501088
"optional": true,7511089
"os": [752
- "openbsd"1090
+ "linux"7531091
]7541092
},755
- "node_modules/@rollup/rollup-openharmony-arm64": {756
- "version": "4.63.4",757
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.63.4.tgz",758
- "integrity": "sha512-t3NlauOW6gxZVVFcBEnO62Cb4wbyDFL416gTg1uFI/2tgqYQlf69FbSE115Ajre9I+c26Lk4mcmdFUsS/DGifQ==",1093
+ "node_modules/@oxc-resolver/binding-linux-arm64-gnu": {1094
+ "version": "11.21.2",1095
+ "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-11.21.2.tgz",1096
+ "integrity": "sha512-CUEYvlX1Fk7E9kUMzuswru1J9HLxMwnpDeQGjQuI4ZH+iNCoa2X9T+pvyzrbsgl7WnIeTFTlNlHsRfVdf5g9/g==",7591097
"cpu": [7601098
"arm64"7611099
],@@ -763,13 +1101,13 @@
7631101
"license": "MIT",7641102
"optional": true,7651103
"os": [766
- "openharmony"1104
+ "linux"7671105
]7681106
},769
- "node_modules/@rollup/rollup-win32-arm64-msvc": {770
- "version": "4.63.4",771
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.63.4.tgz",772
- "integrity": "sha512-xWuIaSye5FWZF8+UYtVEcHtRJDN5kN9Kfgxx3Kq8XIov9KSKbc1fiqQCm90SKrgQbUXZelbnUhnlUJmfSE7P9A==",1107
+ "node_modules/@oxc-resolver/binding-linux-arm64-musl": {1108
+ "version": "11.21.2",1109
+ "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-11.21.2.tgz",1110
+ "integrity": "sha512-ViN1ZibQyxwC67GpoP33oo+S9UyUnkog13vzQb9+v9bCNvrVzJuk0MRdacjtv/9xfRMVF/eqHFyl8YOeykI10Q==",7731111
"cpu": [7741112
"arm64"7751113
],@@ -777,27 +1115,69 @@
7771115
"license": "MIT",7781116
"optional": true,7791117
"os": [780
- "win32"1118
+ "linux"7811119
]7821120
},783
- "node_modules/@rollup/rollup-win32-ia32-msvc": {784
- "version": "4.63.4",785
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.63.4.tgz",786
- "integrity": "sha512-9ALJJUOg/ZflMJepVo2PlgsGxSaxN7SQ4Z8GoZfVlarWr6r3rkHUNsd/zAio7p4YMtChSMXPionxej4Hkf6CXQ==",1121
+ "node_modules/@oxc-resolver/binding-linux-ppc64-gnu": {1122
+ "version": "11.21.2",1123
+ "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-11.21.2.tgz",1124
+ "integrity": "sha512-CU1sCqWnhGqYD5I1HedHk5pujrn7ssDkNB/AEQd/pd3D/EojVSgJUlpbafwIbyhia3PgIfkvdFpRPWSALzVumA==",7871125
"cpu": [788
- "ia32"1126
+ "ppc64"7891127
],7901128
"dev": true,7911129
"license": "MIT",7921130
"optional": true,7931131
"os": [794
- "win32"1132
+ "linux"7951133
]7961134
},797
- "node_modules/@rollup/rollup-win32-x64-gnu": {798
- "version": "4.63.4",799
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.63.4.tgz",800
- "integrity": "sha512-blj9z5qx/Pv4WU0W1NMFDB97e0JH5ed+aZGywW8WCvp/NhWX/4PFAq5uu6Q0AebNn+Vo6KzUYDT++JzTT5ojlQ==",1135
+ "node_modules/@oxc-resolver/binding-linux-riscv64-gnu": {1136
+ "version": "11.21.2",1137
+ "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-11.21.2.tgz",1138
+ "integrity": "sha512-jWVyZtIHca4Gb96x7dag+y69vlei7ffjrsveLkmf2ZhqEAz6ZSBnY1GWvgZUaZlwZP62A3xD092BW97Q5VGc+g==",1139
+ "cpu": [1140
+ "riscv64"1141
+ ],1142
+ "dev": true,1143
+ "license": "MIT",1144
+ "optional": true,1145
+ "os": [1146
+ "linux"1147
+ ]1148
+ },1149
+ "node_modules/@oxc-resolver/binding-linux-riscv64-musl": {1150
+ "version": "11.21.2",1151
+ "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-11.21.2.tgz",1152
+ "integrity": "sha512-LF29obFqNgBUgDX7rmUK7M4D0JQG5LxhYzn3xXmECcHU9aQAdWG7NiY052qybtesEdwHQXKNTWYQ7mTsybNvWg==",1153
+ "cpu": [1154
+ "riscv64"1155
+ ],1156
+ "dev": true,1157
+ "license": "MIT",1158
+ "optional": true,1159
+ "os": [1160
+ "linux"1161
+ ]1162
+ },1163
+ "node_modules/@oxc-resolver/binding-linux-s390x-gnu": {1164
+ "version": "11.21.2",1165
+ "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-11.21.2.tgz",1166
+ "integrity": "sha512-+NYcm+cCHBbtdQQ3A4phQTSuVRYnNHz7wrl9XRAPEovcdoqi0mb1K5ZOl+jN54ZD+q1zz3V0vltbFJmzecJKmw==",1167
+ "cpu": [1168
+ "s390x"1169
+ ],1170
+ "dev": true,1171
+ "license": "MIT",1172
+ "optional": true,1173
+ "os": [1174
+ "linux"1175
+ ]1176
+ },1177
+ "node_modules/@oxc-resolver/binding-linux-x64-gnu": {1178
+ "version": "11.21.2",1179
+ "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-11.21.2.tgz",1180
+ "integrity": "sha512-UQqZDdG2r2HhAOsZEgufkIWHPQ886IUyuJQkoZByvzhW8j51R4UNzGBJFkTiTnLhQnggwJRdJgFWK4uY6ZVIMw==",8011181
"cpu": [8021182
"x64"8031183
],@@ -805,13 +1185,13 @@
8051185
"license": "MIT",8061186
"optional": true,8071187
"os": [808
- "win32"1188
+ "linux"8091189
]8101190
},811
- "node_modules/@rollup/rollup-win32-x64-msvc": {812
- "version": "4.63.4",813
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.63.4.tgz",814
- "integrity": "sha512-Erx822VRBwLa124shbj+wNXe//BOgMEctDV0m1aqTQdNO1S69DgNUCFKC1RCeZfixs1J31l6igk1ziyXErbigQ==",1191
+ "node_modules/@oxc-resolver/binding-linux-x64-musl": {1192
+ "version": "11.21.2",1193
+ "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-11.21.2.tgz",1194
+ "integrity": "sha512-3Q9PMRjalWkT6NZ4jfujuqTCFwoWErg3y3BnOgb544B8IMw4PktiwWOigMfOHNRLMghZeJ7hpfpZf4CP7rV7Og==",8151195
"cpu": [8161196
"x64"8171197
],@@ -819,141 +1199,2512 @@
8191199
"license": "MIT",8201200
"optional": true,8211201
"os": [822
- "win32"1202
+ "linux"8231203
]8241204
},825
- "node_modules/@sveltejs/vite-plugin-svelte": {826
- "version": "3.1.2",827
- "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-3.1.2.tgz",828
- "integrity": "sha512-Txsm1tJvtiYeLUVRNqxZGKR/mI+CzuIQuc2gn+YCs9rMTowpNZ2Nqt53JdL8KF9bLhAf2ruR/dr9eZCwdTriRA==",1205
+ "node_modules/@oxc-resolver/binding-openharmony-arm64": {1206
+ "version": "11.21.2",1207
+ "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-openharmony-arm64/-/binding-openharmony-arm64-11.21.2.tgz",1208
+ "integrity": "sha512-Eljeq3ndtyKhM+Es8LITi4Zl2htzuRZcrPMF3kMCsrILztvU6AjZ3FuEhHHKobPUB9rMpzLpJP5bDqXI7r+iog==",1209
+ "cpu": [1210
+ "arm64"1211
+ ],8291212
"dev": true,8301213
"license": "MIT",831
- "dependencies": {832
- "@sveltejs/vite-plugin-svelte-inspector": "^2.1.0",833
- "debug": "^4.3.4",834
- "deepmerge": "^4.3.1",835
- "kleur": "^4.1.5",836
- "magic-string": "^0.30.10",837
- "svelte-hmr": "^0.16.0",838
- "vitefu": "^0.2.5"839
- },840
- "engines": {841
- "node": "^18.0.0 || >=20"842
- },843
- "peerDependencies": {844
- "svelte": "^4.0.0 || ^5.0.0-next.0",845
- "vite": "^5.0.0"846
- }1214
+ "optional": true,1215
+ "os": [1216
+ "openharmony"1217
+ ]8471218
},848
- "node_modules/@sveltejs/vite-plugin-svelte-inspector": {849
- "version": "2.1.0",850
- "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-2.1.0.tgz",851
- "integrity": "sha512-9QX28IymvBlSCqsCll5t0kQVxipsfhFFL+L2t3nTWfXnddYwxBuAEtTtlaVQpRz9c37BhJjltSeY4AJSC03SSg==",1219
+ "node_modules/@oxc-resolver/binding-wasm32-wasi": {1220
+ "version": "11.21.2",1221
+ "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-11.21.2.tgz",1222
+ "integrity": "sha512-HGDbNsIywqc4LxU38+CTJNnB/6BF7rheWOJ259b4eE0aEnelYblC8x+1tEd63bp31fYne63RQz9Jb4yVnC7Yig==",1223
+ "cpu": [1224
+ "wasm32"1225
+ ],8521226
"dev": true,8531227
"license": "MIT",1228
+ "optional": true,8541229
"dependencies": {855
- "debug": "^4.3.4"1230
+ "@emnapi/core": "1.11.0",1231
+ "@emnapi/runtime": "1.11.0",1232
+ "@napi-rs/wasm-runtime": "^1.1.5"8561233
},8571234
"engines": {858
- "node": "^18.0.0 || >=20"859
- },860
- "peerDependencies": {861
- "@sveltejs/vite-plugin-svelte": "^3.0.0",862
- "svelte": "^4.0.0 || ^5.0.0-next.0",863
- "vite": "^5.0.0"1235
+ "node": ">=14.0.0"8641236
}8651237
},866
- "node_modules/@types/estree": {867
- "version": "1.0.9",868
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",869
- "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",870
- "license": "MIT"871
- },872
- "node_modules/acorn": {873
- "version": "8.18.0",874
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz",875
- "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==",1238
+ "node_modules/@oxc-resolver/binding-wasm32-wasi/node_modules/@emnapi/core": {1239
+ "version": "1.11.0",1240
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.0.tgz",1241
+ "integrity": "sha512-l9Oo58x0HOP5znGzVhYW9U3e5wVuA4LAZU2AGezTmkhO1CgQRFDhDg4nneHsu/t3WniXg9QrG2nIXL/ZS8ln8Q==",1242
+ "dev": true,8761243
"license": "MIT",877
- "bin": {878
- "acorn": "bin/acorn"879
- },880
- "engines": {881
- "node": ">=0.4.0"882
- }883
- },884
- "node_modules/aria-query": {885
- "version": "5.3.2",886
- "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",887
- "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",888
- "license": "Apache-2.0",889
- "engines": {890
- "node": ">= 0.4"891
- }892
- },893
- "node_modules/axobject-query": {894
- "version": "4.1.0",895
- "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",896
- "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",897
- "license": "Apache-2.0",898
- "engines": {899
- "node": ">= 0.4"1244
+ "optional": true,1245
+ "dependencies": {1246
+ "@emnapi/wasi-threads": "1.2.2",1247
+ "tslib": "^2.4.0"9001248
}9011249
},902
- "node_modules/code-red": {903
- "version": "1.0.4",904
- "resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.4.tgz",905
- "integrity": "sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==",1250
+ "node_modules/@oxc-resolver/binding-wasm32-wasi/node_modules/@emnapi/runtime": {1251
+ "version": "1.11.0",1252
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.0.tgz",1253
+ "integrity": "sha512-55coeOFKHv1ywEcUXJtWU5f+Jr/W5tZDvZig8DLKSwUN1JpROQ4rk/SNOQiFWmaR/VKF4zuFyW1B8JduOSv6Pg==",1254
+ "dev": true,9061255
"license": "MIT",1256
+ "optional": true,9071257
"dependencies": {908
- "@jridgewell/sourcemap-codec": "^1.4.15",909
- "@types/estree": "^1.0.1",910
- "acorn": "^8.10.0",911
- "estree-walker": "^3.0.3",912
- "periscopic": "^3.1.0"1258
+ "tslib": "^2.4.0"9131259
}9141260
},915
- "node_modules/css-tree": {916
- "version": "2.3.1",917
- "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",918
- "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",1261
+ "node_modules/@oxc-resolver/binding-wasm32-wasi/node_modules/@emnapi/wasi-threads": {1262
+ "version": "1.2.2",1263
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz",1264
+ "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==",1265
+ "dev": true,9191266
"license": "MIT",1267
+ "optional": true,9201268
"dependencies": {921
- "mdn-data": "2.0.30",922
- "source-map-js": "^1.0.1"923
- },924
- "engines": {925
- "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"1269
+ "tslib": "^2.4.0"9261270
}9271271
},928
- "node_modules/debug": {929
- "version": "4.4.3",930
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",931
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",1272
+ "node_modules/@oxc-resolver/binding-win32-arm64-msvc": {1273
+ "version": "11.21.2",1274
+ "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-11.21.2.tgz",1275
+ "integrity": "sha512-iWx25CBEgH49iE9q5coEGI/jb1jl5kkCY9z6U5Og67xCkQ/WFMDc2J5U78+AE91SUxM2NqSLhJC8/PLfWnImww==",1276
+ "cpu": [1277
+ "arm64"1278
+ ],9321279
"dev": true,9331280
"license": "MIT",934
- "dependencies": {1281
+ "optional": true,1282
+ "os": [1283
+ "win32"1284
+ ]1285
+ },1286
+ "node_modules/@oxc-resolver/binding-win32-x64-msvc": {1287
+ "version": "11.21.2",1288
+ "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-11.21.2.tgz",1289
+ "integrity": "sha512-VPoCAhKvCQTlG7vxqaBXcmuvbh77BfnGXj8g0pbvVXpm1F/R8rDVwqIWcEbMzrI1JvJlm8v7T9uMVQb6UctMRg==",1290
+ "cpu": [1291
+ "x64"1292
+ ],1293
+ "dev": true,1294
+ "license": "MIT",1295
+ "optional": true,1296
+ "os": [1297
+ "win32"1298
+ ]1299
+ },1300
+ "node_modules/@rollup/rollup-android-arm-eabi": {1301
+ "version": "4.64.2",1302
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.64.2.tgz",1303
+ "integrity": "sha512-gjNDUwMswogkw3fNqV00u54uZlgmInuw5EU/1TeqQ6K0bEagoGvqjPdKzy112lKyhe7PkGudZ/kSQHsc9qroIg==",1304
+ "cpu": [1305
+ "arm"1306
+ ],1307
+ "dev": true,1308
+ "license": "MIT",1309
+ "optional": true,1310
+ "os": [1311
+ "android"1312
+ ]1313
+ },1314
+ "node_modules/@rollup/rollup-android-arm64": {1315
+ "version": "4.64.2",1316
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.64.2.tgz",1317
+ "integrity": "sha512-YkAW8q7p5SCLSaGWaUkmsRnBEb3MGA1pB5nI/8k0lAK5fZsQKRBqkdR1h4UU9p8u3c7ZGdUF2Zcx7mK+E/pUKg==",1318
+ "cpu": [1319
+ "arm64"1320
+ ],1321
+ "dev": true,1322
+ "license": "MIT",1323
+ "optional": true,1324
+ "os": [1325
+ "android"1326
+ ]1327
+ },1328
+ "node_modules/@rollup/rollup-darwin-arm64": {1329
+ "version": "4.64.2",1330
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.64.2.tgz",1331
+ "integrity": "sha512-hNmuIHv+LnrP/+q/44vsmIMWfoh7X2YXOp5FLtjGuvqN52VdtFpOpnshTc1k28tWv1wE/0D5gLjsozBUowEGbQ==",1332
+ "cpu": [1333
+ "arm64"1334
+ ],1335
+ "dev": true,1336
+ "license": "MIT",1337
+ "optional": true,1338
+ "os": [1339
+ "darwin"1340
+ ]1341
+ },1342
+ "node_modules/@rollup/rollup-darwin-x64": {1343
+ "version": "4.64.2",1344
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.64.2.tgz",1345
+ "integrity": "sha512-B0t5CoxgF2KL7R5FHAsyN8yVEQCSIkh4XVs8MCDjuBLNjEa8l3zd5tVKaFMv53LfUtHs9p2rnqeavPTOunV+Ww==",1346
+ "cpu": [1347
+ "x64"1348
+ ],1349
+ "dev": true,1350
+ "license": "MIT",1351
+ "optional": true,1352
+ "os": [1353
+ "darwin"1354
+ ]1355
+ },1356
+ "node_modules/@rollup/rollup-freebsd-arm64": {1357
+ "version": "4.64.2",1358
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.64.2.tgz",1359
+ "integrity": "sha512-QQdYnfwrPmc1DoPlddjFvQPzUHFbStKXsHrG6EBYsWHhBVUCjsCRdcfGGXGAvhDpDtTzKK4vy1UrGFJ45rQaiw==",1360
+ "cpu": [1361
+ "arm64"1362
+ ],1363
+ "dev": true,1364
+ "license": "MIT",1365
+ "optional": true,1366
+ "os": [1367
+ "freebsd"1368
+ ]1369
+ },1370
+ "node_modules/@rollup/rollup-freebsd-x64": {1371
+ "version": "4.64.2",1372
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.64.2.tgz",1373
+ "integrity": "sha512-1xRxtGWif6BB58VSfMavi0Yfs2M4x6CtRp4o7ScY4W7AGlgvf6GSPKdDNdw7TX3tMiQwZY5W/mvyrOJTq/7AKA==",1374
+ "cpu": [1375
+ "x64"1376
+ ],1377
+ "dev": true,1378
+ "license": "MIT",1379
+ "optional": true,1380
+ "os": [1381
+ "freebsd"1382
+ ]1383
+ },1384
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {1385
+ "version": "4.64.2",1386
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.64.2.tgz",1387
+ "integrity": "sha512-CXFLEt384BUwwOLR9DURWNHl1bQOVLd1ibOee+yKBJm/fZtvrSAOZ0JbxjAxszVMIovYMwFMS+oP+Q1aPcx8Eg==",1388
+ "cpu": [1389
+ "arm"1390
+ ],1391
+ "dev": true,1392
+ "license": "MIT",1393
+ "optional": true,1394
+ "os": [1395
+ "linux"1396
+ ]1397
+ },1398
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {1399
+ "version": "4.64.2",1400
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.64.2.tgz",1401
+ "integrity": "sha512-T1dorY0WHm5mMNpMHFl5rYRZ02gLSZcr6J45r66tYb3S3R3DyIRGiGWVdLtF+zOQjratNJaObl9jYumueRiL1A==",1402
+ "cpu": [1403
+ "arm"1404
+ ],1405
+ "dev": true,1406
+ "license": "MIT",1407
+ "optional": true,1408
+ "os": [1409
+ "linux"1410
+ ]1411
+ },1412
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {1413
+ "version": "4.64.2",1414
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.64.2.tgz",1415
+ "integrity": "sha512-ia6bfaCIc0ldp6bvs9oEkFrJVJKNUMoiDF0+LBZsQAZg+vE0znXnzGqH+ew/FYswE30cruAWPTO3dPw7keaVkQ==",1416
+ "cpu": [1417
+ "arm64"1418
+ ],1419
+ "dev": true,1420
+ "license": "MIT",1421
+ "optional": true,1422
+ "os": [1423
+ "linux"1424
+ ]1425
+ },1426
+ "node_modules/@rollup/rollup-linux-arm64-musl": {1427
+ "version": "4.64.2",1428
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.64.2.tgz",1429
+ "integrity": "sha512-mB/gwfBfXtT0EBpbSssqKCqMFuX8b21Zy2TGoIhehSJEssZ5ksybxymwp1BkEM5Nczh/AAxpmh5q+MkhtundGg==",1430
+ "cpu": [1431
+ "arm64"1432
+ ],1433
+ "dev": true,1434
+ "license": "MIT",1435
+ "optional": true,1436
+ "os": [1437
+ "linux"1438
+ ]1439
+ },1440
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {1441
+ "version": "4.64.2",1442
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.64.2.tgz",1443
+ "integrity": "sha512-VPd0a+XlHoNRI9jIPRHww2UKhDkD6XjbtcKYXZijAnhJS1jLLbiNtVl6a5LyEfNN+eyiyWcJOZXPzBo69oTsew==",1444
+ "cpu": [1445
+ "loong64"1446
+ ],1447
+ "dev": true,1448
+ "license": "MIT",1449
+ "optional": true,1450
+ "os": [1451
+ "linux"1452
+ ]1453
+ },1454
+ "node_modules/@rollup/rollup-linux-loong64-musl": {1455
+ "version": "4.64.2",1456
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.64.2.tgz",1457
+ "integrity": "sha512-10N1I6oBpERqzGtHKcCLrEpHlbXSBbMK9TURHvqgWbIFZuU3oJROxJ0H2nHfq96TVI0XJHQ9qzolJMFd2tz0LA==",1458
+ "cpu": [1459
+ "loong64"1460
+ ],1461
+ "dev": true,1462
+ "license": "MIT",1463
+ "optional": true,1464
+ "os": [1465
+ "linux"1466
+ ]1467
+ },1468
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {1469
+ "version": "4.64.2",1470
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.64.2.tgz",1471
+ "integrity": "sha512-dhJrLVZ3wNNhwCmy9/VTg6Pq6J8a8eZ0n15dVRlbSWcDb+8V/1mDfbnvis+vt8W6Pbxzv6gUbTEl4piOT3bbUQ==",1472
+ "cpu": [1473
+ "ppc64"1474
+ ],1475
+ "dev": true,1476
+ "license": "MIT",1477
+ "optional": true,1478
+ "os": [1479
+ "linux"1480
+ ]1481
+ },1482
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {1483
+ "version": "4.64.2",1484
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.64.2.tgz",1485
+ "integrity": "sha512-tPd2QuwxkTxgju5eARyb3RdgBWWi/O9dn/NFH0VkvGbLzoQeXrH6qMABtW8IODb5lUeBzB3sy2U7qmI4MtQ72g==",1486
+ "cpu": [1487
+ "ppc64"1488
+ ],1489
+ "dev": true,1490
+ "license": "MIT",1491
+ "optional": true,1492
+ "os": [1493
+ "linux"1494
+ ]1495
+ },1496
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {1497
+ "version": "4.64.2",1498
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.64.2.tgz",1499
+ "integrity": "sha512-njtDdPvSQWI9CDhIPPxsiEMeHayCfu7wwcbSQ7c2kYPhGVviL+WGVhq6Jfj/b+VuhSTkFuQ0z4ZFbFjkWwBFmg==",1500
+ "cpu": [1501
+ "riscv64"1502
+ ],1503
+ "dev": true,1504
+ "license": "MIT",1505
+ "optional": true,1506
+ "os": [1507
+ "linux"1508
+ ]1509
+ },1510
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {1511
+ "version": "4.64.2",1512
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.64.2.tgz",1513
+ "integrity": "sha512-EbOBo3dqCj9ecEV9Z7zvulB6AieMP2ztnKQYGVOSN0pzIyOu+3JH2YJZnLmbPeVvfn6yP6Qi7NbBM27EzGbj2w==",1514
+ "cpu": [1515
+ "riscv64"1516
+ ],1517
+ "dev": true,1518
+ "license": "MIT",1519
+ "optional": true,1520
+ "os": [1521
+ "linux"1522
+ ]1523
+ },1524
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {1525
+ "version": "4.64.2",1526
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.64.2.tgz",1527
+ "integrity": "sha512-8wLt2Q5n4qmfiE2Gk8V6KNLSf+oJuBX7Kdw5joFDtnZIZvirS0hLzBc79OiJjV71oYDmBUZLNy6pDgvylo4qiQ==",1528
+ "cpu": [1529
+ "s390x"1530
+ ],1531
+ "dev": true,1532
+ "license": "MIT",1533
+ "optional": true,1534
+ "os": [1535
+ "linux"1536
+ ]1537
+ },1538
+ "node_modules/@rollup/rollup-linux-x64-gnu": {1539
+ "version": "4.64.2",1540
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.64.2.tgz",1541
+ "integrity": "sha512-aIChbkhC4d33bxkVP0LSi2/2lUSGRXE6k4Qa0G7tgpgTOK7kxHTixmx5qC3SKUJ6yUMznHBtQoWaG4QMqLUnhw==",1542
+ "cpu": [1543
+ "x64"1544
+ ],1545
+ "dev": true,1546
+ "license": "MIT",1547
+ "optional": true,1548
+ "os": [1549
+ "linux"1550
+ ]1551
+ },1552
+ "node_modules/@rollup/rollup-linux-x64-musl": {1553
+ "version": "4.64.2",1554
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.64.2.tgz",1555
+ "integrity": "sha512-gQ+TkVZRfjZVcl/UOAxxfWw+sHjzIXoieNwxEyJlD3tRBmBhR8ZDq11w+QEgQDcpslEB+fhN/OEpaTsDoIIHhQ==",1556
+ "cpu": [1557
+ "x64"1558
+ ],1559
+ "dev": true,1560
+ "license": "MIT",1561
+ "optional": true,1562
+ "os": [1563
+ "linux"1564
+ ]1565
+ },1566
+ "node_modules/@rollup/rollup-openbsd-x64": {1567
+ "version": "4.64.2",1568
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.64.2.tgz",1569
+ "integrity": "sha512-sUaJpMKS2JBCvUk8fYimG7aMq2jHVT4kw/uVHxPolKLrMmkKy0KXirmZyZehdNpL7PffqAlPAWUELQcTiD8ChA==",1570
+ "cpu": [1571
+ "x64"1572
+ ],1573
+ "dev": true,1574
+ "license": "MIT",1575
+ "optional": true,1576
+ "os": [1577
+ "openbsd"1578
+ ]1579
+ },1580
+ "node_modules/@rollup/rollup-openharmony-arm64": {1581
+ "version": "4.64.2",1582
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.64.2.tgz",1583
+ "integrity": "sha512-j1RdJWb0CrlSuwt12OPjLucPlwfLtA/KMOKVvh5rXSJEtl/WDoIGR3CSykK/jLGTo9RqNfW5Ub6kY5Z5ccYl9w==",1584
+ "cpu": [1585
+ "arm64"1586
+ ],1587
+ "dev": true,1588
+ "license": "MIT",1589
+ "optional": true,1590
+ "os": [1591
+ "openharmony"1592
+ ]1593
+ },1594
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {1595
+ "version": "4.64.2",1596
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.64.2.tgz",1597
+ "integrity": "sha512-i3r04aHCIY3eggTBLUp/4IxiBjDpAgQaK89Ue2nMJ2MKuIXX5JfoeZjHw+kPjGGNVDlhi8FT8xzuGMJZe3aehg==",1598
+ "cpu": [1599
+ "arm64"1600
+ ],1601
+ "dev": true,1602
+ "license": "MIT",1603
+ "optional": true,1604
+ "os": [1605
+ "win32"1606
+ ]1607
+ },1608
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {1609
+ "version": "4.64.2",1610
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.64.2.tgz",1611
+ "integrity": "sha512-kCQ15h/uwNMGdN8gjXBZGf+aGE+ODzHfbi90/cAm4+Q89WoMiLODNoj8HoGZmYx87HPxfu5CBNPsZ+ZG4uIAoA==",1612
+ "cpu": [1613
+ "ia32"1614
+ ],1615
+ "dev": true,1616
+ "license": "MIT",1617
+ "optional": true,1618
+ "os": [1619
+ "win32"1620
+ ]1621
+ },1622
+ "node_modules/@rollup/rollup-win32-x64-gnu": {1623
+ "version": "4.64.2",1624
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.64.2.tgz",1625
+ "integrity": "sha512-yYAuySSs+0X2gSMJPw/Q4jHsHZHyMq1dpAE+XnN790Jg1WuReUAD/+j+e4vuDvS4PXJ4PA4NCzTR4OYtDf18/g==",1626
+ "cpu": [1627
+ "x64"1628
+ ],1629
+ "dev": true,1630
+ "license": "MIT",1631
+ "optional": true,1632
+ "os": [1633
+ "win32"1634
+ ]1635
+ },1636
+ "node_modules/@rollup/rollup-win32-x64-msvc": {1637
+ "version": "4.64.2",1638
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.64.2.tgz",1639
+ "integrity": "sha512-JY1rQdWOJrKutORqKO1uzrHXV86jFiQzfLFKx2s8S1CjLXL9fC5LOIvk0q7Z7PXJvsByt+sdoE1Q2a9gBr4gLQ==",1640
+ "cpu": [1641
+ "x64"1642
+ ],1643
+ "dev": true,1644
+ "license": "MIT",1645
+ "optional": true,1646
+ "os": [1647
+ "win32"1648
+ ]1649
+ },1650
+ "node_modules/@standard-schema/spec": {1651
+ "version": "1.1.0",1652
+ "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",1653
+ "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",1654
+ "dev": true,1655
+ "license": "MIT"1656
+ },1657
+ "node_modules/@storybook/addon-docs": {1658
+ "version": "10.6.1",1659
+ "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-10.6.1.tgz",1660
+ "integrity": "sha512-31PXR+MCWfI5YHKKah6tWnbV1FJWA9qbTHxtvpszPLd8FBekXtPOnmyYOpFF9CfciBF9bkeJFdFanJvUCjWbjA==",1661
+ "dev": true,1662
+ "license": "MIT",1663
+ "dependencies": {1664
+ "@mdx-js/react": "^3.0.0",1665
+ "@storybook/icons": "^2.0.2",1666
+ "@storybook/react-dom-shim": "10.6.1",1667
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",1668
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",1669
+ "ts-dedent": "^2.0.0",1670
+ "unplugin": "^2.3.5"1671
+ },1672
+ "funding": {1673
+ "type": "opencollective",1674
+ "url": "https://opencollective.com/storybook"1675
+ },1676
+ "peerDependencies": {1677
+ "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",1678
+ "storybook": "^10.6.1"1679
+ },1680
+ "peerDependenciesMeta": {1681
+ "@types/react": {1682
+ "optional": true1683
+ }1684
+ }1685
+ },1686
+ "node_modules/@storybook/addon-mcp": {1687
+ "version": "10.6.1",1688
+ "resolved": "https://registry.npmjs.org/@storybook/addon-mcp/-/addon-mcp-10.6.1.tgz",1689
+ "integrity": "sha512-ILh1wAI/3SgkkjRi4lZRXwT1jq6gEGEjDed5Z2Gd6ykO3yfLX2QnBM3UG2FSDv+uMKyxv8P80uXRDgKUhtmcOQ==",1690
+ "dev": true,1691
+ "license": "MIT",1692
+ "dependencies": {1693
+ "@tmcp/adapter-valibot": "^0.1.5",1694
+ "@tmcp/transport-http": "^0.8.5",1695
+ "tmcp": "^1.19.4",1696
+ "valibot": "^1.4.0"1697
+ },1698
+ "funding": {1699
+ "type": "opencollective",1700
+ "url": "https://opencollective.com/storybook"1701
+ },1702
+ "peerDependencies": {1703
+ "@storybook/addon-vitest": "^10.6.1",1704
+ "storybook": "^10.6.1"1705
+ },1706
+ "peerDependenciesMeta": {1707
+ "@storybook/addon-vitest": {1708
+ "optional": true1709
+ }1710
+ }1711
+ },1712
+ "node_modules/@storybook/builder-vite": {1713
+ "version": "10.6.1",1714
+ "resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-10.6.1.tgz",1715
+ "integrity": "sha512-kUMRRRS4MpJdxOLhrlQX3cpMYi2vVB3tIIRXyqWmAjVM6xT7OZ1SCQEMFPP+S3ToRqaYWZQb8aBqrJucbbYufA==",1716
+ "dev": true,1717
+ "license": "MIT",1718
+ "dependencies": {1719
+ "ts-dedent": "^2.0.0"1720
+ },1721
+ "funding": {1722
+ "type": "opencollective",1723
+ "url": "https://opencollective.com/storybook"1724
+ },1725
+ "peerDependencies": {1726
+ "storybook": "^10.6.1",1727
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"1728
+ }1729
+ },1730
+ "node_modules/@storybook/global": {1731
+ "version": "5.0.0",1732
+ "resolved": "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz",1733
+ "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==",1734
+ "dev": true,1735
+ "license": "MIT"1736
+ },1737
+ "node_modules/@storybook/icons": {1738
+ "version": "2.1.0",1739
+ "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-2.1.0.tgz",1740
+ "integrity": "sha512-Fxh9vYpX9bQqFeHRiY8h2ApeRGDzRSMLwJwNZ/AIRqnyOKHxRKL+yFe+ctEkVJmuptRE9u1Hrn8ZZNHyfDKKNg==",1741
+ "dev": true,1742
+ "license": "MIT",1743
+ "peerDependencies": {1744
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"1745
+ }1746
+ },1747
+ "node_modules/@storybook/react-dom-shim": {1748
+ "version": "10.6.1",1749
+ "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-10.6.1.tgz",1750
+ "integrity": "sha512-OkPFycR6kVE+9ZsgQWRqnUfZm/sLY6dxsNAn3lsvV7DSAQWH9QnHLkqP9E/N/Hg6cKPDtGzDZ8vPNDz2FuaDuQ==",1751
+ "dev": true,1752
+ "license": "MIT",1753
+ "funding": {1754
+ "type": "opencollective",1755
+ "url": "https://opencollective.com/storybook"1756
+ },1757
+ "peerDependencies": {1758
+ "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",1759
+ "@types/react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",1760
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",1761
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",1762
+ "storybook": "^10.6.1"1763
+ },1764
+ "peerDependenciesMeta": {1765
+ "@types/react": {1766
+ "optional": true1767
+ },1768
+ "@types/react-dom": {1769
+ "optional": true1770
+ }1771
+ }1772
+ },1773
+ "node_modules/@storybook/svelte": {1774
+ "version": "10.6.1",1775
+ "resolved": "https://registry.npmjs.org/@storybook/svelte/-/svelte-10.6.1.tgz",1776
+ "integrity": "sha512-r4mH9gX2unus6IpBVAt5b9Q50SgoT2fMX+NmLoZ3WwTFwIfgWHV7aOYEZgJsk61KEFwUFtJp2il2nI67O3G8Xw==",1777
+ "dev": true,1778
+ "license": "MIT",1779
+ "dependencies": {1780
+ "ts-dedent": "^2.0.0",1781
+ "type-fest": "^5.6.0"1782
+ },1783
+ "funding": {1784
+ "type": "opencollective",1785
+ "url": "https://opencollective.com/storybook"1786
+ },1787
+ "peerDependencies": {1788
+ "storybook": "^10.6.1",1789
+ "svelte": "^5.0.0"1790
+ }1791
+ },1792
+ "node_modules/@storybook/svelte-vite": {1793
+ "version": "10.6.1",1794
+ "resolved": "https://registry.npmjs.org/@storybook/svelte-vite/-/svelte-vite-10.6.1.tgz",1795
+ "integrity": "sha512-xyA3EjKdW0gK7mM97pJSzdI3lkbjLzE6MZ3hBLWZtGBxl8UjpYeKwyi9AKvmiMaDoF646mFw0HJo0lSGrFmFDw==",1796
+ "dev": true,1797
+ "license": "MIT",1798
+ "dependencies": {1799
+ "@storybook/builder-vite": "10.6.1",1800
+ "@storybook/svelte": "10.6.1",1801
+ "magic-string": "^1.1.0",1802
+ "svelte2tsx": "^0.7.55",1803
+ "typescript": "^4.9.4 || ^5.0.0"1804
+ },1805
+ "funding": {1806
+ "type": "opencollective",1807
+ "url": "https://opencollective.com/storybook"1808
+ },1809
+ "peerDependencies": {1810
+ "@sveltejs/vite-plugin-svelte": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0",1811
+ "storybook": "^10.6.1",1812
+ "svelte": "^5.0.0",1813
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"1814
+ }1815
+ },1816
+ "node_modules/@storybook/svelte-vite/node_modules/typescript": {1817
+ "version": "5.9.3",1818
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",1819
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",1820
+ "dev": true,1821
+ "license": "Apache-2.0",1822
+ "bin": {1823
+ "tsc": "bin/tsc",1824
+ "tsserver": "bin/tsserver"1825
+ },1826
+ "engines": {1827
+ "node": ">=14.17"1828
+ }1829
+ },1830
+ "node_modules/@sveltejs/acorn-typescript": {1831
+ "version": "1.0.13",1832
+ "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.13.tgz",1833
+ "integrity": "sha512-wgKggnhZVL9Bfx1OaKKTrYY9BFRk6C8UAkQNUcIv1+llzYrIqy+RZm5HPKzn0NpEBvTVhTqB4kQyllZywsRBRQ==",1834
+ "license": "MIT",1835
+ "peerDependencies": {1836
+ "acorn": "^8.9.0"1837
+ }1838
+ },1839
+ "node_modules/@sveltejs/vite-plugin-svelte": {1840
+ "version": "4.0.4",1841
+ "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-4.0.4.tgz",1842
+ "integrity": "sha512-0ba1RQ/PHen5FGpdSrW7Y3fAMQjrXantECALeOiOdBdzR5+5vPP6HVZRLmZaQL+W8m++o+haIAKq5qT+MiZ7VA==",1843
+ "dev": true,1844
+ "license": "MIT",1845
+ "dependencies": {1846
+ "@sveltejs/vite-plugin-svelte-inspector": "^3.0.0-next.0||^3.0.0",1847
+ "debug": "^4.3.7",1848
+ "deepmerge": "^4.3.1",1849
+ "kleur": "^4.1.5",1850
+ "magic-string": "^0.30.12",1851
+ "vitefu": "^1.0.3"1852
+ },1853
+ "engines": {1854
+ "node": "^18.0.0 || ^20.0.0 || >=22"1855
+ },1856
+ "peerDependencies": {1857
+ "svelte": "^5.0.0-next.96 || ^5.0.0",1858
+ "vite": "^5.0.0"1859
+ }1860
+ },1861
+ "node_modules/@sveltejs/vite-plugin-svelte-inspector": {1862
+ "version": "3.0.1",1863
+ "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-3.0.1.tgz",1864
+ "integrity": "sha512-2CKypmj1sM4GE7HjllT7UKmo4Q6L5xFRd7VMGEWhYnZ+wc6AUVU01IBd7yUi6WnFndEwWoMNOd6e8UjoN0nbvQ==",1865
+ "dev": true,1866
+ "license": "MIT",1867
+ "dependencies": {1868
+ "debug": "^4.3.7"1869
+ },1870
+ "engines": {1871
+ "node": "^18.0.0 || ^20.0.0 || >=22"1872
+ },1873
+ "peerDependencies": {1874
+ "@sveltejs/vite-plugin-svelte": "^4.0.0-next.0||^4.0.0",1875
+ "svelte": "^5.0.0-next.96 || ^5.0.0",1876
+ "vite": "^5.0.0"1877
+ }1878
+ },1879
+ "node_modules/@sveltejs/vite-plugin-svelte/node_modules/magic-string": {1880
+ "version": "0.30.21",1881
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",1882
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",1883
+ "dev": true,1884
+ "license": "MIT",1885
+ "dependencies": {1886
+ "@jridgewell/sourcemap-codec": "^1.5.5"1887
+ }1888
+ },1889
+ "node_modules/@testing-library/dom": {1890
+ "version": "10.4.2",1891
+ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.2.tgz",1892
+ "integrity": "sha512-yzr2S9HyAIdhz2/6qHgbs665Q7PKVcDF05vsOlHPxG1mo36gKVesdYVeDLnXgfjJ03CrKRk08knc6+E/9m8v2Q==",1893
+ "dev": true,1894
+ "license": "MIT",1895
+ "dependencies": {1896
+ "@babel/code-frame": "^7.10.4",1897
+ "@babel/runtime": "^7.12.5",1898
+ "@types/aria-query": "^5.0.1",1899
+ "aria-query": "5.3.0",1900
+ "dom-accessibility-api": "^0.5.9",1901
+ "lz-string": "^1.5.0",1902
+ "picocolors": "1.1.1",1903
+ "pretty-format": "^27.0.2"1904
+ },1905
+ "engines": {1906
+ "node": ">=18"1907
+ }1908
+ },1909
+ "node_modules/@testing-library/jest-dom": {1910
+ "version": "6.9.1",1911
+ "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz",1912
+ "integrity": "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==",1913
+ "dev": true,1914
+ "license": "MIT",1915
+ "dependencies": {1916
+ "@adobe/css-tools": "^4.4.0",1917
+ "aria-query": "^5.0.0",1918
+ "css.escape": "^1.5.1",1919
+ "dom-accessibility-api": "^0.6.3",1920
+ "picocolors": "^1.1.1",1921
+ "redent": "^3.0.0"1922
+ },1923
+ "engines": {1924
+ "node": ">=14",1925
+ "npm": ">=6",1926
+ "yarn": ">=1"1927
+ }1928
+ },1929
+ "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": {1930
+ "version": "0.6.3",1931
+ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz",1932
+ "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==",1933
+ "dev": true,1934
+ "license": "MIT"1935
+ },1936
+ "node_modules/@testing-library/user-event": {1937
+ "version": "14.6.7",1938
+ "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.7.tgz",1939
+ "integrity": "sha512-MPCpX8bxe8zS+JmmTwLp8jd0dy1rAm60Te/SL8JrQM3qvQJcBOs1d7IefJMyZzqM3EWBrDn/LWDt1BCGu4ASfg==",1940
+ "dev": true,1941
+ "license": "MIT",1942
+ "engines": {1943
+ "node": ">=12",1944
+ "npm": ">=6"1945
+ },1946
+ "peerDependencies": {1947
+ "@testing-library/dom": ">=7.21.4"1948
+ }1949
+ },1950
+ "node_modules/@tmcp/adapter-valibot": {1951
+ "version": "0.1.6",1952
+ "resolved": "https://registry.npmjs.org/@tmcp/adapter-valibot/-/adapter-valibot-0.1.6.tgz",1953
+ "integrity": "sha512-drirZeNinhYLiRSMksN+m//u0ImFxtGRk1Vp425Xp/7CbBXFQdjAG+f7grssyHAukbVTGzmWsMMP6ejrGVErUA==",1954
+ "dev": true,1955
+ "license": "MIT",1956
+ "dependencies": {1957
+ "@standard-schema/spec": "^1.0.0",1958
+ "@valibot/to-json-schema": "^1.3.0",1959
+ "valibot": "^1.1.0"1960
+ },1961
+ "peerDependencies": {1962
+ "tmcp": "^1.17.0",1963
+ "valibot": "^1.1.0"1964
+ }1965
+ },1966
+ "node_modules/@tmcp/session-manager": {1967
+ "version": "0.2.2",1968
+ "resolved": "https://registry.npmjs.org/@tmcp/session-manager/-/session-manager-0.2.2.tgz",1969
+ "integrity": "sha512-UrCRpTsxh5XnMbplspvftEYboiZWgAiXqqAUbyFTHoHMJ0LoNDy8bQd0+7qtxtT4S5Qsnv650gvs/Nbec5NTCQ==",1970
+ "dev": true,1971
+ "license": "MIT",1972
+ "peerDependencies": {1973
+ "tmcp": "^1.16.3"1974
+ }1975
+ },1976
+ "node_modules/@tmcp/transport-http": {1977
+ "version": "0.8.6",1978
+ "resolved": "https://registry.npmjs.org/@tmcp/transport-http/-/transport-http-0.8.6.tgz",1979
+ "integrity": "sha512-iLcxu+tEMbkVHbhFfyXQhxfPDDTfm+F0kEw8Xg/a1rm29s4cBg1vwcpbtk02XTxsdDh8RJ1AZkQwF9WDGeb/IA==",1980
+ "dev": true,1981
+ "license": "MIT",1982
+ "dependencies": {1983
+ "@tmcp/session-manager": "^0.2.2",1984
+ "esm-env": "^1.2.2"1985
+ },1986
+ "peerDependencies": {1987
+ "@tmcp/auth": "^0.3.3 || ^0.4.0",1988
+ "tmcp": "^1.18.0"1989
+ },1990
+ "peerDependenciesMeta": {1991
+ "@tmcp/auth": {1992
+ "optional": true1993
+ }1994
+ }1995
+ },1996
+ "node_modules/@tybys/wasm-util": {1997
+ "version": "0.10.4",1998
+ "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.4.tgz",1999
+ "integrity": "sha512-W3c4gRigFS0T/Ma4qIYF3GDAc5AQdHb1yL5znJT1Zv1YaD9Kitx656wBjvr19qbiosmZT8lWDM5BEMynUqX65A==",2000
+ "dev": true,2001
+ "license": "MIT",2002
+ "optional": true,2003
+ "dependencies": {2004
+ "tslib": "^2.4.0"2005
+ }2006
+ },2007
+ "node_modules/@types/aria-query": {2008
+ "version": "5.0.4",2009
+ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",2010
+ "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",2011
+ "dev": true,2012
+ "license": "MIT"2013
+ },2014
+ "node_modules/@types/chai": {2015
+ "version": "5.2.3",2016
+ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz",2017
+ "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==",2018
+ "dev": true,2019
+ "license": "MIT",2020
+ "dependencies": {2021
+ "@types/deep-eql": "*",2022
+ "assertion-error": "^2.0.1"2023
+ }2024
+ },2025
+ "node_modules/@types/deep-eql": {2026
+ "version": "4.0.2",2027
+ "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz",2028
+ "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==",2029
+ "dev": true,2030
+ "license": "MIT"2031
+ },2032
+ "node_modules/@types/estree": {2033
+ "version": "1.0.9",2034
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",2035
+ "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",2036
+ "license": "MIT"2037
+ },2038
+ "node_modules/@types/mdx": {2039
+ "version": "2.0.14",2040
+ "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.14.tgz",2041
+ "integrity": "sha512-T48PeuJtvLosNTPVhfnIp3i/n3a4g4Bad7YCq5k64D4u7NwDrAotikQ+5+sjtUvBmxCMlbo3dVL+C2dP0rWHzg==",2042
+ "dev": true,2043
+ "license": "MIT"2044
+ },2045
+ "node_modules/@types/react": {2046
+ "version": "19.3.0",2047
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.3.0.tgz",2048
+ "integrity": "sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==",2049
+ "dev": true,2050
+ "license": "MIT",2051
+ "peer": true,2052
+ "dependencies": {2053
+ "csstype": "^3.2.2"2054
+ }2055
+ },2056
+ "node_modules/@valibot/to-json-schema": {2057
+ "version": "1.8.0",2058
+ "resolved": "https://registry.npmjs.org/@valibot/to-json-schema/-/to-json-schema-1.8.0.tgz",2059
+ "integrity": "sha512-a0M+uwCuQZEPAo65NYkFSJ14O5c213KoSZmPdoCfuFvUhfULi4T2Z6Tpjv6lTVMW9RoLm74RpRAjNEa43KcN+g==",2060
+ "dev": true,2061
+ "license": "MIT",2062
+ "peerDependencies": {2063
+ "valibot": "^1.5.0"2064
+ }2065
+ },2066
+ "node_modules/@vitest/expect": {2067
+ "version": "3.2.4",2068
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz",2069
+ "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==",2070
+ "dev": true,2071
+ "license": "MIT",2072
+ "dependencies": {2073
+ "@types/chai": "^5.2.2",2074
+ "@vitest/spy": "3.2.4",2075
+ "@vitest/utils": "3.2.4",2076
+ "chai": "^5.2.0",2077
+ "tinyrainbow": "^2.0.0"2078
+ },2079
+ "funding": {2080
+ "url": "https://opencollective.com/vitest"2081
+ }2082
+ },2083
+ "node_modules/@vitest/pretty-format": {2084
+ "version": "3.2.4",2085
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz",2086
+ "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==",2087
+ "dev": true,2088
+ "license": "MIT",2089
+ "dependencies": {2090
+ "tinyrainbow": "^2.0.0"2091
+ },2092
+ "funding": {2093
+ "url": "https://opencollective.com/vitest"2094
+ }2095
+ },2096
+ "node_modules/@vitest/spy": {2097
+ "version": "3.2.4",2098
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz",2099
+ "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==",2100
+ "dev": true,2101
+ "license": "MIT",2102
+ "dependencies": {2103
+ "tinyspy": "^4.0.3"2104
+ },2105
+ "funding": {2106
+ "url": "https://opencollective.com/vitest"2107
+ }2108
+ },2109
+ "node_modules/@vitest/utils": {2110
+ "version": "3.2.4",2111
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz",2112
+ "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==",2113
+ "dev": true,2114
+ "license": "MIT",2115
+ "dependencies": {2116
+ "@vitest/pretty-format": "3.2.4",2117
+ "loupe": "^3.1.4",2118
+ "tinyrainbow": "^2.0.0"2119
+ },2120
+ "funding": {2121
+ "url": "https://opencollective.com/vitest"2122
+ }2123
+ },2124
+ "node_modules/@webcontainer/env": {2125
+ "version": "1.1.1",2126
+ "resolved": "https://registry.npmjs.org/@webcontainer/env/-/env-1.1.1.tgz",2127
+ "integrity": "sha512-6aN99yL695Hi9SuIk1oC88l9o0gmxL1nGWWQ/kNy81HigJ0FoaoTXpytCj6ItzgyCEwA9kF1wixsTuv5cjsgng==",2128
+ "dev": true,2129
+ "license": "MIT"2130
+ },2131
+ "node_modules/acorn": {2132
+ "version": "8.19.0",2133
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.19.0.tgz",2134
+ "integrity": "sha512-oJlA3XiRm7Cyk6qFD2Jn8ak9B7jSy0qy00ADO3+8dpT0LSjFihQYv4C02LFCSYJV3Q37xYwwRy5m+IpIiUzqWw==",2135
+ "license": "MIT",2136
+ "bin": {2137
+ "acorn": "bin/acorn"2138
+ },2139
+ "engines": {2140
+ "node": ">=0.4.0"2141
+ }2142
+ },2143
+ "node_modules/ansi-regex": {2144
+ "version": "5.0.1",2145
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",2146
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",2147
+ "dev": true,2148
+ "license": "MIT",2149
+ "engines": {2150
+ "node": ">=8"2151
+ }2152
+ },2153
+ "node_modules/ansi-styles": {2154
+ "version": "5.2.0",2155
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",2156
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",2157
+ "dev": true,2158
+ "license": "MIT",2159
+ "engines": {2160
+ "node": ">=10"2161
+ },2162
+ "funding": {2163
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"2164
+ }2165
+ },2166
+ "node_modules/aria-query": {2167
+ "version": "5.3.0",2168
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",2169
+ "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",2170
+ "dev": true,2171
+ "license": "Apache-2.0",2172
+ "dependencies": {2173
+ "dequal": "^2.0.3"2174
+ }2175
+ },2176
+ "node_modules/assertion-error": {2177
+ "version": "2.0.1",2178
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",2179
+ "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",2180
+ "dev": true,2181
+ "license": "MIT",2182
+ "engines": {2183
+ "node": ">=12"2184
+ }2185
+ },2186
+ "node_modules/ast-types": {2187
+ "version": "0.16.3",2188
+ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.3.tgz",2189
+ "integrity": "sha512-FvWoWYfSCM6kRxCSH+MGLHIKKGRL6A6AW7Zek2O32REPQRdg131428uRTKMBYAeRd3XXAaHDS60Wpri7CdKDrA==",2190
+ "dev": true,2191
+ "license": "MIT",2192
+ "dependencies": {2193
+ "tslib": "^2.0.1"2194
+ },2195
+ "engines": {2196
+ "node": ">=4"2197
+ }2198
+ },2199
+ "node_modules/axobject-query": {2200
+ "version": "4.1.0",2201
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",2202
+ "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",2203
+ "license": "Apache-2.0",2204
+ "engines": {2205
+ "node": ">= 0.4"2206
+ }2207
+ },2208
+ "node_modules/bundle-name": {2209
+ "version": "4.1.1",2210
+ "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.1.tgz",2211
+ "integrity": "sha512-DdH81/zPLVS11EUgWq3tEu/xn+EzljlMYooDNdzWEnFha3R3NBMpMV1UqYIpjYHV/SgpFKMIX1Oh7o06SjM/oA==",2212
+ "dev": true,2213
+ "license": "MIT",2214
+ "dependencies": {2215
+ "run-applescript": "^7.0.0"2216
+ },2217
+ "engines": {2218
+ "node": ">=18"2219
+ },2220
+ "funding": {2221
+ "url": "https://github.com/sponsors/sindresorhus"2222
+ }2223
+ },2224
+ "node_modules/chai": {2225
+ "version": "5.3.3",2226
+ "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz",2227
+ "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==",2228
+ "dev": true,2229
+ "license": "MIT",2230
+ "dependencies": {2231
+ "assertion-error": "^2.0.1",2232
+ "check-error": "^2.1.1",2233
+ "deep-eql": "^5.0.1",2234
+ "loupe": "^3.1.0",2235
+ "pathval": "^2.0.0"2236
+ },2237
+ "engines": {2238
+ "node": ">=18"2239
+ }2240
+ },2241
+ "node_modules/check-error": {2242
+ "version": "2.1.3",2243
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz",2244
+ "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==",2245
+ "dev": true,2246
+ "license": "MIT",2247
+ "engines": {2248
+ "node": ">= 16"2249
+ }2250
+ },2251
+ "node_modules/clsx": {2252
+ "version": "2.1.1",2253
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",2254
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",2255
+ "license": "MIT",2256
+ "engines": {2257
+ "node": ">=6"2258
+ }2259
+ },2260
+ "node_modules/css.escape": {2261
+ "version": "1.5.1",2262
+ "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",2263
+ "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==",2264
+ "dev": true,2265
+ "license": "MIT"2266
+ },2267
+ "node_modules/csstype": {2268
+ "version": "3.2.3",2269
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",2270
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",2271
+ "dev": true,2272
+ "license": "MIT",2273
+ "peer": true2274
+ },2275
+ "node_modules/debug": {2276
+ "version": "4.4.3",2277
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",2278
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",2279
+ "dev": true,2280
+ "license": "MIT",2281
+ "dependencies": {9352282
"ms": "^2.1.3"9362283
},9372284
"engines": {938
- "node": ">=6.0"939
- },940
- "peerDependenciesMeta": {941
- "supports-color": {942
- "optional": true943
- }2285
+ "node": ">=6.0"2286
+ },2287
+ "peerDependenciesMeta": {2288
+ "supports-color": {2289
+ "optional": true2290
+ }2291
+ }2292
+ },2293
+ "node_modules/dedent-js": {2294
+ "version": "1.0.1",2295
+ "resolved": "https://registry.npmjs.org/dedent-js/-/dedent-js-1.0.1.tgz",2296
+ "integrity": "sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==",2297
+ "dev": true,2298
+ "license": "MIT"2299
+ },2300
+ "node_modules/deep-eql": {2301
+ "version": "5.0.2",2302
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",2303
+ "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",2304
+ "dev": true,2305
+ "license": "MIT",2306
+ "engines": {2307
+ "node": ">=6"2308
+ }2309
+ },2310
+ "node_modules/deepmerge": {2311
+ "version": "4.3.1",2312
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",2313
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",2314
+ "dev": true,2315
+ "license": "MIT",2316
+ "engines": {2317
+ "node": ">=0.10.0"2318
+ }2319
+ },2320
+ "node_modules/default-browser": {2321
+ "version": "5.5.1",2322
+ "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.1.tgz",2323
+ "integrity": "sha512-m1pAzaJgZ/gssEqlOhJkPJp8Xly7QyW6xcrkUa2KKcDeDSEMP7X8xipU3snUcfisTQx0w1AGae+9UtJSfVnXGw==",2324
+ "dev": true,2325
+ "license": "MIT",2326
+ "dependencies": {2327
+ "bundle-name": "^4.1.0",2328
+ "default-browser-id": "^5.0.0"2329
+ },2330
+ "engines": {2331
+ "node": ">=18"2332
+ },2333
+ "funding": {2334
+ "url": "https://github.com/sponsors/sindresorhus"2335
+ }2336
+ },2337
+ "node_modules/default-browser-id": {2338
+ "version": "5.0.1",2339
+ "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz",2340
+ "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==",2341
+ "dev": true,2342
+ "license": "MIT",2343
+ "engines": {2344
+ "node": ">=18"2345
+ },2346
+ "funding": {2347
+ "url": "https://github.com/sponsors/sindresorhus"2348
+ }2349
+ },2350
+ "node_modules/define-lazy-prop": {2351
+ "version": "3.0.0",2352
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",2353
+ "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",2354
+ "dev": true,2355
+ "license": "MIT",2356
+ "engines": {2357
+ "node": ">=12"2358
+ },2359
+ "funding": {2360
+ "url": "https://github.com/sponsors/sindresorhus"2361
+ }2362
+ },2363
+ "node_modules/dequal": {2364
+ "version": "2.0.3",2365
+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",2366
+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",2367
+ "dev": true,2368
+ "license": "MIT",2369
+ "engines": {2370
+ "node": ">=6"2371
+ }2372
+ },2373
+ "node_modules/devalue": {2374
+ "version": "5.9.4",2375
+ "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.9.4.tgz",2376
+ "integrity": "sha512-sPAT4pztbu6586/hrhOnMKS17IJrvg12mXiSPSS3W5qDeN2RGgvZ0diZCm31dBbnevfVmujNO3IM2wrS4Y2Rhg==",2377
+ "license": "MIT"2378
+ },2379
+ "node_modules/dom-accessibility-api": {2380
+ "version": "0.5.16",2381
+ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",2382
+ "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",2383
+ "dev": true,2384
+ "license": "MIT"2385
+ },2386
+ "node_modules/esbuild": {2387
+ "version": "0.28.2",2388
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz",2389
+ "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==",2390
+ "dev": true,2391
+ "hasInstallScript": true,2392
+ "license": "MIT",2393
+ "bin": {2394
+ "esbuild": "bin/esbuild"2395
+ },2396
+ "engines": {2397
+ "node": ">=18"2398
+ },2399
+ "optionalDependencies": {2400
+ "@esbuild/aix-ppc64": "0.28.2",2401
+ "@esbuild/android-arm": "0.28.2",2402
+ "@esbuild/android-arm64": "0.28.2",2403
+ "@esbuild/android-x64": "0.28.2",2404
+ "@esbuild/darwin-arm64": "0.28.2",2405
+ "@esbuild/darwin-x64": "0.28.2",2406
+ "@esbuild/freebsd-arm64": "0.28.2",2407
+ "@esbuild/freebsd-x64": "0.28.2",2408
+ "@esbuild/linux-arm": "0.28.2",2409
+ "@esbuild/linux-arm64": "0.28.2",2410
+ "@esbuild/linux-ia32": "0.28.2",2411
+ "@esbuild/linux-loong64": "0.28.2",2412
+ "@esbuild/linux-mips64el": "0.28.2",2413
+ "@esbuild/linux-ppc64": "0.28.2",2414
+ "@esbuild/linux-riscv64": "0.28.2",2415
+ "@esbuild/linux-s390x": "0.28.2",2416
+ "@esbuild/linux-x64": "0.28.2",2417
+ "@esbuild/netbsd-arm64": "0.28.2",2418
+ "@esbuild/netbsd-x64": "0.28.2",2419
+ "@esbuild/openbsd-arm64": "0.28.2",2420
+ "@esbuild/openbsd-x64": "0.28.2",2421
+ "@esbuild/openharmony-arm64": "0.28.2",2422
+ "@esbuild/sunos-x64": "0.28.2",2423
+ "@esbuild/win32-arm64": "0.28.2",2424
+ "@esbuild/win32-ia32": "0.28.2",2425
+ "@esbuild/win32-x64": "0.28.2"2426
+ }2427
+ },2428
+ "node_modules/esm-env": {2429
+ "version": "1.2.2",2430
+ "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz",2431
+ "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==",2432
+ "license": "MIT"2433
+ },2434
+ "node_modules/esprima": {2435
+ "version": "4.0.1",2436
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",2437
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",2438
+ "dev": true,2439
+ "license": "BSD-2-Clause",2440
+ "bin": {2441
+ "esparse": "bin/esparse.js",2442
+ "esvalidate": "bin/esvalidate.js"2443
+ },2444
+ "engines": {2445
+ "node": ">=4"2446
+ }2447
+ },2448
+ "node_modules/esrap": {2449
+ "version": "2.4.0",2450
+ "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.4.0.tgz",2451
+ "integrity": "sha512-CQPcneEHw/czj32uwQC52nYnax8H4SXt25FCM+LIwGZ49cMIxpOj3bP8wmzcI+Z0HIy5KkClaPhRLfCySzwHPA==",2452
+ "license": "MIT",2453
+ "dependencies": {2454
+ "@jridgewell/sourcemap-codec": "^1.4.15"2455
+ },2456
+ "peerDependencies": {2457
+ "@typescript-eslint/types": "^8.2.0"2458
+ },2459
+ "peerDependenciesMeta": {2460
+ "@typescript-eslint/types": {2461
+ "optional": true2462
+ }2463
+ }2464
+ },2465
+ "node_modules/fsevents": {2466
+ "version": "2.3.3",2467
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",2468
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",2469
+ "dev": true,2470
+ "hasInstallScript": true,2471
+ "license": "MIT",2472
+ "optional": true,2473
+ "os": [2474
+ "darwin"2475
+ ],2476
+ "engines": {2477
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"2478
+ }2479
+ },2480
+ "node_modules/indent-string": {2481
+ "version": "4.0.0",2482
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",2483
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",2484
+ "dev": true,2485
+ "license": "MIT",2486
+ "engines": {2487
+ "node": ">=8"2488
+ }2489
+ },2490
+ "node_modules/is-docker": {2491
+ "version": "3.0.0",2492
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",2493
+ "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",2494
+ "dev": true,2495
+ "license": "MIT",2496
+ "bin": {2497
+ "is-docker": "cli.js"2498
+ },2499
+ "engines": {2500
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"2501
+ },2502
+ "funding": {2503
+ "url": "https://github.com/sponsors/sindresorhus"2504
+ }2505
+ },2506
+ "node_modules/is-inside-container": {2507
+ "version": "1.0.0",2508
+ "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",2509
+ "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",2510
+ "dev": true,2511
+ "license": "MIT",2512
+ "dependencies": {2513
+ "is-docker": "^3.0.0"2514
+ },2515
+ "bin": {2516
+ "is-inside-container": "cli.js"2517
+ },2518
+ "engines": {2519
+ "node": ">=14.16"2520
+ },2521
+ "funding": {2522
+ "url": "https://github.com/sponsors/sindresorhus"2523
+ }2524
+ },2525
+ "node_modules/is-reference": {2526
+ "version": "3.0.3",2527
+ "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",2528
+ "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==",2529
+ "license": "MIT",2530
+ "dependencies": {2531
+ "@types/estree": "^1.0.6"2532
+ }2533
+ },2534
+ "node_modules/is-wsl": {2535
+ "version": "3.1.1",2536
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz",2537
+ "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==",2538
+ "dev": true,2539
+ "license": "MIT",2540
+ "dependencies": {2541
+ "is-inside-container": "^1.0.0"2542
+ },2543
+ "engines": {2544
+ "node": ">=16"2545
+ },2546
+ "funding": {2547
+ "url": "https://github.com/sponsors/sindresorhus"2548
+ }2549
+ },2550
+ "node_modules/js-tokens": {2551
+ "version": "4.0.0",2552
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",2553
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",2554
+ "dev": true,2555
+ "license": "MIT"2556
+ },2557
+ "node_modules/json-rpc-2.0": {2558
+ "version": "1.8.1",2559
+ "resolved": "https://registry.npmjs.org/json-rpc-2.0/-/json-rpc-2.0-1.8.1.tgz",2560
+ "integrity": "sha512-BmN42JKn6FI36pcMMzHCXQhpKNEfbeqgSIcUYHKnifq0/4Ey6PDinovwUOgajT7NsgUtpWdDXaCWlpI4LHXN3g==",2561
+ "dev": true,2562
+ "license": "MIT"2563
+ },2564
+ "node_modules/jsonc-parser": {2565
+ "version": "3.3.1",2566
+ "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz",2567
+ "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==",2568
+ "dev": true,2569
+ "license": "MIT"2570
+ },2571
+ "node_modules/kleur": {2572
+ "version": "4.1.5",2573
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",2574
+ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",2575
+ "dev": true,2576
+ "license": "MIT",2577
+ "engines": {2578
+ "node": ">=6"2579
+ }2580
+ },2581
+ "node_modules/locate-character": {2582
+ "version": "3.0.0",2583
+ "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",2584
+ "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",2585
+ "license": "MIT"2586
+ },2587
+ "node_modules/loupe": {2588
+ "version": "3.2.1",2589
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz",2590
+ "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==",2591
+ "dev": true,2592
+ "license": "MIT"2593
+ },2594
+ "node_modules/lz-string": {2595
+ "version": "1.5.0",2596
+ "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz",2597
+ "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",2598
+ "dev": true,2599
+ "license": "MIT",2600
+ "bin": {2601
+ "lz-string": "bin/bin.js"2602
+ }2603
+ },2604
+ "node_modules/magic-string": {2605
+ "version": "1.4.3",2606
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.3.tgz",2607
+ "integrity": "sha512-z12OxmaPGE0F4xlpGdjuAUckipLpQlTAuAmyGhNoD7ODpYUzvDfvtxUbjM/jwznyP178oju/KDdyi220wNJ0RQ==",2608
+ "dev": true,2609
+ "license": "MIT",2610
+ "dependencies": {2611
+ "@jridgewell/sourcemap-codec": "^1.6.0"2612
+ }2613
+ },2614
+ "node_modules/min-indent": {2615
+ "version": "1.0.1",2616
+ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",2617
+ "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",2618
+ "dev": true,2619
+ "license": "MIT",2620
+ "engines": {2621
+ "node": ">=4"2622
+ }2623
+ },2624
+ "node_modules/ms": {2625
+ "version": "2.1.3",2626
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",2627
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",2628
+ "dev": true,2629
+ "license": "MIT"2630
+ },2631
+ "node_modules/nanoid": {2632
+ "version": "3.3.20",2633
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz",2634
+ "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==",2635
+ "dev": true,2636
+ "funding": [2637
+ {2638
+ "type": "github",2639
+ "url": "https://github.com/sponsors/ai"2640
+ }2641
+ ],2642
+ "license": "MIT",2643
+ "bin": {2644
+ "nanoid": "bin/nanoid.cjs"2645
+ },2646
+ "engines": {2647
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"2648
+ }2649
+ },2650
+ "node_modules/open": {2651
+ "version": "10.2.0",2652
+ "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz",2653
+ "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==",2654
+ "dev": true,2655
+ "license": "MIT",2656
+ "dependencies": {2657
+ "default-browser": "^5.2.1",2658
+ "define-lazy-prop": "^3.0.0",2659
+ "is-inside-container": "^1.0.0",2660
+ "wsl-utils": "^0.1.0"2661
+ },2662
+ "engines": {2663
+ "node": ">=18"2664
+ },2665
+ "funding": {2666
+ "url": "https://github.com/sponsors/sindresorhus"2667
+ }2668
+ },2669
+ "node_modules/oxc-parser": {2670
+ "version": "0.127.0",2671
+ "resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.127.0.tgz",2672
+ "integrity": "sha512-bkgD4qHlN7WxLdX8bLXdaU54TtQtAIg/ZBAfm0aje/mo3MRDo3P0hZSgr4U7O3xfX+fQmR5AP04JS/TGcZLcFA==",2673
+ "dev": true,2674
+ "license": "MIT",2675
+ "dependencies": {2676
+ "@oxc-project/types": "^0.127.0"2677
+ },2678
+ "engines": {2679
+ "node": "^20.19.0 || >=22.12.0"2680
+ },2681
+ "funding": {2682
+ "url": "https://github.com/sponsors/Boshen"2683
+ },2684
+ "optionalDependencies": {2685
+ "@oxc-parser/binding-android-arm-eabi": "0.127.0",2686
+ "@oxc-parser/binding-android-arm64": "0.127.0",2687
+ "@oxc-parser/binding-darwin-arm64": "0.127.0",2688
+ "@oxc-parser/binding-darwin-x64": "0.127.0",2689
+ "@oxc-parser/binding-freebsd-x64": "0.127.0",2690
+ "@oxc-parser/binding-linux-arm-gnueabihf": "0.127.0",2691
+ "@oxc-parser/binding-linux-arm-musleabihf": "0.127.0",2692
+ "@oxc-parser/binding-linux-arm64-gnu": "0.127.0",2693
+ "@oxc-parser/binding-linux-arm64-musl": "0.127.0",2694
+ "@oxc-parser/binding-linux-ppc64-gnu": "0.127.0",2695
+ "@oxc-parser/binding-linux-riscv64-gnu": "0.127.0",2696
+ "@oxc-parser/binding-linux-riscv64-musl": "0.127.0",2697
+ "@oxc-parser/binding-linux-s390x-gnu": "0.127.0",2698
+ "@oxc-parser/binding-linux-x64-gnu": "0.127.0",2699
+ "@oxc-parser/binding-linux-x64-musl": "0.127.0",2700
+ "@oxc-parser/binding-openharmony-arm64": "0.127.0",2701
+ "@oxc-parser/binding-wasm32-wasi": "0.127.0",2702
+ "@oxc-parser/binding-win32-arm64-msvc": "0.127.0",2703
+ "@oxc-parser/binding-win32-ia32-msvc": "0.127.0",2704
+ "@oxc-parser/binding-win32-x64-msvc": "0.127.0"2705
+ }2706
+ },2707
+ "node_modules/oxc-resolver": {2708
+ "version": "11.21.2",2709
+ "resolved": "https://registry.npmjs.org/oxc-resolver/-/oxc-resolver-11.21.2.tgz",2710
+ "integrity": "sha512-w5tLwYN3Zo24w5EeWJjJWZOwhYqTtC8PS2B1tIt7BZUuqTIcU07sQValbDw+rq7+AuAGzOHklgK+ifsy4lpXfw==",2711
+ "dev": true,2712
+ "license": "MIT",2713
+ "funding": {2714
+ "url": "https://github.com/sponsors/Boshen"2715
+ },2716
+ "optionalDependencies": {2717
+ "@oxc-resolver/binding-android-arm-eabi": "11.21.2",2718
+ "@oxc-resolver/binding-android-arm64": "11.21.2",2719
+ "@oxc-resolver/binding-darwin-arm64": "11.21.2",2720
+ "@oxc-resolver/binding-darwin-x64": "11.21.2",2721
+ "@oxc-resolver/binding-freebsd-x64": "11.21.2",2722
+ "@oxc-resolver/binding-linux-arm-gnueabihf": "11.21.2",2723
+ "@oxc-resolver/binding-linux-arm-musleabihf": "11.21.2",2724
+ "@oxc-resolver/binding-linux-arm64-gnu": "11.21.2",2725
+ "@oxc-resolver/binding-linux-arm64-musl": "11.21.2",2726
+ "@oxc-resolver/binding-linux-ppc64-gnu": "11.21.2",2727
+ "@oxc-resolver/binding-linux-riscv64-gnu": "11.21.2",2728
+ "@oxc-resolver/binding-linux-riscv64-musl": "11.21.2",2729
+ "@oxc-resolver/binding-linux-s390x-gnu": "11.21.2",2730
+ "@oxc-resolver/binding-linux-x64-gnu": "11.21.2",2731
+ "@oxc-resolver/binding-linux-x64-musl": "11.21.2",2732
+ "@oxc-resolver/binding-openharmony-arm64": "11.21.2",2733
+ "@oxc-resolver/binding-wasm32-wasi": "11.21.2",2734
+ "@oxc-resolver/binding-win32-arm64-msvc": "11.21.2",2735
+ "@oxc-resolver/binding-win32-x64-msvc": "11.21.2"2736
+ }2737
+ },2738
+ "node_modules/pathval": {2739
+ "version": "2.0.1",2740
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz",2741
+ "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==",2742
+ "dev": true,2743
+ "license": "MIT",2744
+ "engines": {2745
+ "node": ">= 14.16"2746
+ }2747
+ },2748
+ "node_modules/picocolors": {2749
+ "version": "1.1.1",2750
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",2751
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",2752
+ "dev": true,2753
+ "license": "ISC"2754
+ },2755
+ "node_modules/picomatch": {2756
+ "version": "4.0.7",2757
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz",2758
+ "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==",2759
+ "dev": true,2760
+ "license": "MIT",2761
+ "engines": {2762
+ "node": ">=12"2763
+ },2764
+ "funding": {2765
+ "url": "https://github.com/sponsors/jonschlinkert"2766
+ }2767
+ },2768
+ "node_modules/postcss": {2769
+ "version": "8.5.29",2770
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.29.tgz",2771
+ "integrity": "sha512-49cGhUbXj8Qenv0iTMxA1cFBzxXoctpC9Ujd77t1WcbJIr6nF/eI7g/8MgxrYldFRuAXvja7xQRwavoW7kgrxQ==",2772
+ "dev": true,2773
+ "funding": [2774
+ {2775
+ "type": "opencollective",2776
+ "url": "https://opencollective.com/postcss/"2777
+ },2778
+ {2779
+ "type": "tidelift",2780
+ "url": "https://tidelift.com/funding/github/npm/postcss"2781
+ },2782
+ {2783
+ "type": "github",2784
+ "url": "https://github.com/sponsors/ai"2785
+ }2786
+ ],2787
+ "license": "MIT",2788
+ "dependencies": {2789
+ "nanoid": "^3.3.19",2790
+ "picocolors": "^1.1.1",2791
+ "source-map-js": "^1.2.2"2792
+ },2793
+ "engines": {2794
+ "node": "^10 || ^12 || >=14"2795
+ }2796
+ },2797
+ "node_modules/pretty-format": {2798
+ "version": "27.5.1",2799
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",2800
+ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",2801
+ "dev": true,2802
+ "license": "MIT",2803
+ "dependencies": {2804
+ "ansi-regex": "^5.0.1",2805
+ "ansi-styles": "^5.0.0",2806
+ "react-is": "^17.0.1"2807
+ },2808
+ "engines": {2809
+ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"2810
+ }2811
+ },2812
+ "node_modules/react": {2813
+ "version": "19.3.0",2814
+ "resolved": "https://registry.npmjs.org/react/-/react-19.3.0.tgz",2815
+ "integrity": "sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==",2816
+ "dev": true,2817
+ "license": "MIT",2818
+ "engines": {2819
+ "node": ">=0.10.0"2820
+ }2821
+ },2822
+ "node_modules/react-dom": {2823
+ "version": "19.3.0",2824
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.3.0.tgz",2825
+ "integrity": "sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q==",2826
+ "dev": true,2827
+ "license": "MIT",2828
+ "dependencies": {2829
+ "scheduler": "^0.28.0"2830
+ },2831
+ "peerDependencies": {2832
+ "react": "^19.3.0"2833
+ }2834
+ },2835
+ "node_modules/react-is": {2836
+ "version": "17.0.2",2837
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",2838
+ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",2839
+ "dev": true,2840
+ "license": "MIT"2841
+ },2842
+ "node_modules/recast": {2843
+ "version": "0.23.21",2844
+ "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.21.tgz",2845
+ "integrity": "sha512-mFAyJq9vUbSTARLZUvAEf1z3YxlvAwswbmxMx2mPA/MSm4KmpwvwvhsH/NIrZhyOuwD60Lzyw2qh83uCbgTPYw==",2846
+ "dev": true,2847
+ "license": "MIT",2848
+ "dependencies": {2849
+ "ast-types": "^0.16.1",2850
+ "esprima": "~4.0.0",2851
+ "source-map": "~0.6.1",2852
+ "tiny-invariant": "^1.3.3",2853
+ "tslib": "^2.0.1"2854
+ },2855
+ "engines": {2856
+ "node": ">= 4"2857
+ }2858
+ },2859
+ "node_modules/redent": {2860
+ "version": "3.0.0",2861
+ "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",2862
+ "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",2863
+ "dev": true,2864
+ "license": "MIT",2865
+ "dependencies": {2866
+ "indent-string": "^4.0.0",2867
+ "strip-indent": "^3.0.0"2868
+ },2869
+ "engines": {2870
+ "node": ">=8"2871
+ }2872
+ },2873
+ "node_modules/rollup": {2874
+ "version": "4.64.2",2875
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.64.2.tgz",2876
+ "integrity": "sha512-RxXm0XVVV1hFI3dYe12ruaOgsYQ725lUcUWeMSQqkF9tTxVErY+fy2Ets6vWhItL9MZMSNZGbvZFc7rH/VHp2Q==",2877
+ "dev": true,2878
+ "license": "MIT",2879
+ "dependencies": {2880
+ "@types/estree": "1.0.9"2881
+ },2882
+ "bin": {2883
+ "rollup": "dist/bin/rollup"2884
+ },2885
+ "engines": {2886
+ "node": ">=18.0.0",2887
+ "npm": ">=8.0.0"2888
+ },2889
+ "optionalDependencies": {2890
+ "@napi-rs/lzma-linux-x64-gnu": "1.5.1",2891
+ "@rollup/rollup-android-arm-eabi": "4.64.2",2892
+ "@rollup/rollup-android-arm64": "4.64.2",2893
+ "@rollup/rollup-darwin-arm64": "4.64.2",2894
+ "@rollup/rollup-darwin-x64": "4.64.2",2895
+ "@rollup/rollup-freebsd-arm64": "4.64.2",2896
+ "@rollup/rollup-freebsd-x64": "4.64.2",2897
+ "@rollup/rollup-linux-arm-gnueabihf": "4.64.2",2898
+ "@rollup/rollup-linux-arm-musleabihf": "4.64.2",2899
+ "@rollup/rollup-linux-arm64-gnu": "4.64.2",2900
+ "@rollup/rollup-linux-arm64-musl": "4.64.2",2901
+ "@rollup/rollup-linux-loong64-gnu": "4.64.2",2902
+ "@rollup/rollup-linux-loong64-musl": "4.64.2",2903
+ "@rollup/rollup-linux-ppc64-gnu": "4.64.2",2904
+ "@rollup/rollup-linux-ppc64-musl": "4.64.2",2905
+ "@rollup/rollup-linux-riscv64-gnu": "4.64.2",2906
+ "@rollup/rollup-linux-riscv64-musl": "4.64.2",2907
+ "@rollup/rollup-linux-s390x-gnu": "4.64.2",2908
+ "@rollup/rollup-linux-x64-gnu": "4.64.2",2909
+ "@rollup/rollup-linux-x64-musl": "4.64.2",2910
+ "@rollup/rollup-openbsd-x64": "4.64.2",2911
+ "@rollup/rollup-openharmony-arm64": "4.64.2",2912
+ "@rollup/rollup-win32-arm64-msvc": "4.64.2",2913
+ "@rollup/rollup-win32-ia32-msvc": "4.64.2",2914
+ "@rollup/rollup-win32-x64-gnu": "4.64.2",2915
+ "@rollup/rollup-win32-x64-msvc": "4.64.2",2916
+ "fsevents": "~2.3.2"2917
+ }2918
+ },2919
+ "node_modules/run-applescript": {2920
+ "version": "7.1.0",2921
+ "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz",2922
+ "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==",2923
+ "dev": true,2924
+ "license": "MIT",2925
+ "engines": {2926
+ "node": ">=18"2927
+ },2928
+ "funding": {2929
+ "url": "https://github.com/sponsors/sindresorhus"2930
+ }2931
+ },2932
+ "node_modules/scheduler": {2933
+ "version": "0.28.0",2934
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.28.0.tgz",2935
+ "integrity": "sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==",2936
+ "dev": true,2937
+ "license": "MIT"2938
+ },2939
+ "node_modules/scule": {2940
+ "version": "1.3.0",2941
+ "resolved": "https://registry.npmjs.org/scule/-/scule-1.3.0.tgz",2942
+ "integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==",2943
+ "dev": true,2944
+ "license": "MIT"2945
+ },2946
+ "node_modules/semver": {2947
+ "version": "7.8.5",2948
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",2949
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",2950
+ "dev": true,2951
+ "license": "ISC",2952
+ "bin": {2953
+ "semver": "bin/semver.js"2954
+ },2955
+ "engines": {2956
+ "node": ">=10"2957
+ }2958
+ },2959
+ "node_modules/source-map": {2960
+ "version": "0.6.1",2961
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",2962
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",2963
+ "dev": true,2964
+ "license": "BSD-3-Clause",2965
+ "engines": {2966
+ "node": ">=0.10.0"2967
+ }2968
+ },2969
+ "node_modules/source-map-js": {2970
+ "version": "1.2.2",2971
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz",2972
+ "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==",2973
+ "dev": true,2974
+ "license": "BSD-3-Clause",2975
+ "engines": {2976
+ "node": ">=0.10.0"2977
+ }2978
+ },2979
+ "node_modules/sqids": {2980
+ "version": "0.3.0",2981
+ "resolved": "https://registry.npmjs.org/sqids/-/sqids-0.3.0.tgz",2982
+ "integrity": "sha512-lOQK1ucVg+W6n3FhRwwSeUijxe93b51Bfz5PMRMihVf1iVkl82ePQG7V5vwrhzB11v0NtsR25PSZRGiSomJaJw==",2983
+ "dev": true,2984
+ "license": "MIT"2985
+ },2986
+ "node_modules/storybook": {2987
+ "version": "10.6.1",2988
+ "resolved": "https://registry.npmjs.org/storybook/-/storybook-10.6.1.tgz",2989
+ "integrity": "sha512-NeEmukMWPA5OqHizUkQtxCIhGt7MUZLPY4FFgpC0LNiipjrac/oKpH0TxI+9Zc+vI5+IoN+NiskOmBP7gtYfmA==",2990
+ "dev": true,2991
+ "license": "MIT",2992
+ "dependencies": {2993
+ "@storybook/global": "^5.0.0",2994
+ "@storybook/icons": "^2.0.2",2995
+ "@testing-library/dom": "^10.4.1",2996
+ "@testing-library/jest-dom": "6.9.1",2997
+ "@testing-library/user-event": "^14.6.3",2998
+ "@vitest/expect": "3.2.4",2999
+ "@vitest/spy": "3.2.4",3000
+ "@webcontainer/env": "^1.1.1",3001
+ "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.26.0 || ^0.27.0 || ^0.28.0",3002
+ "jsonc-parser": "^3.3.1",3003
+ "open": "^10.2.0",3004
+ "oxc-parser": "^0.127.0",3005
+ "oxc-resolver": "11.21.2",3006
+ "recast": "^0.23.5",3007
+ "semver": "^7.7.3",3008
+ "use-sync-external-store": "^1.5.0",3009
+ "ws": "^8.21.1"3010
+ },3011
+ "bin": {3012
+ "storybook": "dist/bin/dispatcher.js"3013
+ },3014
+ "funding": {3015
+ "type": "opencollective",3016
+ "url": "https://opencollective.com/storybook"3017
+ },3018
+ "peerDependencies": {3019
+ "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",3020
+ "prettier": "^2 || ^3",3021
+ "vite-plus": "^0.1.15 || ^0.2.0"3022
+ },3023
+ "peerDependenciesMeta": {3024
+ "@types/react": {3025
+ "optional": true3026
+ },3027
+ "prettier": {3028
+ "optional": true3029
+ },3030
+ "vite-plus": {3031
+ "optional": true3032
+ }3033
+ }3034
+ },3035
+ "node_modules/strip-indent": {3036
+ "version": "3.0.0",3037
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",3038
+ "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",3039
+ "dev": true,3040
+ "license": "MIT",3041
+ "dependencies": {3042
+ "min-indent": "^1.0.0"3043
+ },3044
+ "engines": {3045
+ "node": ">=8"3046
+ }3047
+ },3048
+ "node_modules/svelte": {3049
+ "version": "5.57.2",3050
+ "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.57.2.tgz",3051
+ "integrity": "sha512-1YiPCAXT0Ct6g1vOMmSLa0Nsc3QRMvtDF32ihgglGVrugIuIK38RyDiFNXVDhtQ81TJjSO57NdMw6DyYLqSGDQ==",3052
+ "license": "MIT",3053
+ "dependencies": {3054
+ "@jridgewell/remapping": "^2.3.5",3055
+ "@jridgewell/sourcemap-codec": "^1.6.0",3056
+ "@sveltejs/acorn-typescript": "^1.0.13",3057
+ "@types/estree": "^1.0.9",3058
+ "acorn": "^8.18.0",3059
+ "aria-query": "5.3.1",3060
+ "axobject-query": "^4.1.0",3061
+ "clsx": "^2.1.1",3062
+ "devalue": "^5.9.2",3063
+ "esm-env": "^1.2.1",3064
+ "esrap": "^2.3.6",3065
+ "is-reference": "^3.0.3",3066
+ "locate-character": "^3.0.0",3067
+ "magic-string": "^0.30.11",3068
+ "zimmerframe": "^1.1.2"3069
+ },3070
+ "engines": {3071
+ "node": ">=18"3072
+ }3073
+ },3074
+ "node_modules/svelte/node_modules/aria-query": {3075
+ "version": "5.3.1",3076
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz",3077
+ "integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==",3078
+ "license": "Apache-2.0",3079
+ "engines": {3080
+ "node": ">= 0.4"3081
+ }3082
+ },3083
+ "node_modules/svelte/node_modules/magic-string": {3084
+ "version": "0.30.21",3085
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",3086
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",3087
+ "license": "MIT",3088
+ "dependencies": {3089
+ "@jridgewell/sourcemap-codec": "^1.5.5"3090
+ }3091
+ },3092
+ "node_modules/svelte2tsx": {3093
+ "version": "0.7.61",3094
+ "resolved": "https://registry.npmjs.org/svelte2tsx/-/svelte2tsx-0.7.61.tgz",3095
+ "integrity": "sha512-EpQ/+UHITBULeUojx/LLD3uTYasZXcX1BrqlrzfLUnT9vdUhaOWK59a3ryWcFU8L0sY1SP+gRhJ2Beiis98+qw==",3096
+ "dev": true,3097
+ "license": "MIT",3098
+ "dependencies": {3099
+ "dedent-js": "^1.0.1",3100
+ "scule": "^1.3.0"3101
+ },3102
+ "peerDependencies": {3103
+ "svelte": "^3.55 || ^4.0.0-next.0 || ^4.0 || ^5.0.0-next.0",3104
+ "typescript": "^4.9.4 || ^5.0.0 || ^6.0.0"3105
+ }3106
+ },3107
+ "node_modules/tagged-tag": {3108
+ "version": "1.0.0",3109
+ "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz",3110
+ "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==",3111
+ "dev": true,3112
+ "license": "MIT",3113
+ "engines": {3114
+ "node": ">=20"3115
+ },3116
+ "funding": {3117
+ "url": "https://github.com/sponsors/sindresorhus"3118
+ }3119
+ },3120
+ "node_modules/tiny-invariant": {3121
+ "version": "1.3.3",3122
+ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",3123
+ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==",3124
+ "dev": true,3125
+ "license": "MIT"3126
+ },3127
+ "node_modules/tinyrainbow": {3128
+ "version": "2.0.0",3129
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz",3130
+ "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==",3131
+ "dev": true,3132
+ "license": "MIT",3133
+ "engines": {3134
+ "node": ">=14.0.0"3135
+ }3136
+ },3137
+ "node_modules/tinyspy": {3138
+ "version": "4.0.6",3139
+ "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.6.tgz",3140
+ "integrity": "sha512-u8KszXvGfU68hVcZpRHKG28T0krMuv2G5nDhiHaMLen/gIuFEgIJhaJuO69qjnXg5paSrbPMFfx3brNuN8eVSg==",3141
+ "dev": true,3142
+ "license": "MIT",3143
+ "engines": {3144
+ "node": ">=14.0.0"3145
+ }3146
+ },3147
+ "node_modules/tmcp": {3148
+ "version": "1.20.0",3149
+ "resolved": "https://registry.npmjs.org/tmcp/-/tmcp-1.20.0.tgz",3150
+ "integrity": "sha512-dcDximKQBGqLP/aEAVA26HcWRHhKipstg1w0fbDDJ0HcFZ6lolLU1YYmStYEn/73f534i7WrDNcjRfRYdV9CoA==",3151
+ "dev": true,3152
+ "license": "MIT",3153
+ "dependencies": {3154
+ "@standard-schema/spec": "^1.0.0",3155
+ "json-rpc-2.0": "^1.7.1",3156
+ "sqids": "^0.3.0",3157
+ "uri-template-matcher": "^1.1.1",3158
+ "valibot": "^1.1.0"3159
+ }3160
+ },3161
+ "node_modules/ts-dedent": {3162
+ "version": "2.3.0",3163
+ "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.3.0.tgz",3164
+ "integrity": "sha512-JfJeIHke7y2egdGGgRAvpCwYFUsHlM2gPcrVOxFkznt/4uzQ7HFmvE63iFHVLBJNDuyDOQgijDK/tXH/f6Msjg==",3165
+ "dev": true,3166
+ "license": "MIT",3167
+ "engines": {3168
+ "node": ">=6.10"3169
+ }3170
+ },3171
+ "node_modules/tslib": {3172
+ "version": "2.8.1",3173
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",3174
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",3175
+ "dev": true,3176
+ "license": "0BSD"3177
+ },3178
+ "node_modules/type-fest": {3179
+ "version": "5.10.0",3180
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.10.0.tgz",3181
+ "integrity": "sha512-NoSdpq/WEiAg5sjmBkmV/hfxv6HJH4NqPNrqjtSO5CwRmpsDfaf4begxW34KdJykH/l1yHtwBWQkCRdoXO8mPA==",3182
+ "dev": true,3183
+ "license": "(MIT OR CC0-1.0)",3184
+ "dependencies": {3185
+ "tagged-tag": "^1.0.0"3186
+ },3187
+ "engines": {3188
+ "node": ">=20"3189
+ },3190
+ "funding": {3191
+ "url": "https://github.com/sponsors/sindresorhus"3192
+ }3193
+ },3194
+ "node_modules/typescript": {3195
+ "version": "6.0.3",3196
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",3197
+ "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",3198
+ "dev": true,3199
+ "license": "Apache-2.0",3200
+ "bin": {3201
+ "tsc": "bin/tsc",3202
+ "tsserver": "bin/tsserver"3203
+ },3204
+ "engines": {3205
+ "node": ">=14.17"3206
+ }3207
+ },3208
+ "node_modules/unplugin": {3209
+ "version": "2.3.11",3210
+ "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.11.tgz",3211
+ "integrity": "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==",3212
+ "dev": true,3213
+ "license": "MIT",3214
+ "dependencies": {3215
+ "@jridgewell/remapping": "^2.3.5",3216
+ "acorn": "^8.15.0",3217
+ "picomatch": "^4.0.3",3218
+ "webpack-virtual-modules": "^0.6.2"3219
+ },3220
+ "engines": {3221
+ "node": ">=18.12.0"3222
+ }3223
+ },3224
+ "node_modules/uri-template-matcher": {3225
+ "version": "1.1.2",3226
+ "resolved": "https://registry.npmjs.org/uri-template-matcher/-/uri-template-matcher-1.1.2.tgz",3227
+ "integrity": "sha512-uZc1h12jdO3m/R77SfTEOuo6VbMhgWznaawKpBjRGSJb7i91x5PgI37NQJtG+Cerxkk0yr1pylBY2qG1kQ+aEQ==",3228
+ "dev": true,3229
+ "license": "ISC"3230
+ },3231
+ "node_modules/use-sync-external-store": {3232
+ "version": "1.7.0",3233
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.7.0.tgz",3234
+ "integrity": "sha512-6L+EeigHMQhdaIPNIFUKwfWJSwWFQ8gJbJ2DLOs5sDIegTwR9fRxvnM3uciHKjIZhFz+KAv2emhWMRvDmMcY8A==",3235
+ "dev": true,3236
+ "license": "MIT",3237
+ "peerDependencies": {3238
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"3239
+ }3240
+ },3241
+ "node_modules/valibot": {3242
+ "version": "1.5.0",3243
+ "resolved": "https://registry.npmjs.org/valibot/-/valibot-1.5.0.tgz",3244
+ "integrity": "sha512-nil6AkP2TChWL43Z5uJ6GTxX01CUA+g8LWUM+N/rB9NBbkUMaUsi9PUNzlUPgoKASgmx9f7eGOYpJ04/fSa6FQ==",3245
+ "dev": true,3246
+ "license": "MIT",3247
+ "peerDependencies": {3248
+ "typescript": ">=5"3249
+ },3250
+ "peerDependenciesMeta": {3251
+ "typescript": {3252
+ "optional": true3253
+ }3254
+ }3255
+ },3256
+ "node_modules/vite": {3257
+ "version": "5.4.21",3258
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",3259
+ "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",3260
+ "dev": true,3261
+ "license": "MIT",3262
+ "dependencies": {3263
+ "esbuild": "^0.21.3",3264
+ "postcss": "^8.4.43",3265
+ "rollup": "^4.20.0"3266
+ },3267
+ "bin": {3268
+ "vite": "bin/vite.js"3269
+ },3270
+ "engines": {3271
+ "node": "^18.0.0 || >=20.0.0"3272
+ },3273
+ "funding": {3274
+ "url": "https://github.com/vitejs/vite?sponsor=1"3275
+ },3276
+ "optionalDependencies": {3277
+ "fsevents": "~2.3.3"3278
+ },3279
+ "peerDependencies": {3280
+ "@types/node": "^18.0.0 || >=20.0.0",3281
+ "less": "*",3282
+ "lightningcss": "^1.21.0",3283
+ "sass": "*",3284
+ "sass-embedded": "*",3285
+ "stylus": "*",3286
+ "sugarss": "*",3287
+ "terser": "^5.4.0"3288
+ },3289
+ "peerDependenciesMeta": {3290
+ "@types/node": {3291
+ "optional": true3292
+ },3293
+ "less": {3294
+ "optional": true3295
+ },3296
+ "lightningcss": {3297
+ "optional": true3298
+ },3299
+ "sass": {3300
+ "optional": true3301
+ },3302
+ "sass-embedded": {3303
+ "optional": true3304
+ },3305
+ "stylus": {3306
+ "optional": true3307
+ },3308
+ "sugarss": {3309
+ "optional": true3310
+ },3311
+ "terser": {3312
+ "optional": true3313
+ }3314
+ }3315
+ },3316
+ "node_modules/vite/node_modules/@esbuild/aix-ppc64": {3317
+ "version": "0.21.5",3318
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",3319
+ "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",3320
+ "cpu": [3321
+ "ppc64"3322
+ ],3323
+ "dev": true,3324
+ "license": "MIT",3325
+ "optional": true,3326
+ "os": [3327
+ "aix"3328
+ ],3329
+ "engines": {3330
+ "node": ">=12"3331
+ }3332
+ },3333
+ "node_modules/vite/node_modules/@esbuild/android-arm": {3334
+ "version": "0.21.5",3335
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",3336
+ "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",3337
+ "cpu": [3338
+ "arm"3339
+ ],3340
+ "dev": true,3341
+ "license": "MIT",3342
+ "optional": true,3343
+ "os": [3344
+ "android"3345
+ ],3346
+ "engines": {3347
+ "node": ">=12"3348
+ }3349
+ },3350
+ "node_modules/vite/node_modules/@esbuild/android-arm64": {3351
+ "version": "0.21.5",3352
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",3353
+ "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",3354
+ "cpu": [3355
+ "arm64"3356
+ ],3357
+ "dev": true,3358
+ "license": "MIT",3359
+ "optional": true,3360
+ "os": [3361
+ "android"3362
+ ],3363
+ "engines": {3364
+ "node": ">=12"3365
+ }3366
+ },3367
+ "node_modules/vite/node_modules/@esbuild/android-x64": {3368
+ "version": "0.21.5",3369
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",3370
+ "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",3371
+ "cpu": [3372
+ "x64"3373
+ ],3374
+ "dev": true,3375
+ "license": "MIT",3376
+ "optional": true,3377
+ "os": [3378
+ "android"3379
+ ],3380
+ "engines": {3381
+ "node": ">=12"3382
+ }3383
+ },3384
+ "node_modules/vite/node_modules/@esbuild/darwin-arm64": {3385
+ "version": "0.21.5",3386
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",3387
+ "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",3388
+ "cpu": [3389
+ "arm64"3390
+ ],3391
+ "dev": true,3392
+ "license": "MIT",3393
+ "optional": true,3394
+ "os": [3395
+ "darwin"3396
+ ],3397
+ "engines": {3398
+ "node": ">=12"3399
+ }3400
+ },3401
+ "node_modules/vite/node_modules/@esbuild/darwin-x64": {3402
+ "version": "0.21.5",3403
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",3404
+ "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",3405
+ "cpu": [3406
+ "x64"3407
+ ],3408
+ "dev": true,3409
+ "license": "MIT",3410
+ "optional": true,3411
+ "os": [3412
+ "darwin"3413
+ ],3414
+ "engines": {3415
+ "node": ">=12"3416
+ }3417
+ },3418
+ "node_modules/vite/node_modules/@esbuild/freebsd-arm64": {3419
+ "version": "0.21.5",3420
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",3421
+ "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",3422
+ "cpu": [3423
+ "arm64"3424
+ ],3425
+ "dev": true,3426
+ "license": "MIT",3427
+ "optional": true,3428
+ "os": [3429
+ "freebsd"3430
+ ],3431
+ "engines": {3432
+ "node": ">=12"3433
+ }3434
+ },3435
+ "node_modules/vite/node_modules/@esbuild/freebsd-x64": {3436
+ "version": "0.21.5",3437
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",3438
+ "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",3439
+ "cpu": [3440
+ "x64"3441
+ ],3442
+ "dev": true,3443
+ "license": "MIT",3444
+ "optional": true,3445
+ "os": [3446
+ "freebsd"3447
+ ],3448
+ "engines": {3449
+ "node": ">=12"3450
+ }3451
+ },3452
+ "node_modules/vite/node_modules/@esbuild/linux-arm": {3453
+ "version": "0.21.5",3454
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",3455
+ "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",3456
+ "cpu": [3457
+ "arm"3458
+ ],3459
+ "dev": true,3460
+ "license": "MIT",3461
+ "optional": true,3462
+ "os": [3463
+ "linux"3464
+ ],3465
+ "engines": {3466
+ "node": ">=12"3467
+ }3468
+ },3469
+ "node_modules/vite/node_modules/@esbuild/linux-arm64": {3470
+ "version": "0.21.5",3471
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",3472
+ "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",3473
+ "cpu": [3474
+ "arm64"3475
+ ],3476
+ "dev": true,3477
+ "license": "MIT",3478
+ "optional": true,3479
+ "os": [3480
+ "linux"3481
+ ],3482
+ "engines": {3483
+ "node": ">=12"3484
+ }3485
+ },3486
+ "node_modules/vite/node_modules/@esbuild/linux-ia32": {3487
+ "version": "0.21.5",3488
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",3489
+ "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",3490
+ "cpu": [3491
+ "ia32"3492
+ ],3493
+ "dev": true,3494
+ "license": "MIT",3495
+ "optional": true,3496
+ "os": [3497
+ "linux"3498
+ ],3499
+ "engines": {3500
+ "node": ">=12"3501
+ }3502
+ },3503
+ "node_modules/vite/node_modules/@esbuild/linux-loong64": {3504
+ "version": "0.21.5",3505
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",3506
+ "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",3507
+ "cpu": [3508
+ "loong64"3509
+ ],3510
+ "dev": true,3511
+ "license": "MIT",3512
+ "optional": true,3513
+ "os": [3514
+ "linux"3515
+ ],3516
+ "engines": {3517
+ "node": ">=12"3518
+ }3519
+ },3520
+ "node_modules/vite/node_modules/@esbuild/linux-mips64el": {3521
+ "version": "0.21.5",3522
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",3523
+ "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",3524
+ "cpu": [3525
+ "mips64el"3526
+ ],3527
+ "dev": true,3528
+ "license": "MIT",3529
+ "optional": true,3530
+ "os": [3531
+ "linux"3532
+ ],3533
+ "engines": {3534
+ "node": ">=12"3535
+ }3536
+ },3537
+ "node_modules/vite/node_modules/@esbuild/linux-ppc64": {3538
+ "version": "0.21.5",3539
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",3540
+ "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",3541
+ "cpu": [3542
+ "ppc64"3543
+ ],3544
+ "dev": true,3545
+ "license": "MIT",3546
+ "optional": true,3547
+ "os": [3548
+ "linux"3549
+ ],3550
+ "engines": {3551
+ "node": ">=12"3552
+ }3553
+ },3554
+ "node_modules/vite/node_modules/@esbuild/linux-riscv64": {3555
+ "version": "0.21.5",3556
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",3557
+ "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",3558
+ "cpu": [3559
+ "riscv64"3560
+ ],3561
+ "dev": true,3562
+ "license": "MIT",3563
+ "optional": true,3564
+ "os": [3565
+ "linux"3566
+ ],3567
+ "engines": {3568
+ "node": ">=12"3569
+ }3570
+ },3571
+ "node_modules/vite/node_modules/@esbuild/linux-s390x": {3572
+ "version": "0.21.5",3573
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",3574
+ "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",3575
+ "cpu": [3576
+ "s390x"3577
+ ],3578
+ "dev": true,3579
+ "license": "MIT",3580
+ "optional": true,3581
+ "os": [3582
+ "linux"3583
+ ],3584
+ "engines": {3585
+ "node": ">=12"3586
+ }3587
+ },3588
+ "node_modules/vite/node_modules/@esbuild/linux-x64": {3589
+ "version": "0.21.5",3590
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",3591
+ "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",3592
+ "cpu": [3593
+ "x64"3594
+ ],3595
+ "dev": true,3596
+ "license": "MIT",3597
+ "optional": true,3598
+ "os": [3599
+ "linux"3600
+ ],3601
+ "engines": {3602
+ "node": ">=12"3603
+ }3604
+ },3605
+ "node_modules/vite/node_modules/@esbuild/netbsd-x64": {3606
+ "version": "0.21.5",3607
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",3608
+ "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",3609
+ "cpu": [3610
+ "x64"3611
+ ],3612
+ "dev": true,3613
+ "license": "MIT",3614
+ "optional": true,3615
+ "os": [3616
+ "netbsd"3617
+ ],3618
+ "engines": {3619
+ "node": ">=12"3620
+ }3621
+ },3622
+ "node_modules/vite/node_modules/@esbuild/openbsd-x64": {3623
+ "version": "0.21.5",3624
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",3625
+ "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",3626
+ "cpu": [3627
+ "x64"3628
+ ],3629
+ "dev": true,3630
+ "license": "MIT",3631
+ "optional": true,3632
+ "os": [3633
+ "openbsd"3634
+ ],3635
+ "engines": {3636
+ "node": ">=12"3637
+ }3638
+ },3639
+ "node_modules/vite/node_modules/@esbuild/sunos-x64": {3640
+ "version": "0.21.5",3641
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",3642
+ "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",3643
+ "cpu": [3644
+ "x64"3645
+ ],3646
+ "dev": true,3647
+ "license": "MIT",3648
+ "optional": true,3649
+ "os": [3650
+ "sunos"3651
+ ],3652
+ "engines": {3653
+ "node": ">=12"3654
+ }3655
+ },3656
+ "node_modules/vite/node_modules/@esbuild/win32-arm64": {3657
+ "version": "0.21.5",3658
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",3659
+ "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",3660
+ "cpu": [3661
+ "arm64"3662
+ ],3663
+ "dev": true,3664
+ "license": "MIT",3665
+ "optional": true,3666
+ "os": [3667
+ "win32"3668
+ ],3669
+ "engines": {3670
+ "node": ">=12"3671
+ }3672
+ },3673
+ "node_modules/vite/node_modules/@esbuild/win32-ia32": {3674
+ "version": "0.21.5",3675
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",3676
+ "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",3677
+ "cpu": [3678
+ "ia32"3679
+ ],3680
+ "dev": true,3681
+ "license": "MIT",3682
+ "optional": true,3683
+ "os": [3684
+ "win32"3685
+ ],3686
+ "engines": {3687
+ "node": ">=12"9443688
}9453689
},946
- "node_modules/deepmerge": {947
- "version": "4.3.1",948
- "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",949
- "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",3690
+ "node_modules/vite/node_modules/@esbuild/win32-x64": {3691
+ "version": "0.21.5",3692
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",3693
+ "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",3694
+ "cpu": [3695
+ "x64"3696
+ ],9503697
"dev": true,9513698
"license": "MIT",3699
+ "optional": true,3700
+ "os": [3701
+ "win32"3702
+ ],9523703
"engines": {953
- "node": ">=0.10.0"3704
+ "node": ">=12"9543705
}9553706
},956
- "node_modules/esbuild": {3707
+ "node_modules/vite/node_modules/esbuild": {9573708
"version": "0.21.5",9583709
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",9593710
"integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",@@ -992,324 +3743,76 @@
9923743
"@esbuild/win32-x64": "0.21.5"9933744
}9943745
},995
- "node_modules/estree-walker": {996
- "version": "3.0.3",997
- "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",998
- "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",999
- "license": "MIT",1000
- "dependencies": {1001
- "@types/estree": "^1.0.0"1002
- }1003
- },1004
- "node_modules/fsevents": {1005
- "version": "2.3.3",1006
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",1007
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",1008
- "dev": true,1009
- "hasInstallScript": true,1010
- "license": "MIT",1011
- "optional": true,1012
- "os": [1013
- "darwin"1014
- ],1015
- "engines": {1016
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"1017
- }1018
- },1019
- "node_modules/is-reference": {1020
- "version": "3.0.3",1021
- "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",1022
- "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==",1023
- "license": "MIT",1024
- "dependencies": {1025
- "@types/estree": "^1.0.6"1026
- }1027
- },1028
- "node_modules/kleur": {1029
- "version": "4.1.5",1030
- "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",1031
- "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",3746
+ "node_modules/vitefu": {3747
+ "version": "1.1.3",3748
+ "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.3.tgz",3749
+ "integrity": "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==",10323750
"dev": true,10333751
"license": "MIT",1034
- "engines": {1035
- "node": ">=6"1036
- }1037
- },1038
- "node_modules/locate-character": {1039
- "version": "3.0.0",1040
- "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",1041
- "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",1042
- "license": "MIT"1043
- },1044
- "node_modules/magic-string": {1045
- "version": "0.30.21",1046
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",1047
- "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",1048
- "license": "MIT",1049
- "dependencies": {1050
- "@jridgewell/sourcemap-codec": "^1.5.5"1051
- }1052
- },1053
- "node_modules/mdn-data": {1054
- "version": "2.0.30",1055
- "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",1056
- "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==",1057
- "license": "CC0-1.0"1058
- },1059
- "node_modules/ms": {1060
- "version": "2.1.3",1061
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",1062
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",1063
- "dev": true,1064
- "license": "MIT"1065
- },1066
- "node_modules/nanoid": {1067
- "version": "3.3.19",1068
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.19.tgz",1069
- "integrity": "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==",1070
- "dev": true,1071
- "funding": [1072
- {1073
- "type": "github",1074
- "url": "https://github.com/sponsors/ai"1075
- }3752
+ "workspaces": [3753
+ "tests/deps/*",3754
+ "tests/projects/*",3755
+ "tests/projects/workspace/packages/*"10763756
],1077
- "license": "MIT",1078
- "bin": {1079
- "nanoid": "bin/nanoid.cjs"3757
+ "peerDependencies": {3758
+ "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"10803759
},1081
- "engines": {1082
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"1083
- }1084
- },1085
- "node_modules/periscopic": {1086
- "version": "3.1.0",1087
- "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz",1088
- "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==",1089
- "license": "MIT",1090
- "dependencies": {1091
- "@types/estree": "^1.0.0",1092
- "estree-walker": "^3.0.0",1093
- "is-reference": "^3.0.0"1094
- }1095
- },1096
- "node_modules/picocolors": {1097
- "version": "1.1.1",1098
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",1099
- "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",1100
- "dev": true,1101
- "license": "ISC"1102
- },1103
- "node_modules/postcss": {1104
- "version": "8.5.28",1105
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz",1106
- "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==",1107
- "dev": true,1108
- "funding": [1109
- {1110
- "type": "opencollective",1111
- "url": "https://opencollective.com/postcss/"1112
- },1113
- {1114
- "type": "tidelift",1115
- "url": "https://tidelift.com/funding/github/npm/postcss"1116
- },1117
- {1118
- "type": "github",1119
- "url": "https://github.com/sponsors/ai"3760
+ "peerDependenciesMeta": {3761
+ "vite": {3762
+ "optional": true11203763
}1121
- ],1122
- "license": "MIT",1123
- "dependencies": {1124
- "nanoid": "^3.3.18",1125
- "picocolors": "^1.1.1",1126
- "source-map-js": "^1.2.1"1127
- },1128
- "engines": {1129
- "node": "^10 || ^12 || >=14"1130
- }1131
- },1132
- "node_modules/rollup": {1133
- "version": "4.63.4",1134
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.63.4.tgz",1135
- "integrity": "sha512-4U0liVayNIoLp3GFl1FcI8561WepLnZ1rqfraGh7S9B3Ur5F9S283y8Futii7RUU2C/97tOBmBy7nYvhoiOpbQ==",1136
- "dev": true,1137
- "license": "MIT",1138
- "dependencies": {1139
- "@types/estree": "1.0.9"1140
- },1141
- "bin": {1142
- "rollup": "dist/bin/rollup"1143
- },1144
- "engines": {1145
- "node": ">=18.0.0",1146
- "npm": ">=8.0.0"1147
- },1148
- "optionalDependencies": {1149
- "@napi-rs/lzma-linux-x64-gnu": "1.5.1",1150
- "@rollup/rollup-android-arm-eabi": "4.63.4",1151
- "@rollup/rollup-android-arm64": "4.63.4",1152
- "@rollup/rollup-darwin-arm64": "4.63.4",1153
- "@rollup/rollup-darwin-x64": "4.63.4",1154
- "@rollup/rollup-freebsd-arm64": "4.63.4",1155
- "@rollup/rollup-freebsd-x64": "4.63.4",1156
- "@rollup/rollup-linux-arm-gnueabihf": "4.63.4",1157
- "@rollup/rollup-linux-arm-musleabihf": "4.63.4",1158
- "@rollup/rollup-linux-arm64-gnu": "4.63.4",1159
- "@rollup/rollup-linux-arm64-musl": "4.63.4",1160
- "@rollup/rollup-linux-loong64-gnu": "4.63.4",1161
- "@rollup/rollup-linux-loong64-musl": "4.63.4",1162
- "@rollup/rollup-linux-ppc64-gnu": "4.63.4",1163
- "@rollup/rollup-linux-ppc64-musl": "4.63.4",1164
- "@rollup/rollup-linux-riscv64-gnu": "4.63.4",1165
- "@rollup/rollup-linux-riscv64-musl": "4.63.4",1166
- "@rollup/rollup-linux-s390x-gnu": "4.63.4",1167
- "@rollup/rollup-linux-x64-gnu": "4.63.4",1168
- "@rollup/rollup-linux-x64-musl": "4.63.4",1169
- "@rollup/rollup-openbsd-x64": "4.63.4",1170
- "@rollup/rollup-openharmony-arm64": "4.63.4",1171
- "@rollup/rollup-win32-arm64-msvc": "4.63.4",1172
- "@rollup/rollup-win32-ia32-msvc": "4.63.4",1173
- "@rollup/rollup-win32-x64-gnu": "4.63.4",1174
- "@rollup/rollup-win32-x64-msvc": "4.63.4",1175
- "fsevents": "~2.3.2"1176
- }1177
- },1178
- "node_modules/source-map-js": {1179
- "version": "1.2.1",1180
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",1181
- "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",1182
- "license": "BSD-3-Clause",1183
- "engines": {1184
- "node": ">=0.10.0"1185
- }1186
- },1187
- "node_modules/svelte": {1188
- "version": "4.2.20",1189
- "resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.20.tgz",1190
- "integrity": "sha512-eeEgGc2DtiUil5ANdtd8vPwt9AgaMdnuUFnPft9F5oMvU/FHu5IHFic+p1dR/UOB7XU2mX2yHW+NcTch4DCh5Q==",1191
- "license": "MIT",1192
- "dependencies": {1193
- "@ampproject/remapping": "^2.2.1",1194
- "@jridgewell/sourcemap-codec": "^1.4.15",1195
- "@jridgewell/trace-mapping": "^0.3.18",1196
- "@types/estree": "^1.0.1",1197
- "acorn": "^8.9.0",1198
- "aria-query": "^5.3.0",1199
- "axobject-query": "^4.0.0",1200
- "code-red": "^1.0.3",1201
- "css-tree": "^2.3.1",1202
- "estree-walker": "^3.0.3",1203
- "is-reference": "^3.0.1",1204
- "locate-character": "^3.0.0",1205
- "magic-string": "^0.30.4",1206
- "periscopic": "^3.1.0"1207
- },1208
- "engines": {1209
- "node": ">=16"1210
- }1211
- },1212
- "node_modules/svelte-hmr": {1213
- "version": "0.16.0",1214
- "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.16.0.tgz",1215
- "integrity": "sha512-Gyc7cOS3VJzLlfj7wKS0ZnzDVdv3Pn2IuVeJPk9m2skfhcu5bq3wtIZyQGggr7/Iim5rH5cncyQft/kRLupcnA==",1216
- "dev": true,1217
- "license": "ISC",1218
- "engines": {1219
- "node": "^12.20 || ^14.13.1 || >= 16"1220
- },1221
- "peerDependencies": {1222
- "svelte": "^3.19.0 || ^4.0.0"12233764
}12243765
},1225
- "node_modules/typescript": {1226
- "version": "5.6.3",1227
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",1228
- "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",3766
+ "node_modules/webpack-virtual-modules": {3767
+ "version": "0.6.2",3768
+ "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",3769
+ "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==",12293770
"dev": true,1230
- "license": "Apache-2.0",1231
- "bin": {1232
- "tsc": "bin/tsc",1233
- "tsserver": "bin/tsserver"1234
- },1235
- "engines": {1236
- "node": ">=14.17"1237
- }3771
+ "license": "MIT"12383772
},1239
- "node_modules/vite": {1240
- "version": "5.4.21",1241
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",1242
- "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",3773
+ "node_modules/ws": {3774
+ "version": "8.22.0",3775
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.22.0.tgz",3776
+ "integrity": "sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg==",12433777
"dev": true,12443778
"license": "MIT",1245
- "dependencies": {1246
- "esbuild": "^0.21.3",1247
- "postcss": "^8.4.43",1248
- "rollup": "^4.20.0"1249
- },1250
- "bin": {1251
- "vite": "bin/vite.js"1252
-show full diff (262143 bytes truncated)