A decentralized music tracking and discovery platform built on AT Protocol 🎵 rocksky.app
spotify atproto lastfm musicbrainz scrobbling listenbrainz

add docs proxy and playlists service

+1581 -3
+23
Cargo.lock
··· 2690 2690 ] 2691 2691 2692 2692 [[package]] 2693 + name = "playlists" 2694 + version = "0.1.0" 2695 + dependencies = [ 2696 + "aes", 2697 + "anyhow", 2698 + "async-nats", 2699 + "chrono", 2700 + "clap", 2701 + "ctr", 2702 + "dotenv", 2703 + "duckdb", 2704 + "hex", 2705 + "owo-colors", 2706 + "polars", 2707 + "reqwest", 2708 + "serde", 2709 + "serde_json", 2710 + "sqlx", 2711 + "tokio", 2712 + "tokio-stream", 2713 + ] 2714 + 2715 + [[package]] 2693 2716 name = "polars" 2694 2717 version = "0.46.0" 2695 2718 source = "registry+https://github.com/rust-lang/crates.io-index"
+1
crates/analytics/.env.example
··· 1 + XATA_POSTGRES_URL=""
+3
crates/analytics/src/xata/playlist.rs
··· 7 7 pub name: String, 8 8 pub description: Option<String>, 9 9 pub picture: Option<String>, 10 + pub spotify_link: Option<String>, 11 + pub tidal_link: Option<String>, 12 + pub apple_music_link: Option<String>, 10 13 #[serde(with = "chrono::serde::ts_seconds")] 11 14 pub xata_createdat: DateTime<Utc>, 12 15 #[serde(with = "chrono::serde::ts_seconds")]
+9
crates/playlists/.env.example
··· 1 + JWT_SECRET="" 2 + 3 + SPOTIFY_CLIENT_ID= 4 + SPOTIFY_CLIENT_SECRET= 5 + 6 + SPOTIFY_ENCRYPTION_KEY= 7 + SPOTIFY_ENCRYPTION_IV= 8 + 9 + XATA_POSTGRES_URL=""
+3
crates/playlists/.gitignore
··· 1 + .env 2 + *.ddb 3 + *.ddb.wal
+37
crates/playlists/Cargo.toml
··· 1 + [package] 2 + name = "playlists" 3 + version = "0.1.0" 4 + authors.workspace = true 5 + edition.workspace = true 6 + license.workspace = true 7 + repository.workspace = true 8 + 9 + [dependencies] 10 + aes = "0.8.4" 11 + ctr = "0.9.2" 12 + duckdb = { version = "1.2.0", features = ["chrono"] } 13 + async-nats = "0.39.0" 14 + serde = { version = "1.0.217", features = ["derive"] } 15 + serde_json = "1.0.139" 16 + sqlx = { version = "0.8.3", features = [ 17 + "runtime-tokio", 18 + "tls-rustls", 19 + "postgres", 20 + "chrono", 21 + "derive", 22 + "macros", 23 + ] } 24 + tokio = { version = "1.43.0", features = ["full"] } 25 + owo-colors = "4.1.0" 26 + dotenv = "0.15.0" 27 + chrono = { version = "0.4.39", features = ["serde"] } 28 + anyhow = "1.0.96" 29 + polars = "0.46.0" 30 + clap = "4.5.31" 31 + tokio-stream = { version = "0.1.17", features = ["full"] } 32 + reqwest = { version = "0.12.12", features = [ 33 + "rustls-tls", 34 + "json", 35 + "multipart", 36 + ], default-features = false } 37 + hex = "0.4.3"
+218
crates/playlists/src/core.rs
··· 1 + use std::env; 2 + 3 + use anyhow::Error; 4 + use duckdb::{params, Connection}; 5 + use owo_colors::OwoColorize; 6 + use sqlx::{Pool, Postgres}; 7 + 8 + use crate::{crypto::decrypt_aes_256_ctr, types::{self, spotify_token::SpotifyTokenWithEmail}, xata}; 9 + 10 + pub fn create_tables(conn: &Connection) -> Result<(), Error> { 11 + conn.execute_batch(r#" 12 + CREATE TABLE IF NOT EXISTS playlists ( 13 + id TEXT PRIMARY KEY, 14 + name TEXT, 15 + description TEXT, 16 + picture TEXT, 17 + spotify_link TEXT, 18 + tidal_link TEXT, 19 + apple_music_link TEXT, 20 + xata_createdat TIMESTAMP, 21 + xata_updatedat TIMESTAMP, 22 + uri TEXT, 23 + created_by TEXT 24 + ); 25 + CREATE TABLE IF NOT EXISTS tracks ( 26 + id VARCHAR PRIMARY KEY, 27 + title VARCHAR, 28 + artist VARCHAR, 29 + album_artist VARCHAR, 30 + album_art VARCHAR, 31 + album VARCHAR, 32 + track_number INTEGER, 33 + duration INTEGER, 34 + mb_id VARCHAR, 35 + youtube_link VARCHAR, 36 + spotify_link VARCHAR, 37 + tidal_link VARCHAR, 38 + apple_music_link VARCHAR, 39 + sha256 VARCHAR NOT NULL, 40 + lyrics TEXT, 41 + composer VARCHAR, 42 + genre VARCHAR, 43 + disc_number INTEGER, 44 + copyright_message VARCHAR, 45 + label VARCHAR, 46 + uri VARCHAR, 47 + artist_uri VARCHAR, 48 + album_uri VARCHAR, 49 + created_at TIMESTAMP, 50 + ); 51 + CREATE TABLE IF NOT EXISTS users ( 52 + id VARCHAR PRIMARY KEY, 53 + display_name VARCHAR, 54 + did VARCHAR, 55 + handle VARCHAR, 56 + avatar VARCHAR, 57 + ); 58 + CREATE TABLE IF NOT EXISTS playlist_tracks ( 59 + id VARCHAR PRIMARY KEY, 60 + playlist_id VARCHAR, 61 + track_id VARCHAR, 62 + added_by VARCHAR, 63 + created_at TIMESTAMP, 64 + FOREIGN KEY (playlist_id) REFERENCES playlists(id), 65 + FOREIGN KEY (track_id) REFERENCES tracks(id), 66 + ); 67 + CREATE TABLE IF NOT EXISTS user_playlists ( 68 + id VARCHAR PRIMARY KEY, 69 + user_id VARCHAR, 70 + playlist_id VARCHAR, 71 + created_at TIMESTAMP, 72 + FOREIGN KEY (user_id) REFERENCES users(id), 73 + FOREIGN KEY (playlist_id) REFERENCES playlists(id), 74 + ); 75 + 76 + CREATE UNIQUE INDEX IF NOT EXISTS user_playlists_unique_index ON user_playlists (user_id, playlist_id); 77 + "#)?; 78 + Ok(()) 79 + } 80 + 81 + 82 + pub async fn load_users(conn: &Connection, pool: &Pool<Postgres>) -> Result<(), Error> { 83 + let users: Vec<xata::user::User> = sqlx::query_as(r#" 84 + SELECT * FROM users 85 + "#) 86 + .fetch_all(pool) 87 + .await?; 88 + 89 + for (i, user) in users.clone().into_iter().enumerate() { 90 + println!("user {} - {}", i, user.display_name.bright_green()); 91 + match conn.execute( 92 + "INSERT INTO users ( 93 + id, 94 + display_name, 95 + did, 96 + handle, 97 + avatar 98 + ) VALUES (?, 99 + ?, 100 + ?, 101 + ?, 102 + ?) ON CONFLICT DO NOTHING", 103 + params![ 104 + user.xata_id, 105 + user.display_name, 106 + user.did, 107 + user.handle, 108 + user.avatar, 109 + ], 110 + ) { 111 + Ok(_) => (), 112 + Err(e) => println!("error: {}", e), 113 + } 114 + } 115 + 116 + println!("users: {:?}", users.len()); 117 + Ok(()) 118 + } 119 + 120 + pub async fn find_spotify_users( 121 + pool: &Pool<Postgres>, 122 + offset: usize, 123 + limit: usize 124 + ) -> Result<Vec<(String, String, String, String)>, Error> { 125 + let results: Vec<SpotifyTokenWithEmail> = sqlx::query_as(r#" 126 + SELECT * FROM spotify_tokens 127 + LEFT JOIN spotify_accounts ON spotify_tokens.user_id = spotify_accounts.user_id 128 + LEFT JOIN users ON spotify_accounts.user_id = users.xata_id 129 + LIMIT $1 OFFSET $2 130 + "#) 131 + .bind(limit as i64) 132 + .bind(offset as i64) 133 + .fetch_all(pool) 134 + .await?; 135 + 136 + let mut user_tokens = vec![]; 137 + 138 + for result in &results { 139 + let token = decrypt_aes_256_ctr( 140 + &result.refresh_token, 141 + &hex::decode(env::var("SPOTIFY_ENCRYPTION_KEY")?)? 142 + )?; 143 + user_tokens.push((result.email.clone(), token, result.did.clone(), result.user_id.clone())); 144 + } 145 + 146 + Ok(user_tokens) 147 + } 148 + 149 + pub async fn save_playlists(pool: &Pool<Postgres>, conn: &Connection, playlists: Vec<types::playlist::Playlist>, user_id: &str) -> Result<(), Error> { 150 + for playlist in playlists { 151 + println!("Saving playlist: {} - {} tracks", playlist.name.bright_green(), playlist.tracks.total); 152 + sqlx::query(r#" 153 + INSERT INTO playlists (name, description, picture, spotify_link, created_by) 154 + VALUES ($1, $2, $3, $4, $5) 155 + ON CONFLICT (spotify_link) DO UPDATE set 156 + name = EXCLUDED.name, 157 + description = EXCLUDED.description, 158 + picture = EXCLUDED.picture, 159 + spotify_link = EXCLUDED.spotify_link, 160 + created_by = EXCLUDED.created_by 161 + "#) 162 + .bind(playlist.name) 163 + .bind(playlist.description) 164 + .bind(playlist.images.first().map(|i| i.url.clone())) 165 + .bind(&playlist.external_urls.spotify) 166 + .bind(user_id) 167 + .execute(pool) 168 + .await?; 169 + 170 + let playlist: Vec<xata::playlist::Playlist> = sqlx::query_as(r#"SELECT * FROM playlists WHERE spotify_link = $1"#) 171 + .bind(&playlist.external_urls.spotify) 172 + .fetch_all(pool) 173 + .await?; 174 + 175 + let playlist = playlist.first().unwrap(); 176 + 177 + sqlx::query(r#" 178 + INSERT INTO user_playlists (user_id, playlist_id) 179 + VALUES ($1, $2) 180 + ON CONFLICT (user_id, playlist_id) DO NOTHING 181 + "#) 182 + .bind(user_id) 183 + .bind(&playlist.xata_id) 184 + .execute(pool) 185 + .await?; 186 + 187 + let user_playlist: Vec<xata::user_playlist::UserPlaylist> = sqlx::query_as("SELECT * FROM user_playlists WHERE user_id = $1 AND playlist_id = $2") 188 + .bind(user_id) 189 + .bind(&playlist.xata_id) 190 + .fetch_all(pool) 191 + .await?; 192 + let user_playlist = user_playlist.first().unwrap(); 193 + 194 + conn.execute("INSERT INTO playlists (id, name, description, picture, spotify_link, uri, created_by) VALUES ($1, $2, $3, $4, $5, $6, $7) ON CONFLICT DO NOTHING", 195 + params![ 196 + &playlist.xata_id, 197 + &playlist.name, 198 + playlist.description, 199 + playlist.picture, 200 + playlist.spotify_link, 201 + playlist.uri, 202 + user_id 203 + ] 204 + )?; 205 + 206 + conn.execute( 207 + "INSERT INTO user_playlists (id, user_id, playlist_id, created_at) VALUES ($1, $2, $3, $4) ON CONFLICT DO NOTHING", 208 + params![ 209 + &user_playlist.xata_id, 210 + user_id, 211 + &playlist.xata_id, 212 + chrono::Utc::now() 213 + ] 214 + )?; 215 + 216 + } 217 + Ok(()) 218 + }
+22
crates/playlists/src/crypto.rs
··· 1 + use std::env; 2 + 3 + use aes::{ 4 + cipher::{KeyIvInit, StreamCipher}, 5 + Aes256, 6 + }; 7 + use anyhow::Error; 8 + use hex::decode; 9 + 10 + type Aes256Ctr = ctr::Ctr64BE<Aes256>; 11 + 12 + pub fn decrypt_aes_256_ctr(encrypted_text: &str, key: &[u8]) -> Result<String, Error> { 13 + let iv = decode(env::var("SPOTIFY_ENCRYPTION_IV")?)?; 14 + let ciphertext = decode(encrypted_text)?; 15 + 16 + let mut cipher = 17 + Aes256Ctr::new_from_slices(key, &iv).map_err(|_| Error::msg("Invalid key or IV"))?; 18 + let mut decrypted_data = ciphertext.clone(); 19 + cipher.apply_keystream(&mut decrypted_data); 20 + 21 + Ok(String::from_utf8(decrypted_data)?) 22 + }
+5
crates/playlists/src/lib.rs
··· 1 + pub mod core; 2 + pub mod crypto; 3 + pub mod spotify; 4 + pub mod types; 5 + pub mod xata;
+48
crates/playlists/src/main.rs
··· 1 + use core::{create_tables, find_spotify_users, load_users, save_playlists}; 2 + use std::env; 3 + 4 + use anyhow::Error; 5 + use dotenv::dotenv; 6 + use duckdb::Connection; 7 + use spotify::get_user_playlists; 8 + use sqlx::postgres::PgPoolOptions; 9 + 10 + pub mod types; 11 + pub mod crypto; 12 + pub mod xata; 13 + pub mod core; 14 + pub mod spotify; 15 + 16 + #[tokio::main] 17 + async fn main() -> Result<(), Error> { 18 + dotenv().ok(); 19 + 20 + let conn = Connection::open("./rocksky-playlists.ddb")?; 21 + create_tables(&conn)?; 22 + 23 + let pool = PgPoolOptions::new().max_connections(5).connect(&env::var("XATA_POSTGRES_URL")?).await?; 24 + let users = find_spotify_users(&pool, 0, 100).await?; 25 + 26 + load_users(&conn, &pool).await?; 27 + 28 + sqlx::query(r#" 29 + CREATE UNIQUE INDEX IF NOT EXISTS user_playlists_unique_index ON user_playlists (user_id, playlist_id) 30 + "#) 31 + .execute(&pool) 32 + .await?; 33 + 34 + for user in users { 35 + let token = user.1.clone(); 36 + let user_id = user.3.clone(); 37 + let playlists = get_user_playlists(token).await?; 38 + save_playlists(&pool, &conn, playlists, &user_id).await?; 39 + } 40 + 41 + println!("Done!"); 42 + 43 + conn.close() 44 + .map_err(|(_, e)| Error::new(e))?; 45 + 46 + Ok(()) 47 + } 48 +
+67
crates/playlists/src/spotify.rs
··· 1 + use std::env; 2 + 3 + use anyhow::Error; 4 + use reqwest::Client; 5 + 6 + use crate::types::{self, token::AccessToken}; 7 + 8 + pub async fn refresh_token(token: &str) -> Result<AccessToken, Error> { 9 + if env::var("SPOTIFY_CLIENT_ID").is_err() || env::var("SPOTIFY_CLIENT_SECRET").is_err() { 10 + panic!("Please set SPOTIFY_CLIENT_ID and SPOTIFY_CLIENT_SECRET environment variables"); 11 + } 12 + 13 + let client_id = env::var("SPOTIFY_CLIENT_ID")?; 14 + let client_secret = env::var("SPOTIFY_CLIENT_SECRET")?; 15 + 16 + let client = Client::new(); 17 + 18 + let response = client.post("https://accounts.spotify.com/api/token") 19 + .basic_auth(&client_id, Some(client_secret)) 20 + .form(&[ 21 + ("grant_type", "refresh_token"), 22 + ("refresh_token", token), 23 + ("client_id", &client_id) 24 + ]) 25 + .send() 26 + .await?; 27 + let token = response.json::<AccessToken>().await?; 28 + Ok(token) 29 + } 30 + 31 + 32 + 33 + pub async fn get_user_playlists( 34 + token: String, 35 + ) -> Result<Vec<types::playlist::Playlist>, Error>{ 36 + let token = refresh_token(&token).await?; 37 + let client = Client::new(); 38 + let response = client 39 + .get("https://api.spotify.com/v1/me/playlists") 40 + .header("Authorization", format!("Bearer {}", token.access_token)) 41 + .send() 42 + .await?; 43 + let playlists = response.json::<types::playlist::SpotifyResponse>().await?; 44 + let mut all_playlists = vec![]; 45 + 46 + for playlist in playlists.items { 47 + all_playlists.push( 48 + get_playlist(&playlist.id, &token.access_token).await? 49 + ); 50 + // wait for 1 second to avoid rate limiting 51 + tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; 52 + } 53 + 54 + Ok(all_playlists) 55 + } 56 + 57 + pub async fn get_playlist(id: &str, token: &str) -> Result<types::playlist::Playlist, Error> { 58 + let client = Client::new(); 59 + let response = client 60 + .get(format!("https://api.spotify.com/v1/playlists/{}", id)) 61 + .header("Authorization", format!("Bearer {}", token)) 62 + .send() 63 + .await?; 64 + 65 + let playlist = response.json::<types::playlist::Playlist>().await?; 66 + Ok(playlist) 67 + }
+3
crates/playlists/src/types/mod.rs
··· 1 + pub mod playlist; 2 + pub mod spotify_token; 3 + pub mod token;
+138
crates/playlists/src/types/playlist.rs
··· 1 + use serde::{Deserialize, Serialize}; 2 + 3 + #[derive(Debug, Serialize, Deserialize)] 4 + pub struct SpotifyResponse { 5 + pub href: String, 6 + pub limit: u32, 7 + pub next: Option<String>, 8 + pub offset: u32, 9 + pub previous: Option<String>, 10 + pub total: u32, 11 + pub items: Vec<Playlist>, 12 + } 13 + 14 + #[derive(Debug, Serialize, Deserialize)] 15 + pub struct Playlist { 16 + pub collaborative: bool, 17 + pub description: String, 18 + pub external_urls: ExternalUrls, 19 + pub href: String, 20 + pub id: String, 21 + pub images: Vec<Image>, 22 + pub name: String, 23 + pub owner: Owner, 24 + pub primary_color: Option<String>, 25 + pub public: Option<bool>, 26 + pub snapshot_id: String, 27 + pub tracks: Tracks, 28 + pub r#type: String, 29 + pub uri: String, 30 + } 31 + 32 + #[derive(Debug, Serialize, Deserialize)] 33 + pub struct ExternalUrls { 34 + pub spotify: String, 35 + } 36 + 37 + #[derive(Debug, Serialize, Deserialize)] 38 + pub struct Image { 39 + pub height: u32, 40 + pub url: String, 41 + pub width: u32, 42 + } 43 + 44 + #[derive(Debug, Serialize, Deserialize)] 45 + pub struct Owner { 46 + pub display_name: Option<String>, 47 + pub external_urls: ExternalUrls, 48 + pub href: String, 49 + pub id: String, 50 + pub r#type: String, 51 + pub uri: String, 52 + } 53 + 54 + #[derive(Debug, Serialize, Deserialize)] 55 + pub struct Tracks { 56 + pub href: String, 57 + pub limit: Option<u32>, 58 + pub next: Option<String>, 59 + pub offset: Option<u32>, 60 + pub previous: Option<String>, 61 + pub total: u32, 62 + pub items: Option<Vec<TrackItem>>, 63 + } 64 + 65 + #[derive(Debug, Serialize, Deserialize)] 66 + pub struct TrackItem { 67 + pub added_at: String, 68 + pub added_by: Owner, 69 + pub is_local: bool, 70 + pub track: Track, 71 + } 72 + 73 + #[derive(Debug, Serialize, Deserialize)] 74 + pub struct Track { 75 + pub album: Album, 76 + pub artists: Vec<Artist>, 77 + pub available_markets: Vec<String>, 78 + pub disc_number: u32, 79 + pub duration_ms: u32, 80 + pub explicit: bool, 81 + pub external_ids: ExternalIds, 82 + pub external_urls: ExternalUrls, 83 + pub href: String, 84 + pub id: String, 85 + pub is_playable: Option<bool>, 86 + pub linked_from: Option<LinkedFrom>, 87 + pub restrictions: Option<Restrictions>, 88 + pub name: String, 89 + pub popularity: u32, 90 + pub preview_url: Option<String>, 91 + pub track_number: u32, 92 + pub r#type: String, 93 + pub uri: String, 94 + pub is_local: bool, 95 + } 96 + 97 + #[derive(Debug, Serialize, Deserialize)] 98 + pub struct Album { 99 + pub album_type: String, 100 + pub total_tracks: u32, 101 + pub available_markets: Vec<String>, 102 + pub external_urls: ExternalUrls, 103 + pub href: String, 104 + pub id: String, 105 + pub images: Vec<Image>, 106 + pub name: String, 107 + pub release_date: String, 108 + pub release_date_precision: String, 109 + pub restrictions: Option<Restrictions>, 110 + pub r#type: String, 111 + pub uri: String, 112 + pub artists: Vec<Artist>, 113 + } 114 + 115 + #[derive(Debug, Serialize, Deserialize)] 116 + pub struct Artist { 117 + pub external_urls: ExternalUrls, 118 + pub href: String, 119 + pub id: String, 120 + pub name: String, 121 + pub r#type: String, 122 + pub uri: String, 123 + } 124 + 125 + #[derive(Debug, Serialize, Deserialize)] 126 + pub struct ExternalIds { 127 + pub isrc: String, 128 + pub ean: Option<String>, 129 + pub upc: Option<String>, 130 + } 131 + 132 + #[derive(Debug, Serialize, Deserialize)] 133 + pub struct LinkedFrom {} 134 + 135 + #[derive(Debug, Serialize, Deserialize)] 136 + pub struct Restrictions { 137 + pub reason: String, 138 + }
+30
crates/playlists/src/types/spotify_token.rs
··· 1 + use chrono::{DateTime, Utc}; 2 + use serde::Deserialize; 3 + 4 + #[derive(Debug, Deserialize, sqlx::FromRow, Default, Clone)] 5 + pub struct SpotifyToken { 6 + pub xata_id: String, 7 + pub xata_version: i32, 8 + #[serde(with = "chrono::serde::ts_seconds")] 9 + pub xata_createdat: DateTime<Utc>, 10 + #[serde(with = "chrono::serde::ts_seconds")] 11 + pub xata_updatedat: DateTime<Utc>, 12 + pub user_id: String, 13 + pub access_token: String, 14 + pub refresh_token: String, 15 + } 16 + 17 + #[derive(Debug, Deserialize, sqlx::FromRow, Default, Clone)] 18 + pub struct SpotifyTokenWithEmail { 19 + pub xata_id: String, 20 + pub xata_version: i32, 21 + #[serde(with = "chrono::serde::ts_seconds")] 22 + pub xata_createdat: DateTime<Utc>, 23 + #[serde(with = "chrono::serde::ts_seconds")] 24 + pub xata_updatedat: DateTime<Utc>, 25 + pub user_id: String, 26 + pub access_token: String, 27 + pub refresh_token: String, 28 + pub email: String, 29 + pub did: String, 30 + }
+9
crates/playlists/src/types/token.rs
··· 1 + use serde::Deserialize; 2 + 3 + #[derive(Debug, Deserialize)] 4 + pub struct AccessToken { 5 + pub access_token: String, 6 + pub token_type: String, 7 + pub scope: String, 8 + pub expires_in: u32, 9 + }
+6
crates/playlists/src/xata/mod.rs
··· 1 + pub mod playlist; 2 + pub mod playlist_track; 3 + pub mod track; 4 + pub mod user; 5 + pub mod user_playlist; 6 + pub mod user_track;
+19
crates/playlists/src/xata/playlist.rs
··· 1 + use chrono::{DateTime, Utc}; 2 + use serde::Deserialize; 3 + 4 + #[derive(Debug, sqlx::FromRow, Deserialize, Clone)] 5 + pub struct Playlist { 6 + pub xata_id: String, 7 + pub name: String, 8 + pub description: Option<String>, 9 + pub picture: Option<String>, 10 + pub spotify_link: Option<String>, 11 + pub tidal_link: Option<String>, 12 + pub apple_music_link: Option<String>, 13 + #[serde(with = "chrono::serde::ts_seconds")] 14 + pub xata_createdat: DateTime<Utc>, 15 + #[serde(with = "chrono::serde::ts_seconds")] 16 + pub xata_updatedat: DateTime<Utc>, 17 + pub uri: Option<String>, 18 + pub created_by: String, 19 + }
+11
crates/playlists/src/xata/playlist_track.rs
··· 1 + use serde::Deserialize; 2 + 3 + #[derive(Debug, sqlx::FromRow, Deserialize, Clone)] 4 + pub struct PlaylistTrack { 5 + pub xata_id: String, 6 + pub playlist_id: String, 7 + pub track_id: String, 8 + pub added_by: String, 9 + #[serde(with = "chrono::serde::ts_seconds")] 10 + pub xata_createdat: chrono::DateTime<chrono::Utc>, 11 + }
+31
crates/playlists/src/xata/track.rs
··· 1 + use chrono::{DateTime, Utc}; 2 + use serde::{Deserialize, Serialize}; 3 + 4 + #[derive(Debug, sqlx::FromRow, Serialize, Deserialize, Clone)] 5 + pub struct Track { 6 + pub xata_id: String, 7 + pub title: String, 8 + pub artist: String, 9 + pub album_artist: String, 10 + pub album_art: Option<String>, 11 + pub album: String, 12 + pub track_number: i32, 13 + pub duration: i32, 14 + pub mb_id: Option<String>, 15 + pub youtube_link: Option<String>, 16 + pub spotify_link: Option<String>, 17 + pub tidal_link: Option<String>, 18 + pub apple_music_link: Option<String>, 19 + pub sha256: String, 20 + pub lyrics: Option<String>, 21 + pub composer: Option<String>, 22 + pub genre: Option<String>, 23 + pub disc_number: i32, 24 + pub copyright_message: Option<String>, 25 + pub label: Option<String>, 26 + pub uri: Option<String>, 27 + pub artist_uri: Option<String>, 28 + pub album_uri: Option<String>, 29 + #[serde(with = "chrono::serde::ts_seconds")] 30 + pub xata_createdat: DateTime<Utc>, 31 + }
+13
crates/playlists/src/xata/user.rs
··· 1 + use chrono::{DateTime, Utc}; 2 + use serde::Deserialize; 3 + 4 + #[derive(Debug, sqlx::FromRow, Deserialize, Clone)] 5 + pub struct User { 6 + pub xata_id: String, 7 + pub display_name: String, 8 + pub did: String, 9 + pub handle: String, 10 + pub avatar: String, 11 + #[serde(with = "chrono::serde::ts_seconds")] 12 + pub xata_createdat: DateTime<Utc>, 13 + }
+10
crates/playlists/src/xata/user_playlist.rs
··· 1 + use serde::Deserialize; 2 + 3 + #[derive(Debug, sqlx::FromRow, Deserialize, Clone)] 4 + pub struct UserPlaylist { 5 + pub xata_id: String, 6 + pub user_id: String, 7 + pub playlist_id: String, 8 + #[serde(with = "chrono::serde::ts_seconds")] 9 + pub xata_createdat: chrono::DateTime<chrono::Utc>, 10 + }
+10
crates/playlists/src/xata/user_track.rs
··· 1 + use serde::Deserialize; 2 + 3 + #[derive(Debug, sqlx::FromRow, Deserialize, Clone)] 4 + pub struct UserTrack { 5 + pub xata_id: String, 6 + pub user_id: String, 7 + pub track_id: String, 8 + #[serde(with = "chrono::serde::ts_seconds")] 9 + pub xata_createdat: chrono::DateTime<chrono::Utc>, 10 + }
+9
crates/spotify/.env.example
··· 1 + JWT_SECRET="" 2 + 3 + SPOTIFY_CLIENT_ID= 4 + SPOTIFY_CLIENT_SECRET= 5 + 6 + SPOTIFY_ENCRYPTION_KEY= 7 + SPOTIFY_ENCRYPTION_IV= 8 + 9 + XATA_POSTGRES_URL=""
+12
rockskyapi/rocksky-doc/.editorconfig
··· 1 + # http://editorconfig.org 2 + root = true 3 + 4 + [*] 5 + indent_style = tab 6 + end_of_line = lf 7 + charset = utf-8 8 + trim_trailing_whitespace = true 9 + insert_final_newline = true 10 + 11 + [*.yml] 12 + indent_style = space
+172
rockskyapi/rocksky-doc/.gitignore
··· 1 + # Logs 2 + 3 + logs 4 + _.log 5 + npm-debug.log_ 6 + yarn-debug.log* 7 + yarn-error.log* 8 + lerna-debug.log* 9 + .pnpm-debug.log* 10 + 11 + # Diagnostic reports (https://nodejs.org/api/report.html) 12 + 13 + report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json 14 + 15 + # Runtime data 16 + 17 + pids 18 + _.pid 19 + _.seed 20 + \*.pid.lock 21 + 22 + # Directory for instrumented libs generated by jscoverage/JSCover 23 + 24 + lib-cov 25 + 26 + # Coverage directory used by tools like istanbul 27 + 28 + coverage 29 + \*.lcov 30 + 31 + # nyc test coverage 32 + 33 + .nyc_output 34 + 35 + # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 36 + 37 + .grunt 38 + 39 + # Bower dependency directory (https://bower.io/) 40 + 41 + bower_components 42 + 43 + # node-waf configuration 44 + 45 + .lock-wscript 46 + 47 + # Compiled binary addons (https://nodejs.org/api/addons.html) 48 + 49 + build/Release 50 + 51 + # Dependency directories 52 + 53 + node_modules/ 54 + jspm_packages/ 55 + 56 + # Snowpack dependency directory (https://snowpack.dev/) 57 + 58 + web_modules/ 59 + 60 + # TypeScript cache 61 + 62 + \*.tsbuildinfo 63 + 64 + # Optional npm cache directory 65 + 66 + .npm 67 + 68 + # Optional eslint cache 69 + 70 + .eslintcache 71 + 72 + # Optional stylelint cache 73 + 74 + .stylelintcache 75 + 76 + # Microbundle cache 77 + 78 + .rpt2_cache/ 79 + .rts2_cache_cjs/ 80 + .rts2_cache_es/ 81 + .rts2_cache_umd/ 82 + 83 + # Optional REPL history 84 + 85 + .node_repl_history 86 + 87 + # Output of 'npm pack' 88 + 89 + \*.tgz 90 + 91 + # Yarn Integrity file 92 + 93 + .yarn-integrity 94 + 95 + # dotenv environment variable files 96 + 97 + .env 98 + .env.development.local 99 + .env.test.local 100 + .env.production.local 101 + .env.local 102 + 103 + # parcel-bundler cache (https://parceljs.org/) 104 + 105 + .cache 106 + .parcel-cache 107 + 108 + # Next.js build output 109 + 110 + .next 111 + out 112 + 113 + # Nuxt.js build / generate output 114 + 115 + .nuxt 116 + dist 117 + 118 + # Gatsby files 119 + 120 + .cache/ 121 + 122 + # Comment in the public line in if your project uses Gatsby and not Next.js 123 + 124 + # https://nextjs.org/blog/next-9-1#public-directory-support 125 + 126 + # public 127 + 128 + # vuepress build output 129 + 130 + .vuepress/dist 131 + 132 + # vuepress v2.x temp and cache directory 133 + 134 + .temp 135 + .cache 136 + 137 + # Docusaurus cache and generated files 138 + 139 + .docusaurus 140 + 141 + # Serverless directories 142 + 143 + .serverless/ 144 + 145 + # FuseBox cache 146 + 147 + .fusebox/ 148 + 149 + # DynamoDB Local files 150 + 151 + .dynamodb/ 152 + 153 + # TernJS port file 154 + 155 + .tern-port 156 + 157 + # Stores VSCode versions used for testing VSCode extensions 158 + 159 + .vscode-test 160 + 161 + # yarn v2 162 + 163 + .yarn/cache 164 + .yarn/unplugged 165 + .yarn/build-state.yml 166 + .yarn/install-state.gz 167 + .pnp.\* 168 + 169 + # wrangler project 170 + 171 + .dev.vars 172 + .wrangler/
+6
rockskyapi/rocksky-doc/.prettierrc
··· 1 + { 2 + "printWidth": 140, 3 + "singleQuote": true, 4 + "semi": true, 5 + "useTabs": true 6 + }
+5
rockskyapi/rocksky-doc/.vscode/settings.json
··· 1 + { 2 + "files.associations": { 3 + "wrangler.json": "jsonc" 4 + } 5 + }
+448
rockskyapi/rocksky-doc/bun.lock
··· 1 + { 2 + "lockfileVersion": 1, 3 + "workspaces": { 4 + "": { 5 + "name": "white-scene-4cbd", 6 + "devDependencies": { 7 + "@cloudflare/vitest-pool-workers": "^0.6.4", 8 + "@cloudflare/workers-types": "^4.20250303.0", 9 + "typescript": "^5.5.2", 10 + "vitest": "~2.1.9", 11 + "wrangler": "^3.113.0", 12 + }, 13 + }, 14 + }, 15 + "packages": { 16 + "@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.3.4", "", { "dependencies": { "mime": "^3.0.0" } }, "sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q=="], 17 + 18 + "@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.0.0", "", { "peerDependencies": { "unenv": "2.0.0-rc.8", "workerd": "^1.20250124.0" }, "optionalPeers": ["workerd"] }, "sha512-Ar4HixFYP8e990JPACno3nqe10QsjS3yVWr48z5Vop5LygdnvPa5cfNHxGoQSPavvg5aaGnF0VAWc3JJ1tBKuQ=="], 19 + 20 + "@cloudflare/vitest-pool-workers": ["@cloudflare/vitest-pool-workers@0.6.16", "", { "dependencies": { "birpc": "0.2.14", "cjs-module-lexer": "^1.2.3", "devalue": "^4.3.0", "esbuild": "0.17.19", "miniflare": "3.20250204.1", "semver": "^7.5.1", "wrangler": "3.109.1", "zod": "^3.22.3" }, "peerDependencies": { "@vitest/runner": "2.0.x - 2.1.x", "@vitest/snapshot": "2.0.x - 2.1.x", "vitest": "2.0.x - 2.1.x" } }, "sha512-fKGP+jMyrIh54QncFa7A5NE3k8fWW6oCU4v9IW6Hiu7cAVKBvhdPUAfYBQS7EU1TsjGJl/y5N4Urds3PUFocoQ=="], 21 + 22 + "@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20250224.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-sBbaAF2vgQ9+T50ik1ihekdepStBp0w4fvNghBfXIw1iWqfNWnypcjDMmi/7JhXJt2uBxBrSlXCvE5H7Gz+kbw=="], 23 + 24 + "@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20250224.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-naetGefgjAaDbEacpwaVruJXNwxmRRL7v3ppStgEiqAlPmTpQ/Edjn2SQ284QwOw3MvaVPHrWcaTBupUpkqCyg=="], 25 + 26 + "@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20250224.0", "", { "os": "linux", "cpu": "x64" }, "sha512-BtUvuj91rgB06TUAkLYvedghUA8nDFiLcY3GC7MXmWhxCxGmY4PWkrKq/+uHjrhwknCcXrE4aFsM28ja8EcAGA=="], 27 + 28 + "@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20250224.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-Gr4MPNi+BvwjfWF7clx0dJY2Vm4suaW5FtAQwrfqJmPtN5zb/BP16VZxxnFRMy377dP7ycoxpKfZZ6Q8RVGvbA=="], 29 + 30 + "@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20250224.0", "", { "os": "win32", "cpu": "x64" }, "sha512-x2iF1CsmYmmPEorWb1GRpAAouX5rRjmhuHMC259ojIlozR4G0LarlB9XfmeLEvtw537Ea0kJ6SOhjvUcWzxSvA=="], 31 + 32 + "@cloudflare/workers-types": ["@cloudflare/workers-types@4.20250303.0", "", {}, "sha512-O7F7nRT4bbmwHf3gkRBLfJ7R6vHIJ/oZzWdby6obOiw2yavUfp/AIwS7aO2POu5Cv8+h3TXS3oHs3kKCZLraUA=="], 33 + 34 + "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="], 35 + 36 + "@emnapi/runtime": ["@emnapi/runtime@1.3.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw=="], 37 + 38 + "@esbuild-plugins/node-globals-polyfill": ["@esbuild-plugins/node-globals-polyfill@0.2.3", "", { "peerDependencies": { "esbuild": "*" } }, "sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw=="], 39 + 40 + "@esbuild-plugins/node-modules-polyfill": ["@esbuild-plugins/node-modules-polyfill@0.2.2", "", { "dependencies": { "escape-string-regexp": "^4.0.0", "rollup-plugin-node-polyfills": "^0.2.1" }, "peerDependencies": { "esbuild": "*" } }, "sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA=="], 41 + 42 + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="], 43 + 44 + "@esbuild/android-arm": ["@esbuild/android-arm@0.17.19", "", { "os": "android", "cpu": "arm" }, "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A=="], 45 + 46 + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.17.19", "", { "os": "android", "cpu": "arm64" }, "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA=="], 47 + 48 + "@esbuild/android-x64": ["@esbuild/android-x64@0.17.19", "", { "os": "android", "cpu": "x64" }, "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww=="], 49 + 50 + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.17.19", "", { "os": "darwin", "cpu": "arm64" }, "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg=="], 51 + 52 + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.17.19", "", { "os": "darwin", "cpu": "x64" }, "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw=="], 53 + 54 + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.17.19", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ=="], 55 + 56 + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.17.19", "", { "os": "freebsd", "cpu": "x64" }, "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ=="], 57 + 58 + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.17.19", "", { "os": "linux", "cpu": "arm" }, "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA=="], 59 + 60 + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.17.19", "", { "os": "linux", "cpu": "arm64" }, "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg=="], 61 + 62 + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.17.19", "", { "os": "linux", "cpu": "ia32" }, "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ=="], 63 + 64 + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.17.19", "", { "os": "linux", "cpu": "none" }, "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ=="], 65 + 66 + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.17.19", "", { "os": "linux", "cpu": "none" }, "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A=="], 67 + 68 + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.17.19", "", { "os": "linux", "cpu": "ppc64" }, "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg=="], 69 + 70 + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.17.19", "", { "os": "linux", "cpu": "none" }, "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA=="], 71 + 72 + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.17.19", "", { "os": "linux", "cpu": "s390x" }, "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q=="], 73 + 74 + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.17.19", "", { "os": "linux", "cpu": "x64" }, "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw=="], 75 + 76 + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.17.19", "", { "os": "none", "cpu": "x64" }, "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q=="], 77 + 78 + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.17.19", "", { "os": "openbsd", "cpu": "x64" }, "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g=="], 79 + 80 + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.17.19", "", { "os": "sunos", "cpu": "x64" }, "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg=="], 81 + 82 + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.17.19", "", { "os": "win32", "cpu": "arm64" }, "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag=="], 83 + 84 + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.17.19", "", { "os": "win32", "cpu": "ia32" }, "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw=="], 85 + 86 + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.17.19", "", { "os": "win32", "cpu": "x64" }, "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA=="], 87 + 88 + "@fastify/busboy": ["@fastify/busboy@2.1.1", "", {}, "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA=="], 89 + 90 + "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="], 91 + 92 + "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.0.4" }, "os": "darwin", "cpu": "x64" }, "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q=="], 93 + 94 + "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg=="], 95 + 96 + "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ=="], 97 + 98 + "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.0.5", "", { "os": "linux", "cpu": "arm" }, "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g=="], 99 + 100 + "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA=="], 101 + 102 + "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.0.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA=="], 103 + 104 + "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw=="], 105 + 106 + "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA=="], 107 + 108 + "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw=="], 109 + 110 + "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.0.5" }, "os": "linux", "cpu": "arm" }, "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ=="], 111 + 112 + "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA=="], 113 + 114 + "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.0.4" }, "os": "linux", "cpu": "s390x" }, "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q=="], 115 + 116 + "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA=="], 117 + 118 + "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g=="], 119 + 120 + "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw=="], 121 + 122 + "@img/sharp-wasm32": ["@img/sharp-wasm32@0.33.5", "", { "dependencies": { "@emnapi/runtime": "^1.2.0" }, "cpu": "none" }, "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg=="], 123 + 124 + "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.33.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ=="], 125 + 126 + "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.33.5", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="], 127 + 128 + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], 129 + 130 + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], 131 + 132 + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], 133 + 134 + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.34.9", "", { "os": "android", "cpu": "arm" }, "sha512-qZdlImWXur0CFakn2BJ2znJOdqYZKiedEPEVNTBrpfPjc/YuTGcaYZcdmNFTkUj3DU0ZM/AElcM8Ybww3xVLzA=="], 135 + 136 + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.34.9", "", { "os": "android", "cpu": "arm64" }, "sha512-4KW7P53h6HtJf5Y608T1ISKvNIYLWRKMvfnG0c44M6In4DQVU58HZFEVhWINDZKp7FZps98G3gxwC1sb0wXUUg=="], 137 + 138 + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.34.9", "", { "os": "darwin", "cpu": "arm64" }, "sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ=="], 139 + 140 + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.34.9", "", { "os": "darwin", "cpu": "x64" }, "sha512-eOojSEAi/acnsJVYRxnMkPFqcxSMFfrw7r2iD9Q32SGkb/Q9FpUY1UlAu1DH9T7j++gZ0lHjnm4OyH2vCI7l7Q=="], 141 + 142 + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.34.9", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-2lzjQPJbN5UnHm7bHIUKFMulGTQwdvOkouJDpPysJS+QFBGDJqcfh+CxxtG23Ik/9tEvnebQiylYoazFMAgrYw=="], 143 + 144 + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.34.9", "", { "os": "freebsd", "cpu": "x64" }, "sha512-SLl0hi2Ah2H7xQYd6Qaiu01kFPzQ+hqvdYSoOtHYg/zCIFs6t8sV95kaoqjzjFwuYQLtOI0RZre/Ke0nPaQV+g=="], 145 + 146 + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.34.9", "", { "os": "linux", "cpu": "arm" }, "sha512-88I+D3TeKItrw+Y/2ud4Tw0+3CxQ2kLgu3QvrogZ0OfkmX/DEppehus7L3TS2Q4lpB+hYyxhkQiYPJ6Mf5/dPg=="], 147 + 148 + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.34.9", "", { "os": "linux", "cpu": "arm" }, "sha512-3qyfWljSFHi9zH0KgtEPG4cBXHDFhwD8kwg6xLfHQ0IWuH9crp005GfoUUh/6w9/FWGBwEHg3lxK1iHRN1MFlA=="], 149 + 150 + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.34.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-6TZjPHjKZUQKmVKMUowF3ewHxctrRR09eYyvT5eFv8w/fXarEra83A2mHTVJLA5xU91aCNOUnM+DWFMSbQ0Nxw=="], 151 + 152 + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.34.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-LD2fytxZJZ6xzOKnMbIpgzFOuIKlxVOpiMAXawsAZ2mHBPEYOnLRK5TTEsID6z4eM23DuO88X0Tq1mErHMVq0A=="], 153 + 154 + "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.34.9", "", { "os": "linux", "cpu": "none" }, "sha512-dRAgTfDsn0TE0HI6cmo13hemKpVHOEyeciGtvlBTkpx/F65kTvShtY/EVyZEIfxFkV5JJTuQ9tP5HGBS0hfxIg=="], 155 + 156 + "@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.34.9", "", { "os": "linux", "cpu": "ppc64" }, "sha512-PHcNOAEhkoMSQtMf+rJofwisZqaU8iQ8EaSps58f5HYll9EAY5BSErCZ8qBDMVbq88h4UxaNPlbrKqfWP8RfJA=="], 157 + 158 + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.34.9", "", { "os": "linux", "cpu": "none" }, "sha512-Z2i0Uy5G96KBYKjeQFKbbsB54xFOL5/y1P5wNBsbXB8yE+At3oh0DVMjQVzCJRJSfReiB2tX8T6HUFZ2k8iaKg=="], 159 + 160 + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.34.9", "", { "os": "linux", "cpu": "s390x" }, "sha512-U+5SwTMoeYXoDzJX5dhDTxRltSrIax8KWwfaaYcynuJw8mT33W7oOgz0a+AaXtGuvhzTr2tVKh5UO8GVANTxyQ=="], 161 + 162 + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.34.9", "", { "os": "linux", "cpu": "x64" }, "sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A=="], 163 + 164 + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.34.9", "", { "os": "linux", "cpu": "x64" }, "sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA=="], 165 + 166 + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.34.9", "", { "os": "win32", "cpu": "arm64" }, "sha512-z4mQK9dAN6byRA/vsSgQiPeuO63wdiDxZ9yg9iyX2QTzKuQM7T4xlBoeUP/J8uiFkqxkcWndWi+W7bXdPbt27Q=="], 167 + 168 + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.34.9", "", { "os": "win32", "cpu": "ia32" }, "sha512-KB48mPtaoHy1AwDNkAJfHXvHp24H0ryZog28spEs0V48l3H1fr4i37tiyHsgKZJnCmvxsbATdZGBpbmxTE3a9w=="], 169 + 170 + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.34.9", "", { "os": "win32", "cpu": "x64" }, "sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw=="], 171 + 172 + "@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="], 173 + 174 + "@vitest/expect": ["@vitest/expect@2.1.9", "", { "dependencies": { "@vitest/spy": "2.1.9", "@vitest/utils": "2.1.9", "chai": "^5.1.2", "tinyrainbow": "^1.2.0" } }, "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw=="], 175 + 176 + "@vitest/mocker": ["@vitest/mocker@2.1.9", "", { "dependencies": { "@vitest/spy": "2.1.9", "estree-walker": "^3.0.3", "magic-string": "^0.30.12" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg=="], 177 + 178 + "@vitest/pretty-format": ["@vitest/pretty-format@2.1.9", "", { "dependencies": { "tinyrainbow": "^1.2.0" } }, "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ=="], 179 + 180 + "@vitest/runner": ["@vitest/runner@2.1.9", "", { "dependencies": { "@vitest/utils": "2.1.9", "pathe": "^1.1.2" } }, "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g=="], 181 + 182 + "@vitest/snapshot": ["@vitest/snapshot@2.1.9", "", { "dependencies": { "@vitest/pretty-format": "2.1.9", "magic-string": "^0.30.12", "pathe": "^1.1.2" } }, "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ=="], 183 + 184 + "@vitest/spy": ["@vitest/spy@2.1.9", "", { "dependencies": { "tinyspy": "^3.0.2" } }, "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ=="], 185 + 186 + "@vitest/utils": ["@vitest/utils@2.1.9", "", { "dependencies": { "@vitest/pretty-format": "2.1.9", "loupe": "^3.1.2", "tinyrainbow": "^1.2.0" } }, "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ=="], 187 + 188 + "acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], 189 + 190 + "acorn-walk": ["acorn-walk@8.3.2", "", {}, "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A=="], 191 + 192 + "as-table": ["as-table@1.0.55", "", { "dependencies": { "printable-characters": "^1.0.42" } }, "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ=="], 193 + 194 + "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], 195 + 196 + "birpc": ["birpc@0.2.14", "", {}, "sha512-37FHE8rqsYM5JEKCnXFyHpBCzvgHEExwVVTq+nUmloInU7l8ezD1TpOhKpS8oe1DTYFqEK27rFZVKG43oTqXRA=="], 197 + 198 + "blake3-wasm": ["blake3-wasm@2.1.5", "", {}, "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g=="], 199 + 200 + "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], 201 + 202 + "chai": ["chai@5.2.0", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw=="], 203 + 204 + "check-error": ["check-error@2.1.1", "", {}, "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw=="], 205 + 206 + "cjs-module-lexer": ["cjs-module-lexer@1.4.3", "", {}, "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q=="], 207 + 208 + "color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="], 209 + 210 + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], 211 + 212 + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], 213 + 214 + "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], 215 + 216 + "confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], 217 + 218 + "cookie": ["cookie@0.5.0", "", {}, "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw=="], 219 + 220 + "data-uri-to-buffer": ["data-uri-to-buffer@2.0.2", "", {}, "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA=="], 221 + 222 + "debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="], 223 + 224 + "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="], 225 + 226 + "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="], 227 + 228 + "detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="], 229 + 230 + "devalue": ["devalue@4.3.3", "", {}, "sha512-UH8EL6H2ifcY8TbD2QsxwCC/pr5xSwPvv85LrLXVihmHVC3T3YqTCIwnR5ak0yO1KYqlxrPVOA/JVZJYPy2ATg=="], 231 + 232 + "es-module-lexer": ["es-module-lexer@1.6.0", "", {}, "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ=="], 233 + 234 + "esbuild": ["esbuild@0.17.19", "", { "optionalDependencies": { "@esbuild/android-arm": "0.17.19", "@esbuild/android-arm64": "0.17.19", "@esbuild/android-x64": "0.17.19", "@esbuild/darwin-arm64": "0.17.19", "@esbuild/darwin-x64": "0.17.19", "@esbuild/freebsd-arm64": "0.17.19", "@esbuild/freebsd-x64": "0.17.19", "@esbuild/linux-arm": "0.17.19", "@esbuild/linux-arm64": "0.17.19", "@esbuild/linux-ia32": "0.17.19", "@esbuild/linux-loong64": "0.17.19", "@esbuild/linux-mips64el": "0.17.19", "@esbuild/linux-ppc64": "0.17.19", "@esbuild/linux-riscv64": "0.17.19", "@esbuild/linux-s390x": "0.17.19", "@esbuild/linux-x64": "0.17.19", "@esbuild/netbsd-x64": "0.17.19", "@esbuild/openbsd-x64": "0.17.19", "@esbuild/sunos-x64": "0.17.19", "@esbuild/win32-arm64": "0.17.19", "@esbuild/win32-ia32": "0.17.19", "@esbuild/win32-x64": "0.17.19" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw=="], 235 + 236 + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], 237 + 238 + "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], 239 + 240 + "exit-hook": ["exit-hook@2.2.1", "", {}, "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw=="], 241 + 242 + "expect-type": ["expect-type@1.2.0", "", {}, "sha512-80F22aiJ3GLyVnS/B3HzgR6RelZVumzj9jkL0Rhz4h0xYbNW9PjlQz5h3J/SShErbXBc295vseR4/MIbVmUbeA=="], 243 + 244 + "exsolve": ["exsolve@1.0.2", "", {}, "sha512-ZEcIMbthn2zeX4/wD/DLxDUjuCltHXT8Htvm/JFlTkdYgWh2+HGppgwwNUnIVxzxP7yJOPtuBAec0dLx6lVY8w=="], 245 + 246 + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], 247 + 248 + "get-source": ["get-source@2.0.12", "", { "dependencies": { "data-uri-to-buffer": "^2.0.0", "source-map": "^0.6.1" } }, "sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w=="], 249 + 250 + "glob-to-regexp": ["glob-to-regexp@0.4.1", "", {}, "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="], 251 + 252 + "is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="], 253 + 254 + "loupe": ["loupe@3.1.3", "", {}, "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug=="], 255 + 256 + "magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="], 257 + 258 + "mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="], 259 + 260 + "miniflare": ["miniflare@3.20250204.1", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "stoppable": "1.1.0", "undici": "^5.28.4", "workerd": "1.20250204.0", "ws": "8.18.0", "youch": "3.2.3", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-B4PQi/Ai4d0ZTWahQwsFe5WAfr1j8ISMYxJZTc56g2/btgbX+Go099LmojAZY/fMRLhIYsglcStW8SeW3f/afA=="], 261 + 262 + "mlly": ["mlly@1.7.4", "", { "dependencies": { "acorn": "^8.14.0", "pathe": "^2.0.1", "pkg-types": "^1.3.0", "ufo": "^1.5.4" } }, "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw=="], 263 + 264 + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], 265 + 266 + "mustache": ["mustache@4.2.0", "", { "bin": { "mustache": "bin/mustache" } }, "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ=="], 267 + 268 + "nanoid": ["nanoid@3.3.8", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w=="], 269 + 270 + "ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="], 271 + 272 + "path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="], 273 + 274 + "pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], 275 + 276 + "pathval": ["pathval@2.0.0", "", {}, "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA=="], 277 + 278 + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], 279 + 280 + "pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], 281 + 282 + "postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="], 283 + 284 + "printable-characters": ["printable-characters@1.0.42", "", {}, "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ=="], 285 + 286 + "rollup": ["rollup@4.34.9", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.34.9", "@rollup/rollup-android-arm64": "4.34.9", "@rollup/rollup-darwin-arm64": "4.34.9", "@rollup/rollup-darwin-x64": "4.34.9", "@rollup/rollup-freebsd-arm64": "4.34.9", "@rollup/rollup-freebsd-x64": "4.34.9", "@rollup/rollup-linux-arm-gnueabihf": "4.34.9", "@rollup/rollup-linux-arm-musleabihf": "4.34.9", "@rollup/rollup-linux-arm64-gnu": "4.34.9", "@rollup/rollup-linux-arm64-musl": "4.34.9", "@rollup/rollup-linux-loongarch64-gnu": "4.34.9", "@rollup/rollup-linux-powerpc64le-gnu": "4.34.9", "@rollup/rollup-linux-riscv64-gnu": "4.34.9", "@rollup/rollup-linux-s390x-gnu": "4.34.9", "@rollup/rollup-linux-x64-gnu": "4.34.9", "@rollup/rollup-linux-x64-musl": "4.34.9", "@rollup/rollup-win32-arm64-msvc": "4.34.9", "@rollup/rollup-win32-ia32-msvc": "4.34.9", "@rollup/rollup-win32-x64-msvc": "4.34.9", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-nF5XYqWWp9hx/LrpC8sZvvvmq0TeTjQgaZHYmAgwysT9nh8sWnZhBnM8ZyVbbJFIQBLwHDNoMqsBZBbUo4U8sQ=="], 287 + 288 + "rollup-plugin-inject": ["rollup-plugin-inject@3.0.2", "", { "dependencies": { "estree-walker": "^0.6.1", "magic-string": "^0.25.3", "rollup-pluginutils": "^2.8.1" } }, "sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w=="], 289 + 290 + "rollup-plugin-node-polyfills": ["rollup-plugin-node-polyfills@0.2.1", "", { "dependencies": { "rollup-plugin-inject": "^3.0.0" } }, "sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA=="], 291 + 292 + "rollup-pluginutils": ["rollup-pluginutils@2.8.2", "", { "dependencies": { "estree-walker": "^0.6.1" } }, "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ=="], 293 + 294 + "semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="], 295 + 296 + "sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="], 297 + 298 + "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], 299 + 300 + "simple-swizzle": ["simple-swizzle@0.2.2", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="], 301 + 302 + "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], 303 + 304 + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], 305 + 306 + "sourcemap-codec": ["sourcemap-codec@1.4.8", "", {}, "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="], 307 + 308 + "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], 309 + 310 + "stacktracey": ["stacktracey@2.1.8", "", { "dependencies": { "as-table": "^1.0.36", "get-source": "^2.0.12" } }, "sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw=="], 311 + 312 + "std-env": ["std-env@3.8.1", "", {}, "sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA=="], 313 + 314 + "stoppable": ["stoppable@1.1.0", "", {}, "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw=="], 315 + 316 + "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], 317 + 318 + "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], 319 + 320 + "tinypool": ["tinypool@1.0.2", "", {}, "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA=="], 321 + 322 + "tinyrainbow": ["tinyrainbow@1.2.0", "", {}, "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ=="], 323 + 324 + "tinyspy": ["tinyspy@3.0.2", "", {}, "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q=="], 325 + 326 + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], 327 + 328 + "typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="], 329 + 330 + "ufo": ["ufo@1.5.4", "", {}, "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ=="], 331 + 332 + "undici": ["undici@5.28.5", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA=="], 333 + 334 + "unenv": ["unenv@2.0.0-rc.8", "", { "dependencies": { "defu": "^6.1.4", "exsolve": "^1.0.0", "ohash": "^2.0.5", "pathe": "^2.0.3", "ufo": "^1.5.4" } }, "sha512-wj/lN45LvZ4Uz95rti6DC5wg56eocAwA8KYzExk2SN01iuAb9ayzMwN13Kd3EG2eBXu27PzgMIXLTwWfSczKfw=="], 335 + 336 + "vite": ["vite@5.4.14", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA=="], 337 + 338 + "vite-node": ["vite-node@2.1.9", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.3.7", "es-module-lexer": "^1.5.4", "pathe": "^1.1.2", "vite": "^5.0.0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA=="], 339 + 340 + "vitest": ["vitest@2.1.9", "", { "dependencies": { "@vitest/expect": "2.1.9", "@vitest/mocker": "2.1.9", "@vitest/pretty-format": "^2.1.9", "@vitest/runner": "2.1.9", "@vitest/snapshot": "2.1.9", "@vitest/spy": "2.1.9", "@vitest/utils": "2.1.9", "chai": "^5.1.2", "debug": "^4.3.7", "expect-type": "^1.1.0", "magic-string": "^0.30.12", "pathe": "^1.1.2", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.1", "tinypool": "^1.0.1", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", "vite-node": "2.1.9", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", "@vitest/browser": "2.1.9", "@vitest/ui": "2.1.9", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q=="], 341 + 342 + "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="], 343 + 344 + "workerd": ["workerd@1.20250224.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20250224.0", "@cloudflare/workerd-darwin-arm64": "1.20250224.0", "@cloudflare/workerd-linux-64": "1.20250224.0", "@cloudflare/workerd-linux-arm64": "1.20250224.0", "@cloudflare/workerd-windows-64": "1.20250224.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-NntMg1d9SSkbS4vGdjV5NZxe6FUrvJXY7UiQD7fBtCRVpoPpqz9bVgTq86zalMm+vz64lftzabKT4ka4Y9hejQ=="], 345 + 346 + "wrangler": ["wrangler@3.113.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.3.4", "@cloudflare/unenv-preset": "2.0.0", "@esbuild-plugins/node-globals-polyfill": "0.2.3", "@esbuild-plugins/node-modules-polyfill": "0.2.2", "blake3-wasm": "2.1.5", "esbuild": "0.17.19", "miniflare": "3.20250224.0", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.8", "workerd": "1.20250224.0" }, "optionalDependencies": { "fsevents": "~2.3.2", "sharp": "^0.33.5" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20250224.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-Fr7sxO9kNFoN12AZLdwkQEnHN7pf1FziOfmEZsQIvyyMJTQC0HMWWS9LEsMdxJf0X9okoRMXLPfE9wtz1C1SIg=="], 347 + 348 + "ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], 349 + 350 + "youch": ["youch@3.2.3", "", { "dependencies": { "cookie": "^0.5.0", "mustache": "^4.2.0", "stacktracey": "^2.1.8" } }, "sha512-ZBcWz/uzZaQVdCvfV4uk616Bbpf2ee+F/AvuKDR5EwX/Y4v06xWdtMluqTD7+KlZdM93lLm9gMZYo0sKBS0pgw=="], 351 + 352 + "zod": ["zod@3.24.2", "", {}, "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ=="], 353 + 354 + "@cloudflare/vitest-pool-workers/wrangler": ["wrangler@3.109.1", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.3.4", "@esbuild-plugins/node-globals-polyfill": "0.2.3", "@esbuild-plugins/node-modules-polyfill": "0.2.2", "blake3-wasm": "2.1.5", "esbuild": "0.17.19", "miniflare": "3.20250204.1", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.1", "workerd": "1.20250204.0" }, "optionalDependencies": { "fsevents": "~2.3.2", "sharp": "^0.33.5" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20250204.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-1Jx+nZ6eCXPQ2rsGdrV6Qy/LGvhpqudeuTl4AYHl9P8Zugp44Uzxnj5w11qF4v/rv1dOZoA5TydSt9xMFfhpKg=="], 355 + 356 + "miniflare/workerd": ["workerd@1.20250204.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20250204.0", "@cloudflare/workerd-darwin-arm64": "1.20250204.0", "@cloudflare/workerd-linux-64": "1.20250204.0", "@cloudflare/workerd-linux-arm64": "1.20250204.0", "@cloudflare/workerd-windows-64": "1.20250204.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-zcKufjVFsQMiD3/acg1Ix00HIMCkXCrDxQXYRDn/1AIz3QQGkmbVDwcUk1Ki2jBUoXmBCMsJdycRucgMVEypWg=="], 357 + 358 + "miniflare/zod": ["zod@3.22.3", "", {}, "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug=="], 359 + 360 + "mlly/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], 361 + 362 + "pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], 363 + 364 + "rollup-plugin-inject/estree-walker": ["estree-walker@0.6.1", "", {}, "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w=="], 365 + 366 + "rollup-plugin-inject/magic-string": ["magic-string@0.25.9", "", { "dependencies": { "sourcemap-codec": "^1.4.8" } }, "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ=="], 367 + 368 + "rollup-pluginutils/estree-walker": ["estree-walker@0.6.1", "", {}, "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w=="], 369 + 370 + "unenv/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], 371 + 372 + "vite/esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="], 373 + 374 + "wrangler/miniflare": ["miniflare@3.20250224.0", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "stoppable": "1.1.0", "undici": "^5.28.5", "workerd": "1.20250224.0", "ws": "8.18.0", "youch": "3.2.3", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-DyLxzhHCQ9UWDceqEsT7tmw8ZTSAhb1yKUqUi5VDmSxsIocKi4y5kvMijw9ELK8+tq/CiCp/RQxwRNZRJD8Xbg=="], 375 + 376 + "@cloudflare/vitest-pool-workers/wrangler/unenv": ["unenv@2.0.0-rc.1", "", { "dependencies": { "defu": "^6.1.4", "mlly": "^1.7.4", "ohash": "^1.1.4", "pathe": "^1.1.2", "ufo": "^1.5.4" } }, "sha512-PU5fb40H8X149s117aB4ytbORcCvlASdtF97tfls4BPIyj4PeVxvpSuy1jAptqYHqB0vb2w2sHvzM0XWcp2OKg=="], 377 + 378 + "@cloudflare/vitest-pool-workers/wrangler/workerd": ["workerd@1.20250204.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20250204.0", "@cloudflare/workerd-darwin-arm64": "1.20250204.0", "@cloudflare/workerd-linux-64": "1.20250204.0", "@cloudflare/workerd-linux-arm64": "1.20250204.0", "@cloudflare/workerd-windows-64": "1.20250204.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-zcKufjVFsQMiD3/acg1Ix00HIMCkXCrDxQXYRDn/1AIz3QQGkmbVDwcUk1Ki2jBUoXmBCMsJdycRucgMVEypWg=="], 379 + 380 + "miniflare/workerd/@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20250204.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-HpsgbWEfvdcwuZ8WAZhi1TlSCyyHC3tbghpKsOqGDaQNltyAFAWqa278TPNfcitYf/FmV4961v3eqUE+RFdHNQ=="], 381 + 382 + "miniflare/workerd/@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20250204.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-AJ8Tk7KMJqePlch3SH8oL41ROtsrb07hKRHD6M+FvGC3tLtf26rpteAAMNYKMDYKzFNFUIKZNijYDFZjBFndXQ=="], 383 + 384 + "miniflare/workerd/@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20250204.0", "", { "os": "linux", "cpu": "x64" }, "sha512-RIUfUSnDC8h73zAa+u1K2Frc7nc+eeQoBBP7SaqsRe6JdX8jfIv/GtWjQWCoj8xQFgLvhpJKZ4sTTTV+AilQbw=="], 385 + 386 + "miniflare/workerd/@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20250204.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-8Ql8jDjoIgr2J7oBD01kd9kduUz60njofrBpAOkjCPed15He8e8XHkYaYow3g0xpae4S2ryrPOeoD3M64sRxeg=="], 387 + 388 + "miniflare/workerd/@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20250204.0", "", { "os": "win32", "cpu": "x64" }, "sha512-RpDJO3+to+e17X3EWfRCagboZYwBz2fowc+jL53+fd7uD19v3F59H48lw2BDpHJMRyhg6ouWcpM94OhsHv8ecA=="], 389 + 390 + "vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="], 391 + 392 + "vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="], 393 + 394 + "vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="], 395 + 396 + "vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="], 397 + 398 + "vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="], 399 + 400 + "vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="], 401 + 402 + "vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="], 403 + 404 + "vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="], 405 + 406 + "vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="], 407 + 408 + "vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="], 409 + 410 + "vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="], 411 + 412 + "vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="], 413 + 414 + "vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="], 415 + 416 + "vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="], 417 + 418 + "vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="], 419 + 420 + "vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="], 421 + 422 + "vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="], 423 + 424 + "vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="], 425 + 426 + "vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="], 427 + 428 + "vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="], 429 + 430 + "vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="], 431 + 432 + "vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="], 433 + 434 + "wrangler/miniflare/zod": ["zod@3.22.3", "", {}, "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug=="], 435 + 436 + "@cloudflare/vitest-pool-workers/wrangler/unenv/ohash": ["ohash@1.1.6", "", {}, "sha512-TBu7PtV8YkAZn0tSxobKY2n2aAQva936lhRrj6957aDaCf9IEtqsKbgMzXE/F/sjqYOwmrukeORHNLe5glk7Cg=="], 437 + 438 + "@cloudflare/vitest-pool-workers/wrangler/workerd/@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20250204.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-HpsgbWEfvdcwuZ8WAZhi1TlSCyyHC3tbghpKsOqGDaQNltyAFAWqa278TPNfcitYf/FmV4961v3eqUE+RFdHNQ=="], 439 + 440 + "@cloudflare/vitest-pool-workers/wrangler/workerd/@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20250204.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-AJ8Tk7KMJqePlch3SH8oL41ROtsrb07hKRHD6M+FvGC3tLtf26rpteAAMNYKMDYKzFNFUIKZNijYDFZjBFndXQ=="], 441 + 442 + "@cloudflare/vitest-pool-workers/wrangler/workerd/@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20250204.0", "", { "os": "linux", "cpu": "x64" }, "sha512-RIUfUSnDC8h73zAa+u1K2Frc7nc+eeQoBBP7SaqsRe6JdX8jfIv/GtWjQWCoj8xQFgLvhpJKZ4sTTTV+AilQbw=="], 443 + 444 + "@cloudflare/vitest-pool-workers/wrangler/workerd/@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20250204.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-8Ql8jDjoIgr2J7oBD01kd9kduUz60njofrBpAOkjCPed15He8e8XHkYaYow3g0xpae4S2ryrPOeoD3M64sRxeg=="], 445 + 446 + "@cloudflare/vitest-pool-workers/wrangler/workerd/@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20250204.0", "", { "os": "win32", "cpu": "x64" }, "sha512-RpDJO3+to+e17X3EWfRCagboZYwBz2fowc+jL53+fd7uD19v3F59H48lw2BDpHJMRyhg6ouWcpM94OhsHv8ecA=="], 447 + } 448 + }
+19
rockskyapi/rocksky-doc/package.json
··· 1 + { 2 + "name": "white-scene-4cbd", 3 + "version": "0.0.0", 4 + "private": true, 5 + "scripts": { 6 + "deploy": "wrangler deploy", 7 + "dev": "wrangler dev", 8 + "start": "wrangler dev", 9 + "test": "vitest", 10 + "cf-typegen": "wrangler types" 11 + }, 12 + "devDependencies": { 13 + "@cloudflare/vitest-pool-workers": "^0.6.4", 14 + "@cloudflare/workers-types": "^4.20250303.0", 15 + "typescript": "^5.5.2", 16 + "vitest": "~2.1.9", 17 + "wrangler": "^3.113.0" 18 + } 19 + }
+31
rockskyapi/rocksky-doc/src/index.ts
··· 1 + /** 2 + * Welcome to Cloudflare Workers! This is your first worker. 3 + * 4 + * - Run `npm run dev` in your terminal to start a development server 5 + * - Open a browser tab at http://localhost:8787/ to see your worker in action 6 + * - Run `npm run deploy` to publish your worker 7 + * 8 + * Bind resources to your worker in `wrangler.jsonc`. After adding bindings, a type definition for the 9 + * `Env` object can be regenerated with `npm run cf-typegen`. 10 + * 11 + * Learn more at https://developers.cloudflare.com/workers/ 12 + */ 13 + 14 + export default { 15 + async fetch(request, env, ctx): Promise<Response> { 16 + /*const url = new URL(request.url); 17 + const proxyUrl = new URL(request.url); 18 + proxyUrl.host = "rocksky.apidog.io"; 19 + proxyUrl.hostname = "rocksky.apidog.io"; 20 + // set headers 21 + const headers = new Headers(request.headers); 22 + headers.set("X-Apidog--Docs-Site-ID", "rocksky"); 23 + return fetch(proxyUrl.toString(), { 24 + method: request.method, 25 + headers, 26 + });*/ 27 + 28 + // redirect to fmqouwwzmr.apidog.io 29 + return Response.redirect("https://docs.rocksky.app", 301); 30 + }, 31 + } satisfies ExportedHandler<Env>;
+25
rockskyapi/rocksky-doc/test/index.spec.ts
··· 1 + // test/index.spec.ts 2 + import { env, createExecutionContext, waitOnExecutionContext, SELF } from 'cloudflare:test'; 3 + import { describe, it, expect } from 'vitest'; 4 + import worker from '../src/index'; 5 + 6 + // For now, you'll need to do something like this to get a correctly-typed 7 + // `Request` to pass to `worker.fetch()`. 8 + const IncomingRequest = Request<unknown, IncomingRequestCfProperties>; 9 + 10 + describe('Hello World worker', () => { 11 + it('responds with Hello World! (unit style)', async () => { 12 + const request = new IncomingRequest('http://example.com'); 13 + // Create an empty context to pass to `worker.fetch()`. 14 + const ctx = createExecutionContext(); 15 + const response = await worker.fetch(request, env, ctx); 16 + // Wait for all `Promise`s passed to `ctx.waitUntil()` to settle before running test assertions 17 + await waitOnExecutionContext(ctx); 18 + expect(await response.text()).toMatchInlineSnapshot(`"Hello World!"`); 19 + }); 20 + 21 + it('responds with Hello World! (integration style)', async () => { 22 + const response = await SELF.fetch('https://example.com'); 23 + expect(await response.text()).toMatchInlineSnapshot(`"Hello World!"`); 24 + }); 25 + });
+8
rockskyapi/rocksky-doc/test/tsconfig.json
··· 1 + { 2 + "extends": "../tsconfig.json", 3 + "compilerOptions": { 4 + "types": ["@cloudflare/workers-types/experimental", "@cloudflare/vitest-pool-workers"] 5 + }, 6 + "include": ["./**/*.ts", "../worker-configuration.d.ts"], 7 + "exclude": [] 8 + }
+46
rockskyapi/rocksky-doc/tsconfig.json
··· 1 + { 2 + "compilerOptions": { 3 + /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 + 5 + /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 6 + "target": "es2021", 7 + /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 8 + "lib": ["es2021"], 9 + /* Specify what JSX code is generated. */ 10 + "jsx": "react-jsx", 11 + 12 + /* Specify what module code is generated. */ 13 + "module": "es2022", 14 + /* Specify how TypeScript looks up a file from a given module specifier. */ 15 + "moduleResolution": "Bundler", 16 + /* Specify type package names to be included without being referenced in a source file. */ 17 + "types": [ 18 + "@cloudflare/workers-types/2023-07-01" 19 + ], 20 + /* Enable importing .json files */ 21 + "resolveJsonModule": true, 22 + 23 + /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ 24 + "allowJs": true, 25 + /* Enable error reporting in type-checked JavaScript files. */ 26 + "checkJs": false, 27 + 28 + /* Disable emitting files from a compilation. */ 29 + "noEmit": true, 30 + 31 + /* Ensure that each file can be safely transpiled without relying on other imports. */ 32 + "isolatedModules": true, 33 + /* Allow 'import x from y' when a module doesn't have a default export. */ 34 + "allowSyntheticDefaultImports": true, 35 + /* Ensure that casing is correct in imports. */ 36 + "forceConsistentCasingInFileNames": true, 37 + 38 + /* Enable all strict type-checking options. */ 39 + "strict": true, 40 + 41 + /* Skip type checking all .d.ts files. */ 42 + "skipLibCheck": true 43 + }, 44 + "exclude": ["test"], 45 + "include": ["worker-configuration.d.ts", "src/**/*.ts"] 46 + }
+11
rockskyapi/rocksky-doc/vitest.config.mts
··· 1 + import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config'; 2 + 3 + export default defineWorkersConfig({ 4 + test: { 5 + poolOptions: { 6 + workers: { 7 + wrangler: { configPath: './wrangler.jsonc' }, 8 + }, 9 + }, 10 + }, 11 + });
+4
rockskyapi/rocksky-doc/worker-configuration.d.ts
··· 1 + // Generated by Wrangler 2 + // After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen` 3 + interface Env { 4 + }
+47
rockskyapi/rocksky-doc/wrangler.jsonc
··· 1 + /** 2 + * For more details on how to configure Wrangler, refer to: 3 + * https://developers.cloudflare.com/workers/wrangler/configuration/ 4 + */ 5 + { 6 + "$schema": "node_modules/wrangler/config-schema.json", 7 + "name": "white-scene-4cbd", 8 + "main": "src/index.ts", 9 + "compatibility_date": "2025-03-03", 10 + "observability": { 11 + "enabled": true 12 + } 13 + /** 14 + * Smart Placement 15 + * Docs: https://developers.cloudflare.com/workers/configuration/smart-placement/#smart-placement 16 + */ 17 + // "placement": { "mode": "smart" }, 18 + 19 + /** 20 + * Bindings 21 + * Bindings allow your Worker to interact with resources on the Cloudflare Developer Platform, including 22 + * databases, object storage, AI inference, real-time communication and more. 23 + * https://developers.cloudflare.com/workers/runtime-apis/bindings/ 24 + */ 25 + 26 + /** 27 + * Environment Variables 28 + * https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables 29 + */ 30 + // "vars": { "MY_VARIABLE": "production_value" }, 31 + /** 32 + * Note: Use secrets to store sensitive data. 33 + * https://developers.cloudflare.com/workers/configuration/secrets/ 34 + */ 35 + 36 + /** 37 + * Static Assets 38 + * https://developers.cloudflare.com/workers/static-assets/binding/ 39 + */ 40 + // "assets": { "directory": "./public/", "binding": "ASSETS" }, 41 + 42 + /** 43 + * Service Bindings (communicate between multiple Workers) 44 + * https://developers.cloudflare.com/workers/wrangler/configuration/#service-bindings 45 + */ 46 + // "services": [{ "binding": "MY_SERVICE", "service": "my-service" }] 47 + }
+22 -3
rockskyweb/src/pages/album/Album.tsx
··· 1 1 import styled from "@emotion/styled"; 2 2 import { TableBuilder, TableBuilderColumn } from "baseui/table-semantic"; 3 - import { HeadingMedium, LabelLarge, LabelMedium } from "baseui/typography"; 3 + import { 4 + HeadingMedium, 5 + LabelLarge, 6 + LabelMedium, 7 + LabelXSmall, 8 + } from "baseui/typography"; 9 + import dayjs from "dayjs"; 4 10 import numeral from "numeral"; 5 11 import { useEffect, useState } from "react"; 6 12 import ContentLoader from "react-content-loader"; ··· 50 56 albumArt?: string; 51 57 artist: string; 52 58 title: string; 53 - year: string; 59 + year: number; 54 60 uri: string; 55 61 releaseDate: string; 56 62 listeners: number; 57 63 scrobbles: number; 58 64 artistUri?: string; 65 + label?: string; 59 66 tracks: { 60 67 xata_id: string; 61 68 track_number: number; ··· 87 94 title: data.title, 88 95 year: data.year, 89 96 uri: data.uri, 90 - releaseDate: data.release_date, 91 97 listeners: data.listeners, 92 98 scrobbles: data.scrobbles, 93 99 tracks: data.tracks, 100 + releaseDate: data.release_date 101 + ? dayjs(data.release_date).format("MMMM D, YYYY") 102 + : data.year.toString(), 103 + label: data.tracks[0].copyright_message || data.tracks[0].label, 94 104 }); 95 105 // eslint-disable-next-line @typescript-eslint/no-explicit-any 96 106 setDisc(Math.max(...data.tracks.map((track: any) => track.disc_number))); ··· 418 428 ))} 419 429 </div> 420 430 )} 431 + 432 + <div style={{ marginTop: 20 }}> 433 + <LabelMedium margin={0} color="rgba(36, 49, 61, 0.65)"> 434 + {album?.releaseDate} 435 + </LabelMedium> 436 + <LabelXSmall margin={0} color={"rgba(36, 49, 61, 0.65)"}> 437 + {album?.label} 438 + </LabelXSmall> 439 + </div> 421 440 </div> 422 441 <Shout type="album" /> 423 442 </div>