diff --git a/Cargo.lock b/Cargo.lock index 51119a6ee..db850fd79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "addr2line" -version = "0.24.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ "gimli", ] @@ -182,9 +182,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "async-compression" -version = "0.4.31" +version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9611ec0b6acea03372540509035db2f7f1e9f04da5d27728436fa994033c00a0" +checksum = "5a89bce6054c720275ac2432fbba080a66a2106a44a1b804553930ca6909f4e0" dependencies = [ "compression-codecs", "compression-core", @@ -283,9 +283,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.75" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ "addr2line", "cfg-if", @@ -293,7 +293,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -515,6 +515,14 @@ dependencies = [ "brk_structs", ] +[[package]] +name = "brk_bridge" +version = "0.0.109" +dependencies = [ + "brk_interface", + "brk_structs", +] + [[package]] name = "brk_bundler" version = "0.0.109" @@ -531,6 +539,7 @@ name = "brk_cli" version = "0.0.109" dependencies = [ "bitcoincore-rpc", + "brk_bridge", "brk_bundler", "brk_computer", "brk_fetcher", @@ -1070,7 +1079,7 @@ dependencies = [ "quick_cache", "serde", "serde_json", - "sonic-rs 0.5.4", + "sonic-rs 0.5.5", "tokio", "tower-http", "tracing", @@ -1183,9 +1192,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.38" +version = "1.2.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80f41ae168f955c12fb8960b057d70d0ca153fb83182b57d86380443527be7e9" +checksum = "e1354349954c6fc9cb0deab020f27f783cf0b604e8bb754dc4658ecf0d29c35f" dependencies = [ "find-msvc-tools", "jobserver", @@ -1227,7 +1236,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-link 0.2.0", + "windows-link", ] [[package]] @@ -1335,9 +1344,9 @@ checksum = "ea0095f6103c2a8b44acd6fd15960c801dafebf02e21940360833e0673f48ba7" [[package]] name = "compression-codecs" -version = "0.4.30" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "485abf41ac0c8047c07c87c72c8fb3eb5197f6e9d7ded615dfd1a00ae00a0f64" +checksum = "ef8a506ec4b81c460798f572caead636d57d3d7e940f998160f52bd254bf2d23" dependencies = [ "brotli", "compression-core", @@ -1507,7 +1516,7 @@ checksum = "881c5d0a13b2f1498e2306e82cbada78390e152d4b1378fb28a84f4dcd0dc4f3" dependencies = [ "dispatch", "nix", - "windows-sys 0.61.0", + "windows-sys 0.61.1", ] [[package]] @@ -1640,7 +1649,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.61.0", + "windows-sys 0.61.1", ] [[package]] @@ -1750,7 +1759,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.0", + "windows-sys 0.61.1", ] [[package]] @@ -2016,9 +2025,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.1" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "guardian" @@ -2632,9 +2641,9 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memmap2" @@ -2855,9 +2864,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.7" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] @@ -2918,9 +2927,9 @@ dependencies = [ [[package]] name = "oxc-browserslist" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c5bf598bf7f55955c737d580cdadaeeda80e0e6430834f6165aef21220e3a2" +checksum = "7612127f5fa1ef0f3e98905ddfc10a7fa1df98944b75d774bb3cb4b530663616" dependencies = [ "bincode", "flate2", @@ -3248,9 +3257,9 @@ dependencies = [ [[package]] name = "oxc_sourcemap" -version = "4.1.5" +version = "4.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6194c58467a15d9dcb5cb852fcad312af57fd46fabd419fae87fcf801f83702" +checksum = "05ff280f25901ac054ad8552395ecd6a455e4b9352a94debbc34c433760586ef" dependencies = [ "base64-simd", "json-escape-simd", @@ -3855,9 +3864,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.2" +version = "1.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" +checksum = "8b5288124840bee7b386bc413c487869b360b2b4ec421ea56425128692f2a82c" dependencies = [ "aho-corasick", "memchr", @@ -3867,9 +3876,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" +checksum = "833eb9ce86d40ef33cb1306d8accf7bc8ec2bfea4355cbdebb3df68b40925cad" dependencies = [ "aho-corasick", "memchr", @@ -3983,7 +3992,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.0", + "windows-sys 0.61.1", ] [[package]] @@ -4111,7 +4120,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b55fb86dfd3a2f5f76ea78310a88f96c4ea21a3031f8d212443d56123fd0521" dependencies = [ "libc", - "windows-sys 0.61.0", + "windows-sys 0.61.1", ] [[package]] @@ -4144,9 +4153,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.226" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", "serde_derive", @@ -4164,18 +4173,18 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.226" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e966a4" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.226" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -4374,9 +4383,9 @@ dependencies = [ [[package]] name = "sonic-rs" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0e0c5c1c429b500b4583e860ed48f9e34968cb1ba49dd16c1e2743678e3fd18" +checksum = "22540d56ba14521e4878ad436d498518c59698c39a89d5905c694932f0bf7134" dependencies = [ "ahash", "bumpalo", @@ -4521,7 +4530,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix", - "windows-sys 0.61.0", + "windows-sys 0.61.1", ] [[package]] @@ -5227,7 +5236,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.0", + "windows-sys 0.61.1", ] [[package]] @@ -5238,55 +5247,54 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.62.0" +version = "0.62.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9579d0e6970fd5250aa29aba5994052385ff55cf7b28a059e484bb79ea842e42" +checksum = "49e6c4a1f363c8210c6f77ba24f645c61c6fb941eccf013da691f7e09515b8ac" dependencies = [ "windows-collections", "windows-core", "windows-future", - "windows-link 0.2.0", "windows-numerics", ] [[package]] name = "windows-collections" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a90dd7a7b86859ec4cdf864658b311545ef19dbcf17a672b52ab7cefe80c336f" +checksum = "123e712f464a8a60ce1a13f4c446d2d43ab06464cb5842ff68f5c71b6fb7852e" dependencies = [ "windows-core", ] [[package]] name = "windows-core" -version = "0.62.0" +version = "0.62.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57fe7168f7de578d2d8a05b07fd61870d2e73b4020e9f49aa00da8471723497c" +checksum = "6844ee5416b285084d3d3fffd743b925a6c9385455f64f6d4fa3031c4c2749a9" dependencies = [ "windows-implement", "windows-interface", - "windows-link 0.2.0", + "windows-link", "windows-result", "windows-strings", ] [[package]] name = "windows-future" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2194dee901458cb79e1148a4e9aac2b164cc95fa431891e7b296ff0b2f1d8a6" +checksum = "68f3db6b24b120200d649cd4811b4947188ed3a8d2626f7075146c5d178a9a4a" dependencies = [ "windows-core", - "windows-link 0.2.0", + "windows-link", "windows-threading", ] [[package]] name = "windows-implement" -version = "0.60.0" +version = "0.60.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +checksum = "edb307e42a74fb6de9bf3a02d9712678b22399c87e6fa869d6dfcd8c1b7754e0" dependencies = [ "proc-macro2", "quote", @@ -5295,21 +5303,15 @@ dependencies = [ [[package]] name = "windows-interface" -version = "0.59.1" +version = "0.59.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +checksum = "c0abd1ddbc6964ac14db11c7213d6532ef34bd9aa042c2e5935f59d7908b46a5" dependencies = [ "proc-macro2", "quote", "syn 2.0.106", ] -[[package]] -name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - [[package]] name = "windows-link" version = "0.2.0" @@ -5323,7 +5325,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ce3498fe0aba81e62e477408383196b4b0363db5e0c27646f932676283b43d8" dependencies = [ "windows-core", - "windows-link 0.2.0", + "windows-link", ] [[package]] @@ -5332,7 +5334,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f" dependencies = [ - "windows-link 0.2.0", + "windows-link", ] [[package]] @@ -5341,7 +5343,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda" dependencies = [ - "windows-link 0.2.0", + "windows-link", ] [[package]] @@ -5368,16 +5370,16 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.3", + "windows-targets 0.53.4", ] [[package]] name = "windows-sys" -version = "0.61.0" +version = "0.61.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" +checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f" dependencies = [ - "windows-link 0.2.0", + "windows-link", ] [[package]] @@ -5398,11 +5400,11 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.3" +version = "0.53.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +checksum = "2d42b7b7f66d2a06854650af09cfdf8713e427a439c97ad65a6375318033ac4b" dependencies = [ - "windows-link 0.1.3", + "windows-link", "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", "windows_i686_gnu 0.53.0", @@ -5419,7 +5421,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab47f085ad6932defa48855254c758cdd0e2f2d48e62a34118a268d8f345e118" dependencies = [ - "windows-link 0.2.0", + "windows-link", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 108e53172..d61fef6bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,7 @@ allocative = { version = "0.3.4", features = ["parking_lot"] } axum = "0.8.4" bitcoin = { version = "0.32.7", features = ["serde"] } bitcoincore-rpc = "0.19.0" +brk_bridge = { version = "0.0.109", path = "crates/brk_bridge" } brk_bundler = { version = "0.0.109", path = "crates/brk_bundler" } brk_cli = { version = "0.0.109", path = "crates/brk_cli" } brk_computer = { version = "0.0.109", path = "crates/brk_computer" } @@ -67,11 +68,11 @@ minreq = { version = "2.14.1", features = ["https", "serde_json"] } parking_lot = "0.12.4" quick_cache = "0.6.16" rayon = "1.11.0" -serde = "1.0.226" +serde = "1.0.228" serde_bytes = "0.11.19" -serde_derive = "1.0.226" +serde_derive = "1.0.228" serde_json = { version = "1.0.145", features = ["float_roundtrip"] } -sonic-rs = "0.5.4" +sonic-rs = "0.5.5" tokio = { version = "1.47.1", features = ["rt-multi-thread"] } # vecdb = { path = "../seqdb/crates/vecdb", features = ["derive"]} vecdb = { version = "0.2.16", features = ["derive"]} diff --git a/assets/brk-v0.1.0.png b/assets/brk-v0.1.0.png deleted file mode 100644 index ee08d6a38..000000000 Binary files a/assets/brk-v0.1.0.png and /dev/null differ diff --git a/assets/claude-step1.png b/assets/claude-step1.png deleted file mode 100644 index 4d4edb45a..000000000 Binary files a/assets/claude-step1.png and /dev/null differ diff --git a/assets/claude-step2.png b/assets/claude-step2.png deleted file mode 100644 index 49520268c..000000000 Binary files a/assets/claude-step2.png and /dev/null differ diff --git a/assets/claude-step3.png b/assets/claude-step3.png deleted file mode 100644 index af3735423..000000000 Binary files a/assets/claude-step3.png and /dev/null differ diff --git a/assets/claude-step4.png b/assets/claude-step4.png deleted file mode 100644 index 17277ec61..000000000 Binary files a/assets/claude-step4.png and /dev/null differ diff --git a/assets/kibo-v0.4.0.jpg b/assets/kibo-v0.4.0.jpg deleted file mode 100644 index 39ed0ca34..000000000 Binary files a/assets/kibo-v0.4.0.jpg and /dev/null differ diff --git a/assets/kibo-v0.5.0.jpg b/assets/kibo-v0.5.0.jpg deleted file mode 100644 index 8e101192a..000000000 Binary files a/assets/kibo-v0.5.0.jpg and /dev/null differ diff --git a/assets/satonomics-v0.0.1.jpg b/assets/satonomics-v0.0.1.jpg deleted file mode 100644 index 1c309fa21..000000000 Binary files a/assets/satonomics-v0.0.1.jpg and /dev/null differ diff --git a/assets/satonomics-v0.1.0.jpg b/assets/satonomics-v0.1.0.jpg deleted file mode 100644 index c7e6d14b3..000000000 Binary files a/assets/satonomics-v0.1.0.jpg and /dev/null differ diff --git a/assets/satonomics-v0.1.1.jpg b/assets/satonomics-v0.1.1.jpg deleted file mode 100644 index a999f808e..000000000 Binary files a/assets/satonomics-v0.1.1.jpg and /dev/null differ diff --git a/assets/satonomics-v0.2.0.jpg b/assets/satonomics-v0.2.0.jpg deleted file mode 100644 index 34caf044e..000000000 Binary files a/assets/satonomics-v0.2.0.jpg and /dev/null differ diff --git a/assets/satonomics-v0.3.0.jpg b/assets/satonomics-v0.3.0.jpg deleted file mode 100644 index 5b4cc8c5d..000000000 Binary files a/assets/satonomics-v0.3.0.jpg and /dev/null differ diff --git a/crates/brk_bridge/Cargo.toml b/crates/brk_bridge/Cargo.toml new file mode 100644 index 000000000..739c604c5 --- /dev/null +++ b/crates/brk_bridge/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "brk_bridge" +description = "A generator of bridge files for other languages" +version.workspace = true +edition.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true +rust-version.workspace = true +build = "build.rs" + +[dependencies] +brk_interface = { workspace = true } +brk_structs = { workspace = true } diff --git a/crates/brk_bridge/README.md b/crates/brk_bridge/README.md new file mode 100644 index 000000000..d11d53f46 --- /dev/null +++ b/crates/brk_bridge/README.md @@ -0,0 +1 @@ +# brk_bridge diff --git a/crates/brk_bridge/build.rs b/crates/brk_bridge/build.rs new file mode 100644 index 000000000..a4055a31e --- /dev/null +++ b/crates/brk_bridge/build.rs @@ -0,0 +1,8 @@ +fn main() { + let profile = std::env::var("PROFILE").unwrap_or_default(); + + if profile == "release" { + println!("cargo:rustc-flag=-C"); + println!("cargo:rustc-flag=target-cpu=native"); + } +} diff --git a/crates/brk_bridge/src/js.rs b/crates/brk_bridge/src/js.rs new file mode 100644 index 000000000..c33b04253 --- /dev/null +++ b/crates/brk_bridge/src/js.rs @@ -0,0 +1,291 @@ +use std::{ + collections::{BTreeMap, HashMap}, + fs, io, + path::Path, +}; + +use brk_interface::{Index, Interface}; +use brk_structs::pools; + +use super::VERSION; + +const AUTO_GENERATED_DISCLAIMER: &str = "// +// File auto-generated, any modifications will be overwritten +//"; + +#[allow(clippy::upper_case_acronyms)] +pub trait Bridge { + fn generate_js_files(&self, packages_path: &Path) -> io::Result<()>; +} + +impl Bridge for Interface<'static> { + fn generate_js_files(&self, packages_path: &Path) -> io::Result<()> { + let path = packages_path.join("brk"); + + if !fs::exists(&path)? { + return Ok(()); + } + + let path = packages_path.join("generated"); + fs::create_dir_all(&path)?; + + generate_version_file(&path)?; + generate_metrics_file(self, &path)?; + generate_pools_file(&path) + } +} + +fn generate_version_file(parent: &Path) -> io::Result<()> { + let path = parent.join(Path::new("metrics.js")); + + let contents = format!( + "{AUTO_GENERATED_DISCLAIMER} + +export const VERSION = \"v{VERSION}\"; +" + ); + + fs::write(path, contents) +} + +fn generate_pools_file(parent: &Path) -> io::Result<()> { + let path = parent.join(Path::new("pools.js")); + + let pools = pools(); + + let mut contents = format!("{AUTO_GENERATED_DISCLAIMER}\n"); + + contents += " +/** + * @typedef {typeof POOL_ID_TO_POOL_NAME} PoolIdToPoolName + * @typedef {keyof PoolIdToPoolName} PoolId + */ + +export const POOL_ID_TO_POOL_NAME = /** @type {const} */ ({ +"; + + let mut sorted_pools: Vec<_> = pools.iter().collect(); + sorted_pools.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase())); + + contents += &sorted_pools + .iter() + .map(|pool| { + let id = pool.serialized_id(); + format!(" {id}: \"{}\",", pool.name) + }) + .collect::>() + .join("\n"); + + contents += "\n});\n"; + + fs::write(path, contents) +} + +fn generate_metrics_file(interface: &Interface<'static>, parent: &Path) -> io::Result<()> { + let path = parent.join(Path::new("metrics.js")); + + let indexes = Index::all(); + + let mut contents = format!( + "{AUTO_GENERATED_DISCLAIMER} + +/** +" + ); + + contents += &indexes + .iter() + .map(|i| format!(" * @typedef {{\"{}\"}} {i}", i.serialize_long())) + .collect::>() + .join("\n"); + + contents += &format!( + " + * @typedef {{{}}} Index", + indexes + .iter() + .map(|i| i.to_string()) + .collect::>() + .join(" | ") + ); + + let mut unique_index_groups = BTreeMap::new(); + + contents += " + * + * @typedef {typeof COMPRESSED_METRIC_TO_INDEXES} MetricToIndexes + * @typedef {string} Metric + */ + +"; + + let mut word_to_freq: BTreeMap<_, usize> = BTreeMap::new(); + interface + .metric_to_index_to_vec() + .keys() + .for_each(|metric| { + metric.split("_").for_each(|word| { + *word_to_freq.entry(word).or_default() += 1; + }); + }); + let mut word_to_freq = word_to_freq.into_iter().collect::>(); + word_to_freq.sort_unstable_by(|a, b| b.1.cmp(&a.1).then(a.0.cmp(b.0))); + let words = word_to_freq + .into_iter() + .map(|(str, _)| str) + .collect::>(); + + contents += &format!( + "const INDEX_TO_WORD = [ + {} +]; +", + words + .iter() + .map(|w| format!("\"{w}\"")) + .collect::>() + .join(",\n ") + ); + + contents += " +const WORD_TO_INDEX = {}; +INDEX_TO_WORD.forEach((word, index) => { + WORD_TO_INDEX[word] = index; +}); + +function lettersToIndex(s) { + let result = 0; + for (let i = 0; i < s.length; i++) { + const value = charToIndex(s.charCodeAt(i)); + result = result * 52 + value + 1; + } + return result - 1; +} + +function charToIndex(c) { + const A = 65, Z = 90, a = 97, z = 122; + + if (c >= A && c <= Z) { + return c - A; + } else if (c >= a && c <= z) { + return c - a + 26; + } else { + return 255; // Invalid + } +} + +function compressMetric(metric) { + return metric + .split('_') + .map((word) => { + const index = WORD_TO_INDEX[word]; + if (index === undefined) throw \"bad word\"; + return indexToLetters(index); + }) + .join('_'); +} + +function decompressMetric(compressedMetric) { + return compressedMetric + .split('_') + .map((code) => { + const index = lettersToIndex(code); + return WORDS[index] || code; // Fallback to original if not found + }) + .join('_'); +} +"; + + let word_to_base62 = words + .into_iter() + .enumerate() + .map(|(i, w)| (w, index_to_letters(i))) + .collect::>(); + + let mut ser_metric_to_indexes = " +/** @type {Record} */ +const COMPRESSED_METRIC_TO_INDEXES = { +" + .to_string(); + + interface + .metric_to_index_to_vec() + .iter() + .for_each(|(metric, index_to_vec)| { + let indexes = index_to_vec + .keys() + .map(|i| format!("\"{}\"", i.serialize_long())) + .collect::>() + .join(", "); + let indexes = format!("[{indexes}]"); + let unique = unique_index_groups.len(); + let index = index_to_letters(*unique_index_groups.entry(indexes).or_insert(unique)); + + let compressed_metric = metric.split('_').fold(String::new(), |mut acc, w| { + if !acc.is_empty() { + acc.push('_'); + } + acc.push_str(&word_to_base62[w]); + acc + }); + + ser_metric_to_indexes += &format!(" {compressed_metric}: {index},\n"); + }); + + ser_metric_to_indexes += "}; +"; + + let mut sorted_groups: Vec<_> = unique_index_groups.into_iter().collect(); + sorted_groups.sort_by_key(|(_, index)| *index); + sorted_groups.into_iter().for_each(|(group, index)| { + let index = index_to_letters(index); + contents += &format!("/** @type {{Index[]}} */\nconst {index} = {group};\n"); + }); + + contents += &ser_metric_to_indexes; + + fs::write(path, contents) +} + +fn index_to_letters(mut index: usize) -> String { + if index < 52 { + return (index_to_char(index) as char).to_string(); + } + let mut result = [0u8; 8]; + let mut pos = 8; + loop { + pos -= 1; + result[pos] = index_to_char(index % 52); + index /= 52; + if index == 0 { + break; + } + index -= 1; + } + unsafe { String::from_utf8_unchecked(result[pos..].to_vec()) } +} + +fn index_to_char(index: usize) -> u8 { + match index { + 0..=25 => b'A' + index as u8, + 26..=51 => b'a' + (index - 26) as u8, + _ => unreachable!(), + } +} + +// fn letters_to_index(s: &str) -> usize { +// let mut result = 0; +// for byte in s.bytes() { +// let value = char_to_index(byte) as usize; +// result = result * 52 + value + 1; +// } +// result - 1 +// } + +// fn char_to_index(byte: u8) -> u8 { +// match byte { +// b'A'..=b'Z' => byte - b'A', +// b'a'..=b'z' => byte - b'a' + 26, +// _ => 255, // Invalid +// } +// } diff --git a/crates/brk_bridge/src/lib.rs b/crates/brk_bridge/src/lib.rs new file mode 100644 index 000000000..09e0b7629 --- /dev/null +++ b/crates/brk_bridge/src/lib.rs @@ -0,0 +1,5 @@ +mod js; + +pub use js::Bridge; + +pub const VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/crates/brk_bridge/src/python.rs b/crates/brk_bridge/src/python.rs new file mode 100644 index 000000000..8215809c2 --- /dev/null +++ b/crates/brk_bridge/src/python.rs @@ -0,0 +1 @@ +// TODO ? diff --git a/crates/brk_cli/Cargo.toml b/crates/brk_cli/Cargo.toml index c9ae06fc4..c5c82044b 100644 --- a/crates/brk_cli/Cargo.toml +++ b/crates/brk_cli/Cargo.toml @@ -11,6 +11,7 @@ build = "build.rs" [dependencies] bitcoincore-rpc = { workspace = true } +brk_bridge = { workspace = true } brk_bundler = { workspace = true } brk_computer = { workspace = true } brk_fetcher = { workspace = true } diff --git a/crates/brk_cli/src/bridge.rs b/crates/brk_cli/src/bridge.rs deleted file mode 100644 index e467df158..000000000 --- a/crates/brk_cli/src/bridge.rs +++ /dev/null @@ -1,154 +0,0 @@ -use std::{fs, io, path::Path}; - -use brk_interface::{Index, Interface}; -use brk_server::VERSION; -use brk_structs::pools; - -use crate::website::Website; - -const BRIDGE_PATH: &str = "scripts/bridge"; - -#[allow(clippy::upper_case_acronyms)] -pub trait Bridge { - fn generate_bridge_files(&self, website: Website, websites_path: &Path) -> io::Result<()>; -} - -impl Bridge for Interface<'static> { - fn generate_bridge_files(&self, website: Website, websites_path: &Path) -> io::Result<()> { - if website.is_none() { - return Ok(()); - } - - let path = websites_path.join(website.to_folder_name()); - - if !fs::exists(&path)? { - return Ok(()); - } - - let path = path.join(BRIDGE_PATH); - - fs::create_dir_all(&path)?; - - generate_metrics_file(self, &path)?; - generate_pools_file(&path) - } -} - -fn generate_pools_file(parent: &Path) -> io::Result<()> { - let path = parent.join(Path::new("pools.js")); - - let pools = pools(); - - let mut contents = "// -// File auto-generated, any modifications will be overwritten -// -" - .to_string(); - - contents += " -/** @typedef {ReturnType} Pools */ -/** @typedef {keyof Pools} Pool */ - -export function createPools() { -return /** @type {const} */ ({ -"; - - let mut sorted_pools: Vec<_> = pools.iter().collect(); - sorted_pools.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase())); - - contents += &sorted_pools - .iter() - .map(|pool| { - let id = pool.serialized_id(); - format!(" {id}: \"{}\",", pool.name) - }) - .collect::>() - .join("\n"); - - contents += "\n });\n}\n"; - - fs::write(path, contents) -} - -fn generate_metrics_file(interface: &Interface<'static>, parent: &Path) -> io::Result<()> { - let path = parent.join(Path::new("metrics.js")); - - let indexes = Index::all(); - - let mut contents = format!( - "// -// File auto-generated, any modifications will be overwritten -// - -export const VERSION = \"v{VERSION}\"; - -" - ); - - contents += &indexes - .iter() - .enumerate() - .map(|(i_of_i, i)| { - // let lowered = i.to_string().to_lowercase(); - format!("/** @typedef {{{i_of_i}}} {i} */",) - }) - .collect::>() - .join("\n"); - - contents += &format!( - "\n\n/** @typedef {{{}}} Index */\n", - indexes - .iter() - .map(|i| i.to_string()) - .collect::>() - .join(" | ") - ); - - contents += " -/** @typedef {ReturnType} Indexes */ - -export function createIndexes() { -return { -"; - - contents += &indexes - .iter() - .enumerate() - .map(|(i_of_i, i)| { - let lowered = i.to_string().to_lowercase(); - format!(" {lowered}: /** @satisfies {{{i}}} */ ({i_of_i}),",) - }) - .collect::>() - .join("\n"); - - contents += " };\n}\n"; - - contents += " -/** @typedef {ReturnType} MetricToIndexes -/** @typedef {keyof MetricToIndexes} Metric */ - -/** -* @returns {Record} -*/ -export function createMetricToIndexes() { -return { -"; - - interface - .id_to_index_to_vec() - .iter() - .for_each(|(id, index_to_vec)| { - let indexes = index_to_vec - .keys() - .map(|i| (*i as u8).to_string()) - // .map(|i| i.to_string()) - .collect::>() - .join(", "); - - contents += &format!(" \"{id}\": [{indexes}],\n"); - }); - - contents += " };\n}\n"; - - fs::write(path, contents) -} diff --git a/crates/brk_cli/src/lib.rs b/crates/brk_cli/src/lib.rs index d9f22088b..3b6019374 100644 --- a/crates/brk_cli/src/lib.rs +++ b/crates/brk_cli/src/lib.rs @@ -9,6 +9,7 @@ use std::{ }; use bitcoincore_rpc::{self, RpcApi}; +use brk_bridge::Bridge; use brk_bundler::bundle; use brk_computer::Computer; use brk_indexer::Indexer; @@ -18,12 +19,11 @@ use brk_server::{Server, VERSION}; use log::info; use vecdb::Exit; -mod bridge; mod config; mod paths; mod website; -use crate::{bridge::Bridge, config::Config, paths::*}; +use crate::{config::Config, paths::*}; pub fn main() -> color_eyre::Result<()> { color_eyre::install()?; @@ -51,97 +51,107 @@ pub fn run() -> color_eyre::Result<()> { let mut indexer = Indexer::forced_import(&config.brkdir())?; - let wait_for_synced_node = |rpc_client: &bitcoincore_rpc::Client| -> color_eyre::Result<()> { - let is_synced = || -> color_eyre::Result { - let info = rpc_client.get_blockchain_info()?; - Ok(info.headers == info.blocks) + let mut computer = Computer::forced_import(&config.brkdir(), &indexer, config.fetcher())?; + + let interface = Interface::build(&parser, &indexer, &computer); + + let website = config.website(); + + let downloads_path = config.downloads_dir(); + + let future = async { + let bundle_path = if website.is_some() { + let websites_dev_path = Path::new("../../websites"); + let packages_dev_path = Path::new("../../packages"); + + let websites_path; + let packages_path; + + if fs::exists(websites_dev_path)? { + websites_path = websites_dev_path.to_path_buf(); + packages_path = packages_dev_path.to_path_buf(); + } else { + let downloaded_brk_path = downloads_path.join(format!("brk-{VERSION}")); + + let downloaded_websites_path = downloaded_brk_path.join("websites"); + let downloaded_packages_path = downloaded_brk_path.join("packages"); + + if !fs::exists(&downloaded_websites_path)? { + info!("Downloading source from Github..."); + + let url = format!( + "https://github.com/bitcoinresearchkit/brk/archive/refs/tags/v{VERSION}.zip", + ); + + let response = minreq::get(url).send()?; + let bytes = response.as_bytes(); + let cursor = Cursor::new(bytes); + + let mut zip = zip::ZipArchive::new(cursor).unwrap(); + + zip.extract(downloads_path).unwrap(); + } + + websites_path = downloaded_websites_path; + packages_path = downloaded_packages_path; + } + + interface.generate_js_files(&packages_path)?; + + Some(bundle(&websites_path, website.to_folder_name(), true).await?) + } else { + None }; - if !is_synced()? { - info!("Waiting for node to be synced..."); - while !is_synced()? { + let server = Server::new(interface, bundle_path); + + tokio::spawn(async move { + server.serve(true).await.unwrap(); + }); + + sleep(Duration::from_secs(1)); + + loop { + wait_for_synced_node(rpc)?; + + let block_count = rpc.get_block_count()?; + + info!("{} blocks found.", block_count + 1); + + let starting_indexes = indexer + .index(&parser, rpc, &exit, config.check_collisions()) + .unwrap(); + + computer + .compute(&indexer, starting_indexes, &parser, &exit) + .unwrap(); + + info!("Waiting for new blocks..."); + + while block_count == rpc.get_block_count()? { sleep(Duration::from_secs(1)) } } - - Ok(()) }; - let mut computer = Computer::forced_import(&config.brkdir(), &indexer, config.fetcher())?; - tokio::runtime::Builder::new_multi_thread() .enable_all() .build()? - .block_on(async { - let interface = Interface::build(&parser, &indexer, &computer); - - let website = config.website(); - - let downloads_path = config.downloads_dir(); - - let bundle_path = if website.is_some() { - let websites_dev_path = Path::new("../../websites"); - - let websites_path = if fs::exists(websites_dev_path)? { - websites_dev_path.to_path_buf() - } else { - let downloaded_websites_path = - downloads_path.join(format!("brk-{VERSION}")).join("websites"); - - if !fs::exists(&downloaded_websites_path)? { - info!("Downloading websites from Github..."); - - let url = format!( - "https://github.com/bitcoinresearchkit/brk/archive/refs/tags/v{VERSION}.zip", - ); - - let response = minreq::get(url).send()?; - let bytes = response.as_bytes(); - let cursor = Cursor::new(bytes); - - let mut zip = zip::ZipArchive::new(cursor).unwrap(); - - zip.extract(downloads_path).unwrap(); - } - - downloaded_websites_path - }; - - interface.generate_bridge_files(website, websites_path.as_path())?; - - Some(bundle(&websites_path, website.to_folder_name(), true).await?) - } else { - None - }; - - let server = Server::new( - interface, - bundle_path, - ); - - tokio::spawn(async move { - server.serve(true).await.unwrap(); - }); - - sleep(Duration::from_secs(1)); - - loop { - wait_for_synced_node(rpc)?; - - let block_count = rpc.get_block_count()?; - - info!("{} blocks found.", block_count + 1); - - let starting_indexes = - indexer.index(&parser, rpc, &exit, config.check_collisions()).unwrap(); - - computer.compute(&indexer, starting_indexes, &parser, &exit).unwrap(); - - info!("Waiting for new blocks..."); - - while block_count == rpc.get_block_count()? { - sleep(Duration::from_secs(1)) - } - } - }) + .block_on(future) +} + +fn wait_for_synced_node(rpc_client: &bitcoincore_rpc::Client) -> color_eyre::Result<()> { + let is_synced = || -> color_eyre::Result { + let info = rpc_client.get_blockchain_info()?; + Ok(info.headers == info.blocks) + }; + + if !is_synced()? { + info!("Waiting for node to be synced..."); + while !is_synced()? { + sleep(Duration::from_secs(1)) + } + } + + Ok(()) } diff --git a/crates/brk_interface/src/lib.rs b/crates/brk_interface/src/lib.rs index 7e5160335..6e3ede143 100644 --- a/crates/brk_interface/src/lib.rs +++ b/crates/brk_interface/src/lib.rs @@ -30,7 +30,7 @@ pub use pagination::{PaginatedIndexParam, PaginationParam}; pub use params::{IdParam, Params, ParamsOpt}; use vecs::Vecs; -use crate::vecs::{IdToVec, IndexToVec}; +use crate::vecs::{IndexToVec, MetricToVec}; pub fn cached_errors() -> &'static Cache { static CACHE: OnceLock> = OnceLock::new(); @@ -70,7 +70,7 @@ impl<'a> Interface<'a> { let ids_to_vec = self .vecs - .index_to_id_to_vec + .index_to_metric_to_vec .get(&index) .ok_or(Error::String(format!( "Index \"{}\" isn't a valid index", @@ -111,7 +111,7 @@ impl<'a> Interface<'a> { &format!("\nMaybe you meant one of the following: {matches:#?} ?\n"); } - if let Some(index_to_vec) = self.id_to_index_to_vec().get(id.as_str()) { + if let Some(index_to_vec) = self.metric_to_index_to_vec().get(id.as_str()) { message += &format!("\nBut there is a vec named {id} which supports the following indexes: {:#?}\n", index_to_vec.keys()); } @@ -214,16 +214,16 @@ impl<'a> Interface<'a> { self.format(self.search(¶ms)?, ¶ms.rest) } - pub fn id_to_index_to_vec(&self) -> &BTreeMap<&str, IndexToVec<'_>> { - &self.vecs.id_to_index_to_vec + pub fn metric_to_index_to_vec(&self) -> &BTreeMap<&str, IndexToVec<'_>> { + &self.vecs.metric_to_index_to_vec } - pub fn index_to_id_to_vec(&self) -> &BTreeMap> { - &self.vecs.index_to_id_to_vec + pub fn index_to_metric_to_vec(&self) -> &BTreeMap> { + &self.vecs.index_to_metric_to_vec } - pub fn get_vecid_count(&self) -> usize { - self.vecs.id_count + pub fn get_metric_count(&self) -> usize { + self.vecs.metric_count } pub fn get_index_count(&self) -> usize { @@ -242,8 +242,8 @@ impl<'a> Interface<'a> { &self.vecs.accepted_indexes } - pub fn get_vecids(&self, pagination: PaginationParam) -> &[&str] { - self.vecs.ids(pagination) + pub fn get_metrics(&self, pagination: PaginationParam) -> &[&str] { + self.vecs.metrics(pagination) } pub fn get_index_to_vecids(&self, paginated_index: PaginatedIndexParam) -> Vec<&str> { diff --git a/crates/brk_interface/src/vecs.rs b/crates/brk_interface/src/vecs.rs index aa7f5ca25..22bc1b9f4 100644 --- a/crates/brk_interface/src/vecs.rs +++ b/crates/brk_interface/src/vecs.rs @@ -11,16 +11,16 @@ use super::index::Index; #[derive(Default)] pub struct Vecs<'a> { - pub id_to_index_to_vec: BTreeMap<&'a str, IndexToVec<'a>>, - pub index_to_id_to_vec: BTreeMap>, - pub ids: Vec<&'a str>, + pub metric_to_index_to_vec: BTreeMap<&'a str, IndexToVec<'a>>, + pub index_to_metric_to_vec: BTreeMap>, + pub metrics: Vec<&'a str>, pub indexes: Vec<&'static str>, pub accepted_indexes: BTreeMap<&'static str, &'static [&'static str]>, pub index_count: usize, - pub id_count: usize, + pub metric_count: usize, pub vec_count: usize, - id_to_indexes: BTreeMap<&'a str, Vec<&'static str>>, - indexes_to_ids: BTreeMap>, + metric_to_indexes: BTreeMap<&'a str, Vec<&'static str>>, + index_to_metrics: BTreeMap>, } impl<'a> Vecs<'a> { @@ -33,7 +33,11 @@ impl<'a> Vecs<'a> { .iter_any_collectable() .for_each(|vec| this.insert(vec)); - let mut ids = this.id_to_index_to_vec.keys().cloned().collect::>(); + let mut ids = this + .metric_to_index_to_vec + .keys() + .cloned() + .collect::>(); let sort_ids = |ids: &mut Vec<&str>| { ids.sort_unstable_by(|a, b| { @@ -48,26 +52,26 @@ impl<'a> Vecs<'a> { sort_ids(&mut ids); - this.ids = ids; - this.id_count = this.id_to_index_to_vec.keys().count(); - this.index_count = this.index_to_id_to_vec.keys().count(); + this.metrics = ids; + this.metric_count = this.metric_to_index_to_vec.keys().count(); + this.index_count = this.index_to_metric_to_vec.keys().count(); this.vec_count = this - .index_to_id_to_vec + .index_to_metric_to_vec .values() .map(|tree| tree.len()) .sum::(); this.indexes = this - .index_to_id_to_vec + .index_to_metric_to_vec .keys() .map(|i| i.serialize_long()) .collect::>(); this.accepted_indexes = this - .index_to_id_to_vec + .index_to_metric_to_vec .keys() .map(|i| (i.serialize_long(), i.possible_values())) .collect::>(); - this.id_to_indexes = this - .id_to_index_to_vec + this.metric_to_indexes = this + .metric_to_index_to_vec .iter() .map(|(id, index_to_vec)| { ( @@ -79,12 +83,12 @@ impl<'a> Vecs<'a> { ) }) .collect(); - this.indexes_to_ids = this - .index_to_id_to_vec + this.index_to_metrics = this + .index_to_metric_to_vec .iter() .map(|(index, id_to_vec)| (*index, id_to_vec.keys().cloned().collect::>())) .collect(); - this.indexes_to_ids + this.index_to_metrics .values_mut() .for_each(|ids| sort_ids(ids)); @@ -101,7 +105,7 @@ impl<'a> Vecs<'a> { }) .unwrap(); let prev = self - .id_to_index_to_vec + .metric_to_index_to_vec .entry(name) .or_default() .insert(index, vec); @@ -110,7 +114,7 @@ impl<'a> Vecs<'a> { panic!() } let prev = self - .index_to_id_to_vec + .index_to_metric_to_vec .entry(index) .or_default() .insert(name, vec); @@ -120,22 +124,22 @@ impl<'a> Vecs<'a> { } } - pub fn ids(&self, pagination: PaginationParam) -> &[&'_ str] { - let len = self.ids.len(); + pub fn metrics(&self, pagination: PaginationParam) -> &[&'_ str] { + let len = self.metrics.len(); let start = pagination.start(len); let end = pagination.end(len); - &self.ids[start..end] + &self.metrics[start..end] } pub fn id_to_indexes(&self, id: String) -> Option<&Vec<&'static str>> { - self.id_to_indexes.get(id.as_str()) + self.metric_to_indexes.get(id.as_str()) } pub fn index_to_ids( &self, PaginatedIndexParam { index, pagination }: PaginatedIndexParam, ) -> Vec<&'a str> { - let vec = self.indexes_to_ids.get(&index).unwrap(); + let vec = self.index_to_metrics.get(&index).unwrap(); let len = vec.len(); let start = pagination.start(len); @@ -149,4 +153,4 @@ impl<'a> Vecs<'a> { pub struct IndexToVec<'a>(BTreeMap); #[derive(Default, Deref, DerefMut)] -pub struct IdToVec<'a>(BTreeMap<&'a str, &'a dyn AnyCollectableVec>); +pub struct MetricToVec<'a>(BTreeMap<&'a str, &'a dyn AnyCollectableVec>); diff --git a/crates/brk_mcp/src/lib.rs b/crates/brk_mcp/src/lib.rs index 0e6e0978d..2a0d2ff1c 100644 --- a/crates/brk_mcp/src/lib.rs +++ b/crates/brk_mcp/src/lib.rs @@ -40,12 +40,12 @@ Get the count of all existing indexes. } #[tool(description = " -Get the count of all existing vec ids. +Get the count of all existing metrics. ")] - async fn get_vecid_count(&self) -> Result { - info!("mcp: get_vecid_count"); + async fn get_metric_count(&self) -> Result { + info!("mcp: get_metric_count"); Ok(CallToolResult::success(vec![ - Content::json(self.interface.get_vecid_count()).unwrap(), + Content::json(self.interface.get_metric_count()).unwrap(), ])) } @@ -89,9 +89,9 @@ If the `page` param is omitted, it will default to the first page. &self, Parameters(pagination): Parameters, ) -> Result { - info!("mcp: get_vecids"); + info!("mcp: get_metrics"); Ok(CallToolResult::success(vec![ - Content::json(self.interface.get_vecids(pagination)).unwrap(), + Content::json(self.interface.get_metrics(pagination)).unwrap(), ])) } diff --git a/crates/brk_server/src/api/mod.rs b/crates/brk_server/src/api/mod.rs index 27172d43a..5b4584893 100644 --- a/crates/brk_server/src/api/mod.rs +++ b/crates/brk_server/src/api/mod.rs @@ -229,9 +229,9 @@ impl ApiRoutes for Router { }), ) .route( - "/api/vecs/id-count", + "/api/vecs/metric-count", get(async |State(app_state): State| -> Response { - Json(app_state.interface.get_vecid_count()).into_response() + Json(app_state.interface.get_metric_count()).into_response() }), ) .route( @@ -253,17 +253,17 @@ impl ApiRoutes for Router { }), ) .route( - "/api/vecs/ids", + "/api/vecs/metrics", get( async |State(app_state): State, Query(pagination): Query| -> Response { - Json(app_state.interface.get_vecids(pagination)).into_response() + Json(app_state.interface.get_metrics(pagination)).into_response() }, ), ) .route( - "/api/vecs/index-to-ids", + "/api/vecs/index-to-metrics", get( async |State(app_state): State, Query(paginated_index): Query| diff --git a/docs/TODO.md b/docs/TODO.md index 3bf607596..53bdf90b1 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -93,6 +93,8 @@ - _STORE_ - save height and version in one file - _STRUCTS_ + - _GLOBAL_ + - https://davidlattimore.github.io/posts/2025/09/02/rustforge-wild-performance-tricks.html - __DOCS__ - _README_ - add a comparison table with alternatives @@ -145,6 +147,7 @@ - https://fonts.google.com/specimen/Space+Mono - keep as many files as possible [under 14kb](https://endtimes.dev/why-your-website-should-be-under-14kb-in-size/) - [No classes](https://news.ycombinator.com/item?id=45287155) + - [Organic animations](https://courses.joshwcomeau.com/playground/magic-wand-final) - __GLOBAL__ - check `TODO`s in codebase - rename `output` to `txout` or `vout`, `input` to `txin` or `vin` diff --git a/websites/packages/.gitignore b/packages/.gitignore similarity index 100% rename from websites/packages/.gitignore rename to packages/.gitignore diff --git a/packages/brk/.gitignore b/packages/brk/.gitignore new file mode 100644 index 000000000..86d4c2dd3 --- /dev/null +++ b/packages/brk/.gitignore @@ -0,0 +1 @@ +generated diff --git a/websites/packages/brk/idle.js b/packages/brk/idle.js similarity index 100% rename from websites/packages/brk/idle.js rename to packages/brk/idle.js diff --git a/websites/packages/brk/index.js b/packages/brk/index.js similarity index 100% rename from websites/packages/brk/index.js rename to packages/brk/index.js diff --git a/packages/brk/metrics.js b/packages/brk/metrics.js new file mode 100644 index 000000000..e69de29bb diff --git a/packages/brk/pools.js b/packages/brk/pools.js new file mode 100644 index 000000000..e69de29bb diff --git a/websites/packages/brk/standalone.js b/packages/brk/standalone.js similarity index 100% rename from websites/packages/brk/standalone.js rename to packages/brk/standalone.js diff --git a/packages/brk/types.js b/packages/brk/types.js new file mode 100644 index 000000000..03df82f79 --- /dev/null +++ b/packages/brk/types.js @@ -0,0 +1,7 @@ +/** + * @import { Signal, Signals, Accessor } from "../solidjs-signals/index"; + * + * @import { Index } from "./metrics" + * + * @typedef {[number, number, number, number]} OHLCTuple + */ diff --git a/websites/packages/jsconfig.json b/packages/jsconfig.json similarity index 69% rename from websites/packages/jsconfig.json rename to packages/jsconfig.json index 4f31f3562..cffb39bbd 100644 --- a/websites/packages/jsconfig.json +++ b/packages/jsconfig.json @@ -6,5 +6,5 @@ "module": "ESNext", "skipLibCheck": true }, - "exclude": ["scripts/packages", "scripts/bridge", "spmething"] + "exclude": ["dist"] } diff --git a/websites/packages/lean-qr/.gitignore b/packages/lean-qr/.gitignore similarity index 100% rename from websites/packages/lean-qr/.gitignore rename to packages/lean-qr/.gitignore diff --git a/websites/packages/lean-qr/2.5.0/index.d.ts b/packages/lean-qr/2.5.0/index.d.ts similarity index 100% rename from websites/packages/lean-qr/2.5.0/index.d.ts rename to packages/lean-qr/2.5.0/index.d.ts diff --git a/websites/packages/lean-qr/2.5.0/index.mjs b/packages/lean-qr/2.5.0/index.mjs similarity index 100% rename from websites/packages/lean-qr/2.5.0/index.mjs rename to packages/lean-qr/2.5.0/index.mjs diff --git a/packages/lean-qr/2.6.0/index.d.ts b/packages/lean-qr/2.6.0/index.d.ts new file mode 100644 index 000000000..9764296d1 --- /dev/null +++ b/packages/lean-qr/2.6.0/index.d.ts @@ -0,0 +1,656 @@ +declare module 'lean-qr' { + interface ImageDataLike { + readonly data: Uint8ClampedArray; + } + + interface Context2DLike { + createImageData(width: number, height: number): DataT; + putImageData(data: DataT, x: number, y: number): void; + } + + interface CanvasLike { + width: number; + height: number; + getContext(type: '2d'): Context2DLike | null; + } + + /** + * A colour in `[red, green, blue, alpha]` format (all values from 0 to 255). + * If alpha is omitted, it is assumed to be 255 (opaque). + */ + export type RGBA = readonly [number, number, number, number?]; + + export interface Bitmap1D { + /** + * Appends a sequence of bits. + * + * @param value an integer containing the bits to append (big endian). + * @param bits the number of bits to read from `value`. Must be between 1 and 24. + */ + push(value: number, bits: number): void; + } + + export interface StringOptions { + /** the text to use for modules which are 'on' (typically black) */ + on?: string; + + /** the text to use for modules which are 'off' (typically white) */ + off?: string; + + /** the text to use for linefeeds between rows */ + lf?: string; + + /** the padding to apply around the output (populated with 'off' modules) */ + pad?: number; + + /** + * the padding to apply on the left and right of the output (populated with 'off' modules) + * @deprecated use `pad` instead + */ + padX?: number; + + /** + * the padding to apply on the top and bottom of the output (populated with 'off' modules) + * @deprecated use `pad` instead + */ + padY?: number; + } + + export interface ImageDataOptions { + /** the colour to use for modules which are 'on' (typically black) */ + on?: RGBA; + + /** the colour to use for modules which are 'off' (typically white) */ + off?: RGBA; + + /** the padding to apply around the output (filled with 'off') */ + pad?: number; + + /** + * the padding to apply on the left and right of the output (filled with 'off') + * @deprecated use `pad` instead + */ + padX?: number; + + /** + * the padding to apply on the top and bottom of the output (filled with 'off') + * @deprecated use `pad` instead + */ + padY?: number; + } + + export interface Bitmap2D { + /** the width / height of the QR code in modules (excluding any padding) */ + readonly size: number; + + /** + * Read the state of a module from the QR code. + * + * @param x the x coordinate to read. Can be negative / out of bounds. + * @param y the y coordinate to read. Can be negative / out of bounds. + * @returns true if the requested module is set (i.e. typically black) + */ + get(x: number, y: number): boolean; + + /** + * Generate a string containing the QR code, suitable for displaying in a + * terminal environment. Generally, you should customise on and off to use + * the ANSI escapes of your target terminal for better rendering. + * + * @param options optional configuration for the display. + */ + toString(options?: Readonly): string; + + /** + * Generate image data containing the QR code, at a scale of 1 pixel per + * module. Use this if you need more control than toCanvas allows. + * + * @param context a context to use for creating the image data. + * @param options optional configuration for the display. + */ + toImageData( + context: Context2DLike, + options?: Readonly, + ): DataT; + + /** + * Generate a `data:image/*` URL for the QR code. + * + * @param options optional configuration for the output. + * @returns a string suitable for use as the `src` of an `img` tag. + */ + toDataURL( + options?: Readonly< + ImageDataOptions & { + type?: `image/${string}`; + scale?: number; + } + >, + ): string; + + /** + * Populate a given canvas with the QR code, at a scale of 1 pixel per + * module. Set image-rendering: pixelated and scale the canvas using CSS + * for a large image. Automatically resizes the canvas to fit the QR code + * if necessary. + * + * @param canvas the canvas to populate. + * @param options optional configuration for the display. + */ + toCanvas( + canvas: CanvasLike, + options?: Readonly, + ): void; + } + + export type Mask = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7; + export type Mode = (data: Bitmap1D, version: number) => void; + export interface ModeFactory { + (value: string): Mode; + /** a function which returns true when given a character which the current mode can represent */ + test(string: string): boolean; + /** a function which returns an estimate of the number of bits required to encode a given value */ + est(value: string, version: number): number; + /** an optional ECI which must be active for this mode to be interpreted correctly by a reader */ + eci?: number; + } + + interface ModeAutoOptions { + /** a list of modes which can be considered when encoding a message */ + modes?: ReadonlyArray; + } + + export const mode: Readonly<{ + /** automatically picks the most optimal combination of modes for the requested message */ + auto(value: string, options?: Readonly): Mode; + /** concatenates multiple modes together */ + multi(...modes: ReadonlyArray): Mode; + /** sets the Extended Channel Interpretation for the message from this point onwards */ + eci(id: number): Mode; + /** supports `0-9` and stores 3 characters per 10 bits */ + numeric: ModeFactory; + /** supports `0-9A-Z $%*+-./:` and stores 2 characters per 11 bits */ + alphaNumeric: ModeFactory; + /** arbitrary byte data, typically combined with `eci` */ + bytes(data: Uint8Array | ReadonlyArray): Mode; + /** supports 7-bit ASCII and stores 1 character per 8 bits with no ECI */ + ascii: ModeFactory; + /** supports 8-bit ISO-8859-1 and stores 1 character per 8 bits with ECI 3 */ + iso8859_1: ModeFactory; + /** supports double-byte Shift-JIS characters stores 1 character per 13 bits */ + shift_jis: ModeFactory; + /** supports variable length UTF-8 with ECI 26 */ + utf8: ModeFactory; + }>; + + export type Correction = number & { readonly _: unique symbol }; + export const correction: Readonly<{ + /** + * minimum possible correction level (same as L) + * @deprecated use correction.L + */ + min: Correction; + /** ~7.5% error tolerance, ~25% data overhead */ + L: Correction; + /** ~15% error tolerance, ~60% data overhead */ + M: Correction; + /** ~22.5% error tolerance, ~120% data overhead */ + Q: Correction; + /** ~30% error tolerance, ~190% data overhead */ + H: Correction; + /** + * maximum possible correction level (same as H) + * @deprecated use correction.H + */ + max: Correction; + }>; + + export interface GenerateOptions extends ModeAutoOptions { + /** the minimum correction level to use (higher levels may still be used if the chosen version has space) */ + minCorrectionLevel?: Correction; + /** the maximum correction level to use */ + maxCorrectionLevel?: Correction; + /** the minimum version (size) of code to generate (must be between 1 and 40) */ + minVersion?: number; + /** the maximum version (size) of code to generate (must be between 1 and 40) */ + maxVersion?: number; + /** a mask to use on the QR code (should be left as `null` for ISO compliance but may be changed for artistic effect) */ + mask?: null | Mask; + /** padding bits to use for extra space in the QR code (should be left as the default for ISO compliance but may be changed for artistic effect) */ + trailer?: number; + } + + /** + * Generate a QR code. + * + * @param data either a string, or a pre-encoded mode. + * @param options optional configuration for the QR code. + * @returns the requested QR code. + */ + export type GenerateFn = ( + data: Mode | string, + options?: Readonly, + ) => Bitmap2D; + interface Generate extends GenerateFn { + /** + * Creates a scoped `generate` function which considers additional modes + * when using auto encoding. + * + * @param modes the modes to add. + * @returns a `generate` function which will additionally consider the + * given modes when using auto encoding. + * + * @deprecated this will be removed in version 3. Prefer passing an explicit list of modes when calling `generate`. + */ + with(...modes: ReadonlyArray): GenerateFn; + } + export const generate: Generate; +} + +declare module 'lean-qr/nano' { + import type { + Correction, + Bitmap2D as FullBitmap2D, + GenerateOptions as FullGenerateOptions, + } from 'lean-qr'; + import { correction as fullCorrection } from 'lean-qr'; + + export type { Correction }; + + export const correction: Pick; + + export type Bitmap2D = Pick; + + export type GenerateOptions = Pick< + FullGenerateOptions, + 'minCorrectionLevel' | 'minVersion' + >; + + /** + * Generate a QR code. + * + * @param data either a string, or a pre-encoded mode. + * @param options optional configuration for the QR code. + * @returns the requested QR code. + */ + export function generate( + data: string, + options?: Readonly, + ): Bitmap2D; +} + +declare module 'lean-qr/extras/svg' { + import type { Bitmap2D as FullBitmap2D } from 'lean-qr'; + + type Bitmap2D = Pick; + + export interface SVGOptions { + /** the colour to use for modules which are 'on' (typically black) */ + on?: string; + /** the colour to use for modules which are 'off' (typically white) */ + off?: string; + /** the padding to apply around the output (filled with 'off') */ + pad?: number; + /** + * the padding to apply on the left and right of the output (filled with 'off') + * @deprecated use `pad` instead + */ + padX?: number; + /** + * the padding to apply on the top and bottom of the output (filled with 'off') + * @deprecated use `pad` instead + */ + padY?: number; + /** a width to apply to the resulting image (overrides `scale`) */ + width?: number | null; + /** a height to apply to the resulting image (overrides `scale`) */ + height?: number | null; + /** a scale to apply to the resulting image (`scale` pixels = 1 module) */ + scale?: number; + } + + /** + * Generate the raw outline of the QR code for use in an existing SVG. + * + * @param code the QR code to convert. + * @returns a string suitable for passing to the `d` attribute of a `path`. + */ + export function toSvgPath(code: Bitmap2D): string; + + /** + * Generate an SVG element which can be added to the DOM. + * + * @param code the QR code to convert. + * @param options optional configuration for the display. + * @returns an SVG element. + */ + export function toSvg( + code: Bitmap2D, + target: Document | SVGElement, + options?: Readonly, + ): SVGElement; + + /** + * Generate an SVG document which can be exported to a file or served from a + * web server. + * + * @param code the QR code to convert. + * @param options optional configuration for the display. + * @returns an SVG document. + */ + export function toSvgSource( + code: Bitmap2D, + options?: Readonly< + SVGOptions & { + /** `true` to include an XML declaration at the start of the source (for standalone documents which will not be embedded inside another document) */ + xmlDeclaration?: boolean; + } + >, + ): string; + + /** + * Generate a `data:image/svg+xml` URL. + * + * @param code the QR code to convert. + * @param options optional configuration for the display. + * @returns a string suitable for use as the `src` of an `img` tag. + */ + export function toSvgDataURL( + code: Bitmap2D, + options?: Readonly, + ): string; +} + +declare module 'lean-qr/extras/node_export' { + import type { RGBA, Bitmap2D as FullBitmap2D } from 'lean-qr'; + + type Bitmap2D = Pick; + + export interface PNGOptions { + /** the colour to use for modules which are 'on' (typically black) */ + on?: RGBA; + /** the colour to use for modules which are 'off' (typically white) */ + off?: RGBA; + /** the padding to apply around the output (filled with 'off') */ + pad?: number; + /** + * the padding to apply on the left and right of the output (filled with 'off') + * @deprecated use `pad` instead + */ + padX?: number; + /** + * the padding to apply on the top and bottom of the output (filled with 'off') + * @deprecated use `pad` instead + */ + padY?: number; + /** a scale to apply to the resulting image (`scale` pixels = 1 module) */ + scale?: number; + } + + /** + * Generate a PNG document which can be exported to a file or served from a + * web server. + * + * @param code the QR code to convert. + * @param options optional configuration for the display. + * @returns a PNG document. + */ + export function toPngBuffer( + code: Bitmap2D, + options?: Readonly, + ): Uint8Array; + + /** + * Generate a `data:image/png` URL. + * + * @param code the QR code to convert. + * @param options optional configuration for the display. + * @returns a string suitable for use as the `src` of an `img` tag. + */ + export function toPngDataURL( + code: Bitmap2D, + options?: Readonly, + ): string; +} + +declare module 'lean-qr/extras/react' { + import type { + Bitmap2D as FullBitmap2D, + GenerateOptions, + ImageDataOptions, + } from 'lean-qr'; + import type { + SVGOptions, + toSvgDataURL as toSvgDataURLFn, + } from 'lean-qr/extras/svg'; + + export interface AsyncFramework { + createElement: ( + type: 'canvas', + props: { + ref: any; + style: { imageRendering: 'pixelated' }; + className: string; + }, + ) => T; + useRef(initialValue: T | null): { readonly current: T | null }; + useEffect(fn: () => void | (() => void), deps: unknown[]): void; + } + + interface QRComponentProps { + content: string; + className?: string; + } + + export interface AsyncQRComponentProps + extends ImageDataOptions, + GenerateOptions, + QRComponentProps {} + + export type AsyncQRComponent = ( + props: Readonly, + ) => T; + + /** + * Generate an asynchronous QR component (rendering to a `canvas`). + * You should call this just once, in the global scope. + * + * ```js + * import * as React from 'react'; + * import { generate } from 'lean-qr'; + * import { makeAsyncComponent } from 'lean-qr/extras/react'; + * const QR = makeAsyncComponent(React, generate); + * ``` + * + * This is not suitable for server-side rendering (use `makeSyncComponent` + * instead). + * + * @param framework the framework to use (e.g. `React`). + * @param generate the `generate` function to use + * (from `lean-qr` or `lean-qr/nano`). + * @param defaultProps optional default properties to apply when the + * component is used (overridden by properties set on use). + * @returns a component which can be rendered elsewhere. + */ + export function makeAsyncComponent( + framework: Readonly>, + generate: ( + data: string, + options?: Readonly, + ) => Pick, + defaultProps?: Readonly>, + ): AsyncQRComponent; + + export interface SyncFramework { + createElement: ( + type: 'img', + props: { + src: string; + style: { imageRendering: 'pixelated' }; + className: string; + }, + ) => T; + useMemo(fn: () => T, deps: unknown[]): T; + } + + export interface SyncQRComponentProps + extends SVGOptions, + GenerateOptions, + QRComponentProps {} + + export type SyncQRComponent = (props: Readonly) => T; + + /** + * Generate a synchronous QR component (rendering to an SVG). + * You should call this just once, in the global scope. + * + * ```js + * import * as React from 'react'; + * import { generate } from 'lean-qr'; + * import { toSvgDataURL } from 'lean-qr/extras/svg'; + * import { makeSyncComponent } from 'lean-qr/extras/react'; + * const QR = makeSyncComponent(React, generate, toSvgDataURL); + * ``` + * + * This is best suited for server-side rendering (prefer + * `makeAsyncComponent` if you only need client-side rendering). + * + * @param framework the framework to use (e.g. `React`). + * @param generate the `generate` function to use + * (from `lean-qr` or `lean-qr/nano`). + * @param toSvgDataURL the `toSvgDataURL` function to use + * (from `lean-qr/extras/svg`). + * @param defaultProps optional default properties to apply when the + * component is used (overridden by properties set on use). + * @returns a component which can be rendered elsewhere. + */ + export function makeSyncComponent( + framework: Readonly>, + generate: ( + data: string, + options?: Readonly, + ) => Pick, + toSvgDataURL: typeof toSvgDataURLFn, + defaultProps?: Readonly>, + ): SyncQRComponent; +} + +declare module 'lean-qr/extras/vue' { + import type { + Bitmap2D as FullBitmap2D, + GenerateOptions, + ImageDataOptions, + } from 'lean-qr'; + import type { + SVGOptions, + toSvgDataURL as toSvgDataURLFn, + } from 'lean-qr/extras/svg'; + + export interface Framework { + h: + | ((type: 'canvas', props: { ref: string; style: string }) => T) + | ((type: 'img', props: { src: string; style: string }) => T); + } + + interface QRComponentProps { + content: string; + } + + export interface VueCanvasComponentProps + extends ImageDataOptions, + GenerateOptions, + QRComponentProps {} + + type VueComponentDefinition = { + props: { + [k in keyof Props]: { + type: { + (): Props[k]; + required: undefined extends Props[k] ? false : true; + }; + }; + }; + render: () => Node; + } & ThisType; + + /** + * Generate a QR component which renders to a `canvas`. + * You should call this just once, in the global scope. + * + * ```js + * import { h, defineComponent } from 'vue'; + * import { generate } from 'lean-qr'; + * import { makeVueCanvasComponent } from 'lean-qr/extras/vue'; + * export const QR = defineComponent(makeVueCanvasComponent({ h }, generate)); + * ``` + * + * This is not suitable for server-side rendering (use `makeSyncComponent` + * instead). + * + * @param framework the framework to use (e.g. `{ h }`). + * @param generate the `generate` function to use + * (from `lean-qr` or `lean-qr/nano`). + * @param defaultProps optional default properties to apply when the + * component is used (overridden by properties set on use). + * @returns a component which can be rendered elsewhere. + */ + export function makeVueCanvasComponent( + framework: Readonly>, + generate: ( + data: string, + options?: Readonly, + ) => Pick, + defaultProps?: Readonly>, + ): VueComponentDefinition, T>; + + export interface VueSVGComponentProps + extends SVGOptions, + GenerateOptions, + QRComponentProps {} + + /** + * Generate a QR component which renders to an SVG. + * You should call this just once, in the global scope: + * + * ```js + * import { h, defineComponent } from 'vue'; + * import { generate } from 'lean-qr'; + * import { toSvgDataURL } from 'lean-qr/extras/svg'; + * import { makeVueSvgComponent } from 'lean-qr/extras/vue'; + * export const QR = defineComponent(makeVueSvgComponent({ h }, generate, toSvgDataURL)); + * ``` + * + * This is best suited for server-side rendering (prefer + * `makeAsyncComponent` if you only need client-side rendering). + * + * @param framework the framework to use (e.g. `{ h }`). + * @param generate the `generate` function to use + * (from `lean-qr` or `lean-qr/nano`). + * @param toSvgDataURL the `toSvgDataURL` function to use + * (from `lean-qr/extras/svg`). + * @param defaultProps optional default properties to apply when the + * component is used (overridden by properties set on use). + * @returns a component which can be rendered elsewhere. + */ + export function makeVueSvgComponent( + framework: Readonly>, + generate: ( + data: string, + options?: Readonly, + ) => Pick, + toSvgDataURL: typeof toSvgDataURLFn, + defaultProps?: Readonly>, + ): VueComponentDefinition, T>; +} + +declare module 'lean-qr/extras/errors' { + /** + * Convert an error into a human-readable message. This is intended for use + * with Lean QR errors, but will return somewhat meaningful messages for + * other errors too. + * + * @param error the error to convert. + * @returns a human-readable message explaining the error. + */ + export function readError(error: unknown): string; +} diff --git a/packages/lean-qr/2.6.0/index.mjs b/packages/lean-qr/2.6.0/index.mjs new file mode 100644 index 000000000..c83e283e3 --- /dev/null +++ b/packages/lean-qr/2.6.0/index.mjs @@ -0,0 +1 @@ +const t=[.2,3/8,5/9,2/3],o=(o,e)=>r=>{const n=4*o+r-4,s="*-04-39?2$%%$%%'$%''%'''%')(%'))%(++'(++'(+.'+-.',/3',33)-/5)-43).36)058*18<+37<+4:<,4:E,5C/8@F/:EH/8?s:1,c=e/f|0,i=e%f,l=f-i,a=n>8?c*t[r]+(o>5)&-2:s,_=c-a;return{t:l*_+i*_+i,o:[[l,_],[i,_+1]],i:a}},e={min:0,L:0,M:1,Q:2,H:3,max:3},r=t=>new Uint8Array(t),n=t=>{const o=new Error(`lean-qr error ${t}`);throw o.code=t,o},s=t=>"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:".indexOf(t),f=t=>t.charCodeAt(0),c=(...t)=>(o,e)=>t.forEach(t=>t(o,e)),i=t=>o=>{o.eci!==t&&(o.push(7,4),o.push(t,8),o.eci=t)},l=t=>(o,e)=>{o.push(4,4),o.push(t.length,8+8*(e>9)),t.forEach(t=>o.push(t,8))},a=(t,o,e,r,n=(t,o)=>e(t.length,o),s=(r?o=>c(i(r),t(o)):t))=>(s.test=o,s.l=e,s.est=n,s.eci=r&&[r],s),_=a(t=>(o,e)=>{o.push(1,4),o.push(t.length,10+2*(e>26)+2*(e>9));let r=0;for(;r/[0-9]/.test(t),(t,o)=>14+2*(o>26)+2*(o>9)+10*t/3),u=a(t=>(o,e)=>{o.push(2,4),o.push(t.length,9+2*(e>26)+2*(e>9));let r=0;for(;rs(t)>=0,(t,o)=>13+2*(o>26)+2*(o>9)+5.5*t),d=a(t=>l([...t].map(f)),t=>f(t)<128,(t,o)=>12+8*(o>9)+8*t);d._=!0,d.u=!0;const p=a(d,t=>f(t)<256,d.l,3);p._=!0;const m=new TextEncoder,h=a(t=>l(m.encode(t)),()=>1,0,26,(t,o)=>12+8*(o>9)+8*m.encode(t).length);h._=!0;let w=()=>{const t=new Map,o=new TextDecoder("sjis"),e=r(2);for(let r=0;r<7973;++r)e[0]=r/192+129+64*(r>5951),e[1]=r%192+64,t.set(o.decode(e),r);return t.delete("\ufffd"),w=()=>t,t};const y=a(t=>(o,e)=>{o.push(8,4),o.push(t.length,8+2*(e>26)+2*(e>9));for(const e of t)o.push(w().get(e),13)},t=>w().has(t),(t,o)=>12+2*(o>26)+2*(o>9)+13*t);y._=!0;const g=[_,u,d,p,y,h],b={auto:(t,{modes:o=g}={})=>(e,r)=>{const s=o.map((o,e)=>{const n=new Map,s=(t,o)=>(n.has(t)||n.set(t,o(t,r)),n.get(t));return{m:o,h:1<s(e-t,o.l):(e,r)=>s(t.slice(e,r),o.est)}});let f=[{v:0}],c=0,i=0,l=-1;for(const o of[...t,""]){let t=0;if(o)for(const e of s)e.m.test(o)&&(t|=e.h);if(!o||t!==l){if(-1!==l){const t=new Set(f.map(t=>t.D)),o=[];for(const{m:e,C:r,S:n,h:a}of s)if(l&a){const s=n(c,i);for(const l of e.eci??t)if(!e.u||!l){let t;for(const o of f)if(o.D===l||e.eci){const f=o.m===e&&o.D===l,a=f?o.V:o,_=e._&&f?o.v+s-r:a.v+12*(a.D!==l)+(f?n(f?o.$:c,i):s);(!t||_o.vt(e,r))},multi:c,eci:i,bytes:l,numeric:_,alphaNumeric:u,ascii:d,iso8859_1:p,shift_jis:y,utf8:h},C=()=>({F:r(2956),I:0,push(t,o){for(let e=o,r=8-(7&this.I);e>0;e-=r,r=8)this.F[this.I>>3]|=t<>e,this.I+=e({size:t,K:e,get:(o,r)=>o>=0&&o1&(t^o),(t,o)=>1&o,t=>t%3,(t,o)=>(t+o)%3,(t,o)=>1&(t/3^o>>1),(t,o)=>(t&o&1)+t*o%3,(t,o)=>(t&o)+t*o%3&1,(t,o)=>(t^o)+t*o%3&1],E=r(511);for(let t=0,o=1;t<255;o=2*o^285*(o>127))E[E[o+255]=t++]=o;const M=t=>E[t%255],S=t=>E[t+255],v=(t,o)=>{const e=r(t.length+o.length-1);for(let r=0;r{const e=r(t.length+o.length-1);e.set(t,0);for(let r=0;r{const e=[[],[]];let n=0,s=0;for(const[r,f]of o.o)for(let c=0;c{let r=t<<=e;for(let t=134217728;t>>=1;)r&t&&(r^=o*(t>>e));return r|t},A=({size:t,K:o},e)=>{const r=(e,r,n,s)=>{for(;n-- >0;e+=t)o.fill(s,e,e+r)},n=(o,e,n)=>{for(let s=0;s++<3;n-=2)r(e*t+o-(n>>1)*(t+1),n,n,2|s)},s=2*((t-13)/(1+(e/7|0))/2+.75|0);if(e>1)for(let o=t-7;o>8;o-=s){for(let t=o;t>8;t-=s)n(o,t,5);o6)for(let r=$(e,7973,12),n=1;n<7;++n)for(let e=12;e-- >9;r>>=1)o[n*t-e]=2|1&r;r(7,2,9,2),r(t-8,8,9,2);for(let e=0;e{const e=[];for(let r=t-2,n=t,s=-1;r>=0;r-=2){for(5===r&&(r=4);n+=s,-1!==n&&n!==t;){const s=n*t+r;o[s+1]||e.push(s+1),o[s]||e.push(s)}s*=-1}return e},H=({K:t},o,e)=>o.forEach((o,r)=>t[o]=e[r>>3]>>(7&~r)&1),I=({size:t,K:o},e,r,n)=>{for(let r=0;r>=1)o[(e-(e<7))*t+8]=1&s,o[9*t-e]=1&s;for(let e=8;--e,s;s>>=1)o[8*t+e-(e<7)]=1&s,o[(t-e)*t+8]=1&s},K=({size:t,K:o},e=0,r=0)=>{for(let n=0;n>1|2098176)&(3047517^a-1),2049&i&&(e+=40),a!==f&&(l=0),f=a,e+=5===++l?3:l>5}if(n)for(let r=t+n,s=5*o[n-1]^o[n];r{r>3);if(8*f(e).t=e;--t){const o=f(t);if(8*o.t{const n=x(e.size,e.K);return I(n,o,c??r,t),n.s=K(n),n}).reduce((t,o)=>o.s(o,e)=>P(o,{modes:[...g,...t],...e});export{e as correction,P as generate,b as mode}; diff --git a/websites/packages/leeoniya-ufuzzy/.gitignore b/packages/leeoniya-ufuzzy/.gitignore similarity index 100% rename from websites/packages/leeoniya-ufuzzy/.gitignore rename to packages/leeoniya-ufuzzy/.gitignore diff --git a/websites/packages/leeoniya-ufuzzy/1.0.19/dist/uFuzzy.d.ts b/packages/leeoniya-ufuzzy/1.0.19/dist/uFuzzy.d.ts similarity index 100% rename from websites/packages/leeoniya-ufuzzy/1.0.19/dist/uFuzzy.d.ts rename to packages/leeoniya-ufuzzy/1.0.19/dist/uFuzzy.d.ts diff --git a/websites/packages/leeoniya-ufuzzy/1.0.19/dist/uFuzzy.mjs b/packages/leeoniya-ufuzzy/1.0.19/dist/uFuzzy.mjs similarity index 100% rename from websites/packages/leeoniya-ufuzzy/1.0.19/dist/uFuzzy.mjs rename to packages/leeoniya-ufuzzy/1.0.19/dist/uFuzzy.mjs diff --git a/websites/packages/lightweight-charts/.gitignore b/packages/lightweight-charts/.gitignore similarity index 100% rename from websites/packages/lightweight-charts/.gitignore rename to packages/lightweight-charts/.gitignore diff --git a/websites/packages/lightweight-charts/5.0.8/dist/lightweight-charts.standalone.production.mjs b/packages/lightweight-charts/5.0.8/dist/lightweight-charts.standalone.production.mjs similarity index 100% rename from websites/packages/lightweight-charts/5.0.8/dist/lightweight-charts.standalone.production.mjs rename to packages/lightweight-charts/5.0.8/dist/lightweight-charts.standalone.production.mjs diff --git a/websites/packages/lightweight-charts/5.0.8/dist/typings.d.ts b/packages/lightweight-charts/5.0.8/dist/typings.d.ts similarity index 100% rename from websites/packages/lightweight-charts/5.0.8/dist/typings.d.ts rename to packages/lightweight-charts/5.0.8/dist/typings.d.ts diff --git a/websites/packages/lightweight-charts/NOTICE.md b/packages/lightweight-charts/NOTICE.md similarity index 100% rename from websites/packages/lightweight-charts/NOTICE.md rename to packages/lightweight-charts/NOTICE.md diff --git a/websites/packages/modern-screenshot/4.6.6/.gitignore b/packages/modern-screenshot/4.6.6/.gitignore similarity index 100% rename from websites/packages/modern-screenshot/4.6.6/.gitignore rename to packages/modern-screenshot/4.6.6/.gitignore diff --git a/websites/packages/modern-screenshot/4.6.6/dist/index.d.ts b/packages/modern-screenshot/4.6.6/dist/index.d.ts similarity index 100% rename from websites/packages/modern-screenshot/4.6.6/dist/index.d.ts rename to packages/modern-screenshot/4.6.6/dist/index.d.ts diff --git a/websites/packages/modern-screenshot/4.6.6/dist/index.mjs b/packages/modern-screenshot/4.6.6/dist/index.mjs similarity index 100% rename from websites/packages/modern-screenshot/4.6.6/dist/index.mjs rename to packages/modern-screenshot/4.6.6/dist/index.mjs diff --git a/websites/packages/modern-screenshot/index.js b/packages/modern-screenshot/index.js similarity index 100% rename from websites/packages/modern-screenshot/index.js rename to packages/modern-screenshot/index.js diff --git a/websites/packages/solidjs-signals/0.4.11/dist/prod.js b/packages/solidjs-signals/0.4.11/dist/prod.js similarity index 100% rename from websites/packages/solidjs-signals/0.4.11/dist/prod.js rename to packages/solidjs-signals/0.4.11/dist/prod.js diff --git a/websites/packages/solidjs-signals/0.4.11/dist/types/boundaries.d.ts b/packages/solidjs-signals/0.4.11/dist/types/boundaries.d.ts similarity index 100% rename from websites/packages/solidjs-signals/0.4.11/dist/types/boundaries.d.ts rename to packages/solidjs-signals/0.4.11/dist/types/boundaries.d.ts diff --git a/websites/packages/solidjs-signals/0.4.11/dist/types/core/constants.d.ts b/packages/solidjs-signals/0.4.11/dist/types/core/constants.d.ts similarity index 100% rename from websites/packages/solidjs-signals/0.4.11/dist/types/core/constants.d.ts rename to packages/solidjs-signals/0.4.11/dist/types/core/constants.d.ts diff --git a/websites/packages/solidjs-signals/0.4.11/dist/types/core/core.d.ts b/packages/solidjs-signals/0.4.11/dist/types/core/core.d.ts similarity index 100% rename from websites/packages/solidjs-signals/0.4.11/dist/types/core/core.d.ts rename to packages/solidjs-signals/0.4.11/dist/types/core/core.d.ts diff --git a/websites/packages/solidjs-signals/0.4.11/dist/types/core/effect.d.ts b/packages/solidjs-signals/0.4.11/dist/types/core/effect.d.ts similarity index 100% rename from websites/packages/solidjs-signals/0.4.11/dist/types/core/effect.d.ts rename to packages/solidjs-signals/0.4.11/dist/types/core/effect.d.ts diff --git a/websites/packages/solidjs-signals/0.4.11/dist/types/core/error.d.ts b/packages/solidjs-signals/0.4.11/dist/types/core/error.d.ts similarity index 100% rename from websites/packages/solidjs-signals/0.4.11/dist/types/core/error.d.ts rename to packages/solidjs-signals/0.4.11/dist/types/core/error.d.ts diff --git a/websites/packages/solidjs-signals/0.4.11/dist/types/core/flags.d.ts b/packages/solidjs-signals/0.4.11/dist/types/core/flags.d.ts similarity index 100% rename from websites/packages/solidjs-signals/0.4.11/dist/types/core/flags.d.ts rename to packages/solidjs-signals/0.4.11/dist/types/core/flags.d.ts diff --git a/websites/packages/solidjs-signals/0.4.11/dist/types/core/index.d.ts b/packages/solidjs-signals/0.4.11/dist/types/core/index.d.ts similarity index 100% rename from websites/packages/solidjs-signals/0.4.11/dist/types/core/index.d.ts rename to packages/solidjs-signals/0.4.11/dist/types/core/index.d.ts diff --git a/websites/packages/solidjs-signals/0.4.11/dist/types/core/owner.d.ts b/packages/solidjs-signals/0.4.11/dist/types/core/owner.d.ts similarity index 100% rename from websites/packages/solidjs-signals/0.4.11/dist/types/core/owner.d.ts rename to packages/solidjs-signals/0.4.11/dist/types/core/owner.d.ts diff --git a/websites/packages/solidjs-signals/0.4.11/dist/types/core/scheduler.d.ts b/packages/solidjs-signals/0.4.11/dist/types/core/scheduler.d.ts similarity index 100% rename from websites/packages/solidjs-signals/0.4.11/dist/types/core/scheduler.d.ts rename to packages/solidjs-signals/0.4.11/dist/types/core/scheduler.d.ts diff --git a/websites/packages/solidjs-signals/0.4.11/dist/types/index.d.ts b/packages/solidjs-signals/0.4.11/dist/types/index.d.ts similarity index 100% rename from websites/packages/solidjs-signals/0.4.11/dist/types/index.d.ts rename to packages/solidjs-signals/0.4.11/dist/types/index.d.ts diff --git a/websites/packages/solidjs-signals/0.4.11/dist/types/map.d.ts b/packages/solidjs-signals/0.4.11/dist/types/map.d.ts similarity index 100% rename from websites/packages/solidjs-signals/0.4.11/dist/types/map.d.ts rename to packages/solidjs-signals/0.4.11/dist/types/map.d.ts diff --git a/websites/packages/solidjs-signals/0.4.11/dist/types/signals.d.ts b/packages/solidjs-signals/0.4.11/dist/types/signals.d.ts similarity index 100% rename from websites/packages/solidjs-signals/0.4.11/dist/types/signals.d.ts rename to packages/solidjs-signals/0.4.11/dist/types/signals.d.ts diff --git a/websites/packages/solidjs-signals/0.4.11/dist/types/store/index.d.ts b/packages/solidjs-signals/0.4.11/dist/types/store/index.d.ts similarity index 100% rename from websites/packages/solidjs-signals/0.4.11/dist/types/store/index.d.ts rename to packages/solidjs-signals/0.4.11/dist/types/store/index.d.ts diff --git a/websites/packages/solidjs-signals/0.4.11/dist/types/store/projection.d.ts b/packages/solidjs-signals/0.4.11/dist/types/store/projection.d.ts similarity index 100% rename from websites/packages/solidjs-signals/0.4.11/dist/types/store/projection.d.ts rename to packages/solidjs-signals/0.4.11/dist/types/store/projection.d.ts diff --git a/websites/packages/solidjs-signals/0.4.11/dist/types/store/reconcile.d.ts b/packages/solidjs-signals/0.4.11/dist/types/store/reconcile.d.ts similarity index 100% rename from websites/packages/solidjs-signals/0.4.11/dist/types/store/reconcile.d.ts rename to packages/solidjs-signals/0.4.11/dist/types/store/reconcile.d.ts diff --git a/websites/packages/solidjs-signals/0.4.11/dist/types/store/store.d.ts b/packages/solidjs-signals/0.4.11/dist/types/store/store.d.ts similarity index 100% rename from websites/packages/solidjs-signals/0.4.11/dist/types/store/store.d.ts rename to packages/solidjs-signals/0.4.11/dist/types/store/store.d.ts diff --git a/websites/packages/solidjs-signals/0.4.11/dist/types/store/utils.d.ts b/packages/solidjs-signals/0.4.11/dist/types/store/utils.d.ts similarity index 100% rename from websites/packages/solidjs-signals/0.4.11/dist/types/store/utils.d.ts rename to packages/solidjs-signals/0.4.11/dist/types/store/utils.d.ts diff --git a/packages/solidjs-signals/0.6.3/dist/prod.js b/packages/solidjs-signals/0.6.3/dist/prod.js new file mode 100644 index 000000000..cad891f7a --- /dev/null +++ b/packages/solidjs-signals/0.6.3/dist/prod.js @@ -0,0 +1,2438 @@ +// src/core/error.ts +var NotReadyError = class extends Error { +}; +var NoOwnerError = class extends Error { + constructor() { + super(""); + } +}; +var ContextNotFoundError = class extends Error { + constructor() { + super( + "" + ); + } +}; + +// src/core/constants.ts +var STATE_CLEAN = 0; +var STATE_CHECK = 1; +var STATE_DIRTY = 2; +var STATE_DISPOSED = 3; +var EFFECT_PURE = 0; +var EFFECT_RENDER = 1; +var EFFECT_USER = 2; +var SUPPORTS_PROXY = typeof Proxy === "function"; + +// src/core/flags.ts +var ERROR_OFFSET = 0; +var ERROR_BIT = 1 << ERROR_OFFSET; +var LOADING_OFFSET = 1; +var LOADING_BIT = 1 << LOADING_OFFSET; +var UNINITIALIZED_OFFSET = 2; +var UNINITIALIZED_BIT = 1 << UNINITIALIZED_OFFSET; +var DEFAULT_FLAGS = ERROR_BIT; + +// src/core/scheduler.ts +var clock = 0; +function incrementClock() { + clock++; +} +var ActiveTransition = null; +var Unobserved = []; +var scheduled = false; +function schedule() { + if (scheduled) + return; + scheduled = true; + if (!globalQueue.A) + queueMicrotask(flush); +} +function notifyUnobserved() { + for (let i = 0; i < Unobserved.length; i++) { + const source = Unobserved[i]; + if (!source.b || !source.b.length) + Unobserved[i].ea?.(); + } + Unobserved = []; +} +var pureQueue = []; +var Queue = class { + k = null; + A = false; + g = [[], []]; + f = []; + created = clock; + enqueue(type, fn) { + pureQueue.push(fn); + if (type) + this.g[type - 1].push(fn); + schedule(); + } + run(type) { + if (type === EFFECT_PURE) { + pureQueue.length && runQueue(pureQueue, type); + pureQueue = []; + return; + } else if (this.g[type - 1].length) { + const effects = this.g[type - 1]; + this.g[type - 1] = []; + runQueue(effects, type); + } + for (let i = 0; i < this.f.length; i++) { + this.f[i].run(type); + } + } + flush() { + if (this.A) + return; + this.A = true; + try { + this.run(EFFECT_PURE); + incrementClock(); + scheduled = false; + this.run(EFFECT_RENDER); + this.run(EFFECT_USER); + } finally { + this.A = false; + Unobserved.length && notifyUnobserved(); + } + } + addChild(child) { + if (ActiveTransition && ActiveTransition.r.has(this)) + return ActiveTransition.r.get(this).addChild(child); + this.f.push(child); + child.k = this; + } + removeChild(child) { + if (ActiveTransition && ActiveTransition.r.has(this)) + return ActiveTransition.r.get(this).removeChild(child); + const index = this.f.indexOf(child); + if (index >= 0) { + this.f.splice(index, 1); + child.k = null; + } + } + notify(...args) { + if (this.k) + return this.k.notify(...args); + return false; + } + merge(queue) { + this.g[0].push.apply(this.g[0], queue.g[0]); + this.g[1].push.apply(this.g[1], queue.g[1]); + for (let i = 0; i < queue.f.length; i++) { + const og = this.f.find((c) => c.e === queue.f[i].e); + if (og) + og.merge(queue.f[i]); + else + this.addChild(queue.f[i]); + } + } +}; +var globalQueue = new Queue(); +function flush() { + while (scheduled) { + globalQueue.flush(); + } +} +function removeSourceObservers(node, index) { + let source; + let swap; + for (let i = index; i < node.a.length; i++) { + source = getTransitionSource(node.a[i]); + if (source.b) { + if ((swap = source.b.indexOf(node)) !== -1) { + source.b[swap] = source.b[source.b.length - 1]; + source.b.pop(); + } + if (!source.b.length) + Unobserved.push(source); + } + } +} +function runQueue(queue, type) { + for (let i = 0; i < queue.length; i++) + queue[i](type); +} +var Transition = class _Transition { + a = /* @__PURE__ */ new Map(); + s = /* @__PURE__ */ new Set(); + H = /* @__PURE__ */ new Set(); + W = /* @__PURE__ */ new Set(); + u = false; + g = [[], []]; + r = /* @__PURE__ */ new Map(); + I = []; + f = []; + k = null; + A = false; + X = false; + e = globalQueue; + created = clock; + constructor() { + this.r.set(globalQueue, this); + for (const child of globalQueue.f) { + cloneQueue(child, this, this.r); + } + } + enqueue(type, fn) { + this.I.push(fn); + if (type) + this.g[type - 1].push(fn); + this.schedule(); + } + run(type) { + if (type === EFFECT_PURE) { + this.I.length && runQueue(this.I, type); + this.I = []; + return; + } else if (this.g[type - 1].length) { + const effects = this.g[type - 1]; + this.g[type - 1] = []; + runQueue(effects, type); + } + for (let i = 0; i < this.f.length; i++) { + this.f[i].run(type); + } + } + flush() { + if (this.A) + return; + this.A = true; + let currentTransition = ActiveTransition; + ActiveTransition = this; + try { + this.run(EFFECT_PURE); + incrementClock(); + this.X = false; + ActiveTransition = currentTransition; + finishTransition(this); + } finally { + this.A = false; + ActiveTransition = currentTransition; + } + } + addChild(child) { + this.f.push(child); + child.k = this; + } + removeChild(child) { + const index = this.f.indexOf(child); + if (index >= 0) + this.f.splice(index, 1); + } + notify(node, type, flags) { + if (!(type & LOADING_BIT)) + return false; + if (flags & LOADING_BIT) { + this.s.add(node); + } else { + this.s.delete(node); + } + return true; + } + merge(queue) { + this.g[0].push.apply(this.g[0], queue.g[0]); + this.g[1].push.apply(this.g[1], queue.g[1]); + this.I.push.apply(this.I, queue.I); + for (let i = 0; i < queue.f.length; i++) { + const og = this.f.find((c) => c.e === queue.f[i].e); + if (og) + og.merge(queue.f[i]); + else + this.addChild(queue.f[i]); + } + } + schedule() { + if (this.X) + return; + this.X = true; + if (!this.A) + queueMicrotask(() => this.flush()); + } + runTransition(fn, force = false) { + if (this.u) { + if (this.u instanceof _Transition) + return this.u.runTransition(fn, force); + if (!force) + throw new Error("Transition already completed"); + fn(); + return; + } + ActiveTransition = this; + try { + let result = fn(); + let transition2 = ActiveTransition; + if (result?.next) { + (async function() { + let temp, value; + while (!(temp = result.next(value)).done) { + if (temp.value instanceof Promise) { + transition2.H.add(temp.value); + try { + value = await temp.value; + } finally { + while (transition2.u instanceof _Transition) + transition2 = transition2.u; + transition2.H.delete(temp.value); + } + ActiveTransition = transition2; + } else + value = temp.value; + } + ActiveTransition = null; + finishTransition(transition2); + })(); + } + if (result instanceof Promise) { + transition2.H.add(result); + result.finally(() => { + while (transition2.u instanceof _Transition) + transition2 = transition2.u; + transition2.H.delete(result); + ActiveTransition = null; + finishTransition(transition2); + }); + } + } finally { + const transition2 = ActiveTransition; + ActiveTransition = null; + finishTransition(transition2); + } + } + addOptimistic(fn) { + if (fn.j && fn.j !== this) { + mergeTransitions(fn.j, this); + ActiveTransition = fn.j; + return; + } + fn.j = this; + this.W.add(fn); + } +}; +function transition(fn) { + let t = new Transition(); + queueMicrotask(() => t.runTransition(() => fn((fn2) => t.runTransition(fn2)))); +} +function cloneGraph(node) { + if (node.j) { + if (node.j !== ActiveTransition) { + mergeTransitions(node.j, ActiveTransition); + ActiveTransition = node.j; + } + return node.j.a.get(node); + } + const clone = Object.create(Object.getPrototypeOf(node)); + Object.assign(clone, node, { + n: null, + m: null, + b: null, + a: node.a ? [...node.a] : null, + e: node + }); + ActiveTransition.a.set(node, clone); + node.j = ActiveTransition; + if (node.a) { + for (let i = 0; i < node.a.length; i++) + node.a[i].b.push(clone); + } + if (node.b) { + clone.b = []; + for (let i = 0, length = node.b.length; i < length; i++) { + !node.b[i].e && clone.b.push(cloneGraph(node.b[i])); + } + } + return clone; +} +function replaceSourceObservers(node, transition2) { + let source; + let swap; + for (let i = 0; i < node.a.length; i++) { + source = transition2.a.get(node.a[i]) || node.a[i]; + if (source.b && (swap = source.b.indexOf(node)) !== -1) { + const remove = source.b.indexOf(node.e) > -1; + source.b[swap] = !remove ? node.e : source.b[source.b.length - 1]; + remove && source.b.pop(); + } + } +} +function cloneQueue(queue, parent, clonedQueues) { + const clone = Object.create(Object.getPrototypeOf(queue)); + Object.assign(clone, queue, { + e: queue, + k: parent, + f: [], + enqueue(type, fn) { + ActiveTransition?.enqueue(type, fn); + }, + notify(node, type, flags) { + node = node.e || node; + if (!clone.J || type & LOADING_BIT) { + type &= ~LOADING_BIT; + ActiveTransition?.notify(node, LOADING_BIT, flags); + if (!type) + return true; + } + return queue.notify.call(this, node, type, flags); + } + }); + parent.f.push(clone); + clonedQueues.set(queue, clone); + for (const child of queue.f) { + cloneQueue(child, clone, clonedQueues); + } +} +function resolveQueues(children) { + for (const child of children) { + const og = child.e; + if (og) { + const clonedChildren = child.f; + delete child.enqueue; + delete child.notify; + delete child.k; + delete child.f; + Object.assign(og, child); + delete og.e; + resolveQueues(clonedChildren); + } else if (child.k.e) { + child.k.e.addChild(child); + } + } +} +function mergeTransitions(t1, t2) { + t2.a.forEach((value, key) => { + key.j = t1; + t1.a.set(key, value); + }); + t2.W.forEach((c) => { + c.j = t1; + t1.W.add(c); + }); + t2.H.forEach((p) => t1.H.add(p)); + t2.s.forEach((n) => t1.s.add(n)); + t1.merge(t2); + t2.u = t1; +} +function getTransitionSource(input) { + return ActiveTransition && ActiveTransition.a.get(input) || input; +} +function getQueue(node) { + const transition2 = ActiveTransition || node.e?.j; + return transition2 && transition2.r.get(node.B) || node.B; +} +function initialDispose(node) { + let current = node.m; + while (current !== null && current.k === node) { + initialDispose(current); + const clone = ActiveTransition.a.get(current); + if (clone && !clone.Y) + clone.dispose(true); + current = current.m; + } +} +function finishTransition(transition2) { + if (transition2.u || transition2.X || transition2.H.size || transition2.s.size) + return; + globalQueue.g[0].push.apply(globalQueue.g[0], transition2.g[0]); + globalQueue.g[1].push.apply(globalQueue.g[1], transition2.g[1]); + resolveQueues(transition2.f); + for (const [source, clone] of transition2.a) { + if (source === clone || source.j !== transition2) { + delete source.j; + continue; + } + if (clone.a) + replaceSourceObservers(clone, transition2); + if (clone.Y || clone.c === STATE_DISPOSED) { + source.dispose(clone.c === STATE_DISPOSED); + source.emptyDisposal(); + delete clone.Y; + } else { + delete clone.m; + delete clone.n; + } + Object.assign(source, clone); + delete source.e; + let current = clone.m; + if (current?.w === clone) + current.w = source; + while (current?.k === clone) { + current.k = source; + current = current.m; + } + delete source.j; + } + transition2.u = true; + for (const reset of transition2.W) { + delete reset.j; + reset(); + } + globalQueue.flush(); +} + +// src/core/owner.ts +var currentOwner = null; +var defaultContext = {}; +function getOwner() { + return currentOwner; +} +function setOwner(owner) { + const out = currentOwner; + currentOwner = owner; + return out; +} +var Owner = class { + // We flatten the owner tree into a linked list so that we don't need a pointer to .firstChild + // However, the children are actually added in reverse creation order + // See comment at the top of the file for an example of the _nextSibling traversal + k = null; + m = null; + w = null; + c = STATE_CLEAN; + n = null; + x = defaultContext; + B = globalQueue; + fa = 0; + id = null; + constructor(id = null, skipAppend = false) { + this.id = id; + if (currentOwner) { + !skipAppend && currentOwner.append(this); + } + } + append(child) { + child.k = this; + child.w = this; + if (this.m) + this.m.w = child; + child.m = this.m; + this.m = child; + if (this.id != null && child.id == null) + child.id = this.getNextChildId(); + if (child.x !== this.x) { + child.x = { ...this.x, ...child.x }; + } + if (this.B) + child.B = this.B; + } + dispose(self = true) { + if (this.c === STATE_DISPOSED) + return; + let head = self ? this.w || this.k : this, current = this.m, next = null; + while (current && current.k === this) { + current.dispose(true); + next = current.m; + current.m = null; + current = next; + } + this.fa = 0; + if (self) + this.R(); + if (current) + current.w = !self ? this : this.w; + if (head) + head.m = current; + } + R() { + if (this.w) + this.w.m = null; + this.k = null; + this.w = null; + this.x = defaultContext; + this.c = STATE_DISPOSED; + this.emptyDisposal(); + } + emptyDisposal() { + if (!this.n) + return; + if (Array.isArray(this.n)) { + for (let i = 0; i < this.n.length; i++) { + const callable = this.n[i]; + callable.call(callable); + } + } else { + this.n.call(this.n); + } + this.n = null; + } + getNextChildId() { + if (this.id != null) + return formatId(this.id, this.fa++); + throw new Error("Cannot get child id from owner without an id"); + } +}; +function createContext(defaultValue, description) { + return { id: Symbol(description), defaultValue }; +} +function getContext(context, owner = currentOwner) { + if (!owner) { + throw new NoOwnerError(); + } + const value = hasContext(context, owner) ? owner.x[context.id] : context.defaultValue; + if (isUndefined(value)) { + throw new ContextNotFoundError(); + } + return value; +} +function setContext(context, value, owner = currentOwner) { + if (!owner) { + throw new NoOwnerError(); + } + owner.x = { + ...owner.x, + [context.id]: isUndefined(value) ? context.defaultValue : value + }; +} +function hasContext(context, owner = currentOwner) { + return !isUndefined(owner?.x[context.id]); +} +function onCleanup(fn) { + if (!currentOwner) + return fn; + const node = currentOwner; + if (!node.n) { + node.n = fn; + } else if (Array.isArray(node.n)) { + node.n.push(fn); + } else { + node.n = [node.n, fn]; + } + return fn; +} +function formatId(prefix, id) { + const num = id.toString(36), len = num.length - 1; + return prefix + (len ? String.fromCharCode(64 + len) : "") + num; +} +function isUndefined(value) { + return typeof value === "undefined"; +} + +// src/core/core.ts +var currentObserver = null; +var currentMask = DEFAULT_FLAGS; +var newSources = null; +var newSourcesIndex = 0; +var newFlags = 0; +var notStale = false; +var updateCheck = null; +var staleCheck = null; +function getObserver() { + return currentObserver; +} +var UNCHANGED = Symbol(0); +var Computation = class extends Owner { + a = null; + b = null; + l; + L; + M; + // Used in __DEV__ mode, hopefully removed in production + la; + // Using false is an optimization as an alternative to _equals: () => false + // which could enable more efficient DIRTY notification + aa = isEqual; + ea; + ha = false; + /** Whether the computation is an error or has ancestors that are unresolved */ + h = 0; + /** Which flags raised by sources are handled, vs. being passed through. */ + ba = DEFAULT_FLAGS; + N = -1; + D = false; + j; + e; + constructor(initialValue, compute2, options) { + super(options?.id, compute2 === null); + this.M = compute2; + this.c = compute2 ? STATE_DIRTY : STATE_CLEAN; + this.h = compute2 && initialValue === void 0 ? UNINITIALIZED_BIT : 0; + this.l = initialValue; + if (options?.equals !== void 0) + this.aa = options.equals; + if (options?.pureWrite) + this.ha = true; + if (options?.unobserved) + this.ea = options?.unobserved; + if (ActiveTransition) { + this.j = ActiveTransition; + ActiveTransition.a.set(this, this); + } + } + ga() { + track(this); + newFlags |= this.h & ~currentMask; + if (this.h & ERROR_BIT) { + throw this.L; + } else { + return this.l; + } + } + /** + * Return the current value of this computation + * Automatically re-executes the surrounding computation when the value changes + */ + read() { + if (ActiveTransition && (ActiveTransition.a.has(this) || !this.e && this.h & (UNINITIALIZED_BIT | ERROR_BIT))) { + const clone = ActiveTransition.a.get(this) || cloneGraph(this); + if (clone !== this) + return clone.read(); + } + if (this.M) { + if (this.h & ERROR_BIT && this.N <= clock) + update(this); + else + this.K(); + } + return this.ga(); + } + /** + * Return the current value of this computation + * Automatically re-executes the surrounding computation when the value changes + * + * If the computation has any unresolved ancestors, this function waits for the value to resolve + * before continuing + */ + wait() { + if (ActiveTransition && (ActiveTransition.a.has(this) || !this.e && this.h & (UNINITIALIZED_BIT | ERROR_BIT))) { + const clone = ActiveTransition.a.get(this) || cloneGraph(this); + if (clone !== this) + return clone.wait(); + } + if (this.M) { + if (this.h & ERROR_BIT && this.N <= clock) + update(this); + else + this.K(); + } + if ((notStale || this.h & UNINITIALIZED_BIT) && this.h & LOADING_BIT) { + track(this); + throw new NotReadyError(); + } + if (staleCheck && this.h & LOADING_BIT) { + staleCheck.l = true; + } + return this.ga(); + } + /** Update the computation with a new value. */ + write(value, flags = 0, raw = false) { + if (ActiveTransition && !this.e) { + const clone = cloneGraph(this); + if (clone !== this) + return clone.write(value, flags, raw); + } + const newValue = !raw && typeof value === "function" ? value(this.l) : value; + const valueChanged = newValue !== UNCHANGED && (!!(this.h & UNINITIALIZED_BIT) || // this._stateFlags & LOADING_BIT & ~flags || + this.aa === false || !this.aa(this.l, newValue)); + if (valueChanged) { + this.l = newValue; + this.L = void 0; + } + const changedFlagsMask = this.h ^ flags, changedFlags = changedFlagsMask & flags; + this.h = flags; + this.N = clock + 1; + if (this.b) { + for (let i = 0; i < this.b.length; i++) { + if (valueChanged) { + this.b[i].y(STATE_DIRTY); + } else if (changedFlagsMask) { + this.b[i].Z(changedFlagsMask, changedFlags); + } + } + } + return this.l; + } + /** + * Set the current node's state, and recursively mark all of this node's observers as STATE_CHECK + */ + y(state, skipQueue) { + if (this.c >= state && !this.D) + return; + this.D = !!skipQueue; + this.c = state; + if (this.b) { + for (let i = 0; i < this.b.length; i++) { + this.b[i].y(STATE_CHECK, skipQueue); + } + } + } + /** + * Notify the computation that one of its sources has changed flags. + * + * @param mask A bitmask for which flag(s) were changed. + * @param newFlags The source's new flags, masked to just the changed ones. + */ + Z(mask, newFlags2) { + if (this.c >= STATE_DIRTY) + return; + if (mask & this.ba) { + this.y(STATE_DIRTY); + return; + } + if (this.c >= STATE_CHECK && !this.D) + return; + const prevFlags = this.h & mask; + const deltaFlags = prevFlags ^ newFlags2; + if (newFlags2 === prevFlags) ; else if (deltaFlags & prevFlags & mask) { + this.y(STATE_CHECK); + } else { + this.h ^= deltaFlags; + if (this.b) { + for (let i = 0; i < this.b.length; i++) { + this.b[i].Z(mask, newFlags2); + } + } + } + } + E(error) { + if (ActiveTransition && !this.e) { + const clone = cloneGraph(this); + if (clone !== this) + return clone.E(error); + } + this.L = error; + this.write(UNCHANGED, this.h & ~LOADING_BIT | ERROR_BIT | UNINITIALIZED_BIT); + } + /** + * This is the core part of the reactivity system, which makes sure that the values are updated + * before they are read. We've also adapted it to return the loading state of the computation, + * so that we can propagate that to the computation's observers. + * + * This function will ensure that the value and states we read from the computation are up to date + */ + K() { + if (!this.M) { + return; + } + if (this.c === STATE_DISPOSED) { + return; + } + if (this.c === STATE_CLEAN) { + return; + } + let observerFlags = 0; + if (this.c === STATE_CHECK) { + for (let i = 0; i < this.a.length; i++) { + const source = getTransitionSource(this.a[i]); + source.K(); + observerFlags |= source.h & ~UNINITIALIZED_BIT; + if (this.c === STATE_DIRTY) { + break; + } + } + } + if (this.c === STATE_DIRTY) { + update(this); + } else { + this.write(UNCHANGED, observerFlags); + this.c = STATE_CLEAN; + } + } + /** + * Remove ourselves from the owner graph and the computation graph + */ + R() { + if (this.c === STATE_DISPOSED) + return; + if (this.a) + removeSourceObservers(this, 0); + super.R(); + } +}; +function track(computation) { + if (ActiveTransition && computation.e) + computation = computation.e; + if (currentObserver) { + if (!newSources && currentObserver.a && currentObserver.a[newSourcesIndex] === computation) { + newSourcesIndex++; + } else if (!newSources) + newSources = [computation]; + else if (computation !== newSources[newSources.length - 1]) { + newSources.push(computation); + } + if (updateCheck) { + updateCheck.l = computation.N > currentObserver.N; + } + } +} +function update(node) { + const prevSources = newSources, prevSourcesIndex = newSourcesIndex, prevFlags = newFlags; + newSources = null; + newSourcesIndex = 0; + newFlags = 0; + try { + if (ActiveTransition && node.e && !node.Y) { + initialDispose(node.e); + node.Y = true; + } + node.dispose(false); + node.emptyDisposal(); + const result = compute(node, node.M, node); + node.write(result, newFlags, true); + } catch (error) { + if (error instanceof NotReadyError) { + node.write(UNCHANGED, newFlags | LOADING_BIT | node.h & UNINITIALIZED_BIT); + } else { + node.E(error); + } + } finally { + if (newSources) { + if (node.a) + removeSourceObservers(node, newSourcesIndex); + if (node.a && newSourcesIndex > 0) { + node.a.length = newSourcesIndex + newSources.length; + for (let i = 0; i < newSources.length; i++) { + node.a[newSourcesIndex + i] = newSources[i]; + } + } else { + node.a = newSources; + } + let source; + for (let i = newSourcesIndex; i < node.a.length; i++) { + source = getTransitionSource(node.a[i]); + if (!source.b) + source.b = [node]; + else + source.b.push(node); + } + } else if (node.a && newSourcesIndex < node.a.length) { + removeSourceObservers(node, newSourcesIndex); + node.a.length = newSourcesIndex; + } + newSources = prevSources; + newSourcesIndex = prevSourcesIndex; + newFlags = prevFlags; + node.N = clock + 1; + node.c = STATE_CLEAN; + } +} +function isEqual(a, b) { + return a === b; +} +function untrack(fn) { + if (currentObserver === null) + return fn(); + return compute(getOwner(), fn, null); +} +function hasUpdated(fn) { + const current = updateCheck; + updateCheck = { l: false }; + try { + fn(); + return updateCheck.l; + } finally { + updateCheck = current; + } +} +function pendingCheck(fn, loadingValue) { + const current = staleCheck; + staleCheck = { l: false }; + try { + latest(fn); + return staleCheck.l; + } catch (err) { + if (!(err instanceof NotReadyError)) + return false; + if (loadingValue !== void 0) + return loadingValue; + throw err; + } finally { + staleCheck = current; + } +} +function isPending(fn, loadingValue) { + if (!currentObserver) + return pendingCheck(fn, loadingValue); + const c = new Computation(void 0, () => pendingCheck(fn, loadingValue)); + c.ba |= LOADING_BIT; + return c.read(); +} +function latest(fn, fallback) { + const argLength = arguments.length; + const prevFlags = newFlags; + const prevNotStale = notStale; + notStale = false; + try { + return fn(); + } catch (err) { + if (argLength > 1 && err instanceof NotReadyError) + return fallback; + throw err; + } finally { + newFlags = prevFlags; + notStale = prevNotStale; + } +} +function runWithObserver(observer, run) { + const prevSources = newSources, prevSourcesIndex = newSourcesIndex, prevFlags = newFlags; + newSources = null; + newSourcesIndex = observer.a ? observer.a.length : 0; + newFlags = 0; + try { + return compute(observer, run, observer); + } catch (error) { + if (error instanceof NotReadyError) { + observer.write( + UNCHANGED, + newFlags | LOADING_BIT | observer.h & UNINITIALIZED_BIT + ); + } else { + observer.E(error); + } + } finally { + if (newSources) { + if (newSourcesIndex > 0) { + observer.a.length = newSourcesIndex + newSources.length; + for (let i = 0; i < newSources.length; i++) { + observer.a[newSourcesIndex + i] = newSources[i]; + } + } else { + observer.a = newSources; + } + let source; + for (let i = newSourcesIndex; i < observer.a.length; i++) { + source = observer.a[i]; + if (!source.b) + source.b = [observer]; + else + source.b.push(observer); + } + } + newSources = prevSources; + newSourcesIndex = prevSourcesIndex; + newFlags = prevFlags; + } +} +function compute(owner, fn, observer) { + const prevOwner = setOwner(owner), prevObserver = currentObserver, prevMask = currentMask, prevNotStale = notStale; + currentObserver = observer; + currentMask = observer?.ba ?? DEFAULT_FLAGS; + notStale = true; + try { + return fn.call(observer, observer ? observer.l : void 0); + } finally { + setOwner(prevOwner); + currentObserver = prevObserver; + currentMask = prevMask; + notStale = prevNotStale; + } +} + +// src/core/effect.ts +var Effect = class extends Computation { + ca; + _; + O; + da = false; + $; + C; + constructor(initialValue, compute2, effect, error, options) { + super(initialValue, compute2, options); + this.ca = effect; + this._ = error; + this.$ = initialValue; + this.C = options?.render ? EFFECT_RENDER : EFFECT_USER; + if (this.C === EFFECT_RENDER) { + this.M = function(p) { + return !this.e && clock > this.B.created && !(this.h & ERROR_BIT) ? latest(() => compute2(p)) : compute2(p); + }; + } + this.K(); + !options?.defer && (this.C === EFFECT_USER ? getQueue(this).enqueue(this.C, this.F.bind(this)) : this.F(this.C)); + } + write(value, flags = 0) { + if (this.c == STATE_DIRTY) { + this.h = flags; + if (this.C === EFFECT_RENDER) { + getQueue(this).notify(this, LOADING_BIT | ERROR_BIT, this.h); + } + } + if (value === UNCHANGED) + return this.l; + this.l = value; + this.da = true; + this.L = void 0; + return value; + } + y(state, skipQueue) { + if (this.c >= state || skipQueue) + return; + if (this.c === STATE_CLEAN) + getQueue(this).enqueue(this.C, this.F.bind(this)); + this.c = state; + } + Z(mask, newFlags2) { + if (this.e) { + if (this.c >= STATE_DIRTY) + return; + if (mask & 3) { + this.y(STATE_DIRTY); + return; + } + } + super.Z(mask, newFlags2); + } + E(error) { + this.L = error; + getQueue(this).notify(this, LOADING_BIT, 0); + this.h = ERROR_BIT; + if (this.C === EFFECT_USER) { + try { + return this._ ? this._(error, () => { + this.O?.(); + this.O = void 0; + }) : console.error(error); + } catch (e) { + error = e; + } + } + if (!getQueue(this).notify(this, ERROR_BIT, ERROR_BIT)) + throw error; + } + R() { + if (this.c === STATE_DISPOSED) + return; + this.ca = void 0; + this.$ = void 0; + this._ = void 0; + this.O?.(); + this.O = void 0; + getQueue(this).notify(this, ERROR_BIT | LOADING_BIT, 0); + super.R(); + } + F(type) { + if (type) { + const effect = this.e || this; + if (effect.da && effect.c !== STATE_DISPOSED) { + effect.O?.(); + try { + effect.O = effect.ca(effect.l, effect.$); + } catch (e) { + if (!getQueue(effect).notify(effect, ERROR_BIT, ERROR_BIT)) + throw e; + } finally { + effect.$ = effect.l; + effect.da = false; + } + } + } else + this.c !== STATE_CLEAN && runTop(this); + } +}; +var EagerComputation = class extends Computation { + constructor(initialValue, compute2, options) { + super(initialValue, compute2, options); + !options?.defer && this.K(); + } + y(state, skipQueue) { + if (this.c >= state && !this.D) + return; + if (!skipQueue && (this.c === STATE_CLEAN || this.c === STATE_CHECK && this.D)) + getQueue(this).enqueue(EFFECT_PURE, this.F.bind(this)); + super.y(state, skipQueue); + } + F() { + this.c !== STATE_CLEAN && runTop(this); + } +}; +var FirewallComputation = class extends Computation { + firewall = true; + constructor(compute2) { + super(void 0, compute2); + } + y(state, skipQueue) { + if (this.c >= state && !this.D) + return; + if (!skipQueue && (this.c === STATE_CLEAN || this.c === STATE_CHECK && this.D)) + getQueue(this).enqueue(EFFECT_PURE, this.F.bind(this)); + super.y(state, true); + this.D = !!skipQueue; + } + F() { + this.c !== STATE_CLEAN && runTop(this); + } +}; +function runTop(node) { + const ancestors = []; + for (let current = node; current !== null; current = current.k) { + if (ActiveTransition && current.j) + current = ActiveTransition.a.get(current); + if (current.c !== STATE_CLEAN) { + ancestors.push(current); + } + } + for (let i = ancestors.length - 1; i >= 0; i--) { + if (ancestors[i].c !== STATE_DISPOSED) + ancestors[i].K(); + } +} + +// src/store/reconcile.ts +function unwrap(value) { + return value?.[$TARGET]?.[STORE_NODE] ?? value; +} +function getOverrideValue(value, override, key) { + return override && key in override ? override[key] : value[key]; +} +function getAllKeys(value, override, next) { + const keys = getKeys(value, override); + const nextKeys = Object.keys(next); + return Array.from(/* @__PURE__ */ new Set([...keys, ...nextKeys])); +} +function applyState(next, state, keyFn, all) { + const target = state?.[$TARGET]; + if (!target) + return; + const previous = target[STORE_VALUE]; + const override = target[STORE_OVERRIDE]; + if (next === previous && !override) + return; + (target[STORE_LOOKUP] || storeLookup).set(next, target[$PROXY]); + target[STORE_VALUE] = next; + target[STORE_OVERRIDE] = void 0; + if (Array.isArray(previous)) { + let changed = false; + const prevLength = getOverrideValue(previous, override, "length"); + if (next.length && prevLength && next[0] && keyFn(next[0]) != null) { + let i, j, start, end, newEnd, item, newIndicesNext, keyVal; + for (start = 0, end = Math.min(prevLength, next.length); start < end && ((item = getOverrideValue(previous, override, start)) === next[start] || item && next[start] && keyFn(item) === keyFn(next[start])); start++) { + applyState(next[start], wrap(item, target), keyFn, all); + } + const temp = new Array(next.length), newIndices = /* @__PURE__ */ new Map(); + for (end = prevLength - 1, newEnd = next.length - 1; end >= start && newEnd >= start && ((item = getOverrideValue(previous, override, end)) === next[newEnd] || item && next[newEnd] && keyFn(item) === keyFn(next[newEnd])); end--, newEnd--) { + temp[newEnd] = item; + } + if (start > newEnd || start > end) { + for (j = start; j <= newEnd; j++) { + changed = true; + target[STORE_NODE][j]?.write(wrap(next[j], target)); + } + for (; j < next.length; j++) { + changed = true; + const wrapped = wrap(temp[j], target); + target[STORE_NODE][j]?.write(wrapped); + applyState(next[j], wrapped, keyFn, all); + } + changed && target[STORE_NODE][$TRACK]?.write(void 0); + prevLength !== next.length && target[STORE_NODE].length?.write(next.length); + return; + } + newIndicesNext = new Array(newEnd + 1); + for (j = newEnd; j >= start; j--) { + item = next[j]; + keyVal = item ? keyFn(item) : item; + i = newIndices.get(keyVal); + newIndicesNext[j] = i === void 0 ? -1 : i; + newIndices.set(keyVal, j); + } + for (i = start; i <= end; i++) { + item = getOverrideValue(previous, override, i); + keyVal = item ? keyFn(item) : item; + j = newIndices.get(keyVal); + if (j !== void 0 && j !== -1) { + temp[j] = item; + j = newIndicesNext[j]; + newIndices.set(keyVal, j); + } + } + for (j = start; j < next.length; j++) { + if (j in temp) { + const wrapped = wrap(temp[j], target); + target[STORE_NODE][j]?.write(wrapped); + applyState(next[j], wrapped, keyFn, all); + } else + target[STORE_NODE][j]?.write(wrap(next[j], target)); + } + if (start < next.length) + changed = true; + } else if (prevLength && next.length) { + for (let i = 0, len = next.length; i < len; i++) { + const item = getOverrideValue(previous, override, i); + isWrappable(item) && applyState(next[i], wrap(item, target), keyFn, all); + } + } + if (prevLength !== next.length) { + changed = true; + target[STORE_NODE].length?.write(next.length); + } + changed && target[STORE_NODE][$TRACK]?.write(void 0); + return; + } + let nodes = target[STORE_NODE]; + if (nodes) { + const tracked = nodes[$TRACK]; + const keys = tracked || all ? getAllKeys(previous, override, next) : Object.keys(nodes); + for (let i = 0, len = keys.length; i < len; i++) { + const key = keys[i]; + const node = nodes[key]; + const previousValue = unwrap(getOverrideValue(previous, override, key)); + let nextValue = unwrap(next[key]); + if (previousValue === nextValue) + continue; + if (!previousValue || !isWrappable(previousValue) || keyFn(previousValue) != null && keyFn(previousValue) !== keyFn(nextValue)) { + tracked?.write(void 0); + node?.write(isWrappable(nextValue) ? wrap(nextValue, target) : nextValue); + } else + applyState(nextValue, wrap(previousValue, target), keyFn, all); + } + } + if (nodes = target[STORE_HAS]) { + const keys = Object.keys(nodes); + for (let i = 0, len = keys.length; i < len; i++) { + nodes[keys[i]].write(keys[i] in next); + } + } +} +function reconcile(value, key, all = false) { + return (state) => { + if (state == null) + throw new Error("Cannot reconcile null or undefined state"); + const keyFn = typeof key === "string" ? (item) => item[key] : key; + const eq = keyFn(state); + if (eq !== void 0 && keyFn(value) !== keyFn(state)) + throw new Error("Cannot reconcile states with different identity"); + applyState(value, state, keyFn, all); + }; +} + +// src/store/projection.ts +function createProjection(fn, initialValue = {}, options) { + let wrappedStore; + const node = new FirewallComputation(() => { + storeSetter(wrappedStore, (s) => { + const value = fn(s); + if (value !== s && value !== void 0) { + reconcile(value, options?.key || "id", options?.all)(s); + } + }); + }); + const wrappedMap = /* @__PURE__ */ new WeakMap(); + const traps = { + ...storeTraps, + get(target, property, receiver) { + const o = getOwner(); + const n = getTransitionSource(node); + (!o || o !== n) && n.wait(); + return storeTraps.get(target, property, receiver); + } + }; + function wrapProjection(source) { + if (wrappedMap.has(source)) + return wrappedMap.get(source); + if (source[$TARGET]?.[STORE_WRAP] === wrapProjection) + return source; + const wrapped = createStoreProxy(source, traps, { + [STORE_WRAP]: wrapProjection, + [STORE_LOOKUP]: wrappedMap + }); + wrappedMap.set(source, wrapped); + return wrapped; + } + return wrappedStore = wrapProjection(initialValue); +} + +// src/store/store.ts +var $TRACK = Symbol(0); +var $DEEP = Symbol(0); +var $TARGET = Symbol(0); +var $PROXY = Symbol(0); +var $DELETED = Symbol(0); +var PARENTS = /* @__PURE__ */ new WeakMap(); +var STORE_VALUE = "v"; +var STORE_OVERRIDE = "o"; +var STORE_NODE = "n"; +var STORE_HAS = "h"; +var STORE_WRAP = "w"; +var STORE_LOOKUP = "l"; +function createStoreProxy(value, traps = storeTraps, extend) { + let newTarget; + if (Array.isArray(value)) { + newTarget = []; + newTarget.v = value; + } else + newTarget = { v: value }; + extend && Object.assign(newTarget, extend); + return newTarget[$PROXY] = new Proxy(newTarget, traps); +} +var storeLookup = /* @__PURE__ */ new WeakMap(); +function wrap(value, target) { + if (target?.[STORE_WRAP]) + return target[STORE_WRAP](value, target); + let p = value[$PROXY] || storeLookup.get(value); + if (!p) + storeLookup.set(value, p = createStoreProxy(value)); + return p; +} +function isWrappable(obj) { + return obj != null && typeof obj === "object" && !Object.isFrozen(obj); +} +function getNodes(target, type) { + let nodes = target[type]; + if (!nodes) + target[type] = nodes = /* @__PURE__ */ Object.create(null); + return nodes; +} +function getNode(nodes, property, value, equals = isEqual) { + if (nodes[property]) + return nodes[property]; + return nodes[property] = new Computation(value, null, { + equals, + unobserved() { + delete nodes[property]; + } + }); +} +function trackSelf(target, symbol = $TRACK) { + getObserver() && getNode(getNodes(target, STORE_NODE), symbol, void 0, false).read(); +} +function getKeys(source, override, enumerable = true) { + const baseKeys = untrack(() => enumerable ? Object.keys(source) : Reflect.ownKeys(source)); + if (!override) + return baseKeys; + const keys = new Set(baseKeys); + const overrides = Reflect.ownKeys(override); + for (const key of overrides) { + if (override[key] !== $DELETED) + keys.add(key); + else + keys.delete(key); + } + return Array.from(keys); +} +function getPropertyDescriptor(source, override, property) { + let value = source; + if (override && property in override) { + if (value[property] === $DELETED) + return void 0; + if (!(property in value)) + value = override; + } + return Reflect.getOwnPropertyDescriptor(value, property); +} +var Writing = null; +var storeTraps = { + get(target, property, receiver) { + if (property === $TARGET) + return target; + if (property === $PROXY) + return receiver; + if (property === $TRACK || property === $DEEP) { + trackSelf(target, property); + return receiver; + } + const nodes = getNodes(target, STORE_NODE); + const tracked = nodes[property]; + const overridden = target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]; + const proxySource = !!target[STORE_VALUE][$TARGET]; + const storeValue = overridden ? target[STORE_OVERRIDE] : target[STORE_VALUE]; + if (!tracked) { + const desc = Object.getOwnPropertyDescriptor(storeValue, property); + if (desc && desc.get) + return desc.get.call(receiver); + } + if (Writing?.has(receiver)) { + let value2 = tracked && (overridden || !proxySource) ? tracked.l : storeValue[property]; + value2 === $DELETED && (value2 = void 0); + if (!isWrappable(value2)) + return value2; + const wrapped = wrap(value2, target); + Writing.add(wrapped); + return wrapped; + } + let value = tracked ? overridden || !proxySource ? nodes[property].read() : (nodes[property].read(), storeValue[property]) : storeValue[property]; + value === $DELETED && (value = void 0); + if (!tracked) { + if (!overridden && typeof value === "function" && !storeValue.hasOwnProperty(property)) { + let proto; + return !Array.isArray(target[STORE_VALUE]) && (proto = Object.getPrototypeOf(target[STORE_VALUE])) && proto !== Object.prototype ? value.bind(storeValue) : value; + } else if (getObserver()) { + return getNode(nodes, property, isWrappable(value) ? wrap(value, target) : value).read(); + } + } + return isWrappable(value) ? wrap(value, target) : value; + }, + has(target, property) { + if (property === $PROXY || property === $TRACK || property === "__proto__") + return true; + const has = target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE] ? target[STORE_OVERRIDE][property] !== $DELETED : property in target[STORE_VALUE]; + getObserver() && getNode(getNodes(target, STORE_HAS), property, has).read(); + return has; + }, + set(target, property, rawValue) { + const store = target[$PROXY]; + if (Writing?.has(target[$PROXY])) { + untrack(() => { + const state = target[STORE_VALUE]; + const base = state[property]; + const prev = target[STORE_OVERRIDE]?.[property] || base; + const value = rawValue?.[$TARGET]?.[STORE_VALUE] ?? rawValue; + if (prev === value) + return true; + const len = target[STORE_OVERRIDE]?.length || state.length; + if (value !== void 0 && value === base) + delete target[STORE_OVERRIDE][property]; + else + (target[STORE_OVERRIDE] || (target[STORE_OVERRIDE] = /* @__PURE__ */ Object.create(null)))[property] = value; + const wrappable = isWrappable(value); + if (isWrappable(prev)) { + const parents = PARENTS.get(prev); + parents && (parents instanceof Set ? parents.delete(store) : PARENTS.delete(prev)); + } + if (recursivelyNotify(store, storeLookup) && wrappable) + recursivelyAddParent(value, store); + target[STORE_HAS]?.[property]?.write(true); + const nodes = getNodes(target, STORE_NODE); + nodes[property]?.write(wrappable ? wrap(value, target) : value); + if (Array.isArray(state)) { + const index = parseInt(property) + 1; + if (index > len) + nodes.length?.write(index); + } + nodes[$TRACK]?.write(void 0); + }); + } + return true; + }, + deleteProperty(target, property) { + if (Writing?.has(target[$PROXY]) && target[STORE_OVERRIDE]?.[property] !== $DELETED) { + untrack(() => { + const prev = target[STORE_OVERRIDE]?.[property] || target[STORE_VALUE][property]; + if (property in target[STORE_VALUE]) { + (target[STORE_OVERRIDE] || (target[STORE_OVERRIDE] = /* @__PURE__ */ Object.create(null)))[property] = $DELETED; + } else if (target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]) { + delete target[STORE_OVERRIDE][property]; + } else + return true; + if (isWrappable(prev)) { + const parents = PARENTS.get(prev); + parents && (parents instanceof Set ? parents.delete(target) : PARENTS.delete(prev)); + } + target[STORE_HAS]?.[property]?.write(false); + const nodes = getNodes(target, STORE_NODE); + nodes[property]?.write(void 0); + nodes[$TRACK]?.write(void 0); + }); + } + return true; + }, + ownKeys(target) { + trackSelf(target); + return getKeys(target[STORE_VALUE], target[STORE_OVERRIDE], false); + }, + getOwnPropertyDescriptor(target, property) { + if (property === $PROXY) + return { value: target[$PROXY], writable: true, configurable: true }; + return getPropertyDescriptor(target[STORE_VALUE], target[STORE_OVERRIDE], property); + }, + getPrototypeOf(target) { + return Object.getPrototypeOf(target[STORE_VALUE]); + } +}; +function storeSetter(store, fn) { + const prevWriting = Writing; + Writing = /* @__PURE__ */ new Set(); + Writing.add(store); + try { + const value = fn(store); + if (value !== store && value !== void 0) { + if (Array.isArray(value)) { + for (let i = 0, len = value.length; i < len; i++) + store[i] = value[i]; + store.length = value.length; + } else { + const keys = /* @__PURE__ */ new Set([...Object.keys(store), ...Object.keys(value)]); + keys.forEach((key) => { + if (key in value) + store[key] = value[key]; + else + delete store[key]; + }); + } + } + } finally { + Writing.clear(); + Writing = prevWriting; + } +} +function createStore(first, second, options) { + const derived = typeof first === "function", wrappedStore = derived ? createProjection(first, second, options) : wrap(first); + return [wrappedStore, (fn) => storeSetter(wrappedStore, fn)]; +} +function recursivelyNotify(state, lookup) { + let target = state[$TARGET] || lookup?.get(state)?.[$TARGET]; + let notified = false; + if (target) { + const deep2 = getNodes(target, STORE_NODE)[$DEEP]; + if (deep2) { + deep2.write(void 0); + notified = true; + } + lookup = target[STORE_LOOKUP] || lookup; + } + const parents = PARENTS.get(target?.[STORE_VALUE] || state); + if (!parents) + return notified; + if (parents instanceof Set) { + for (let parent of parents) + notified = recursivelyNotify(parent, lookup) || notified; + } else + notified = recursivelyNotify(parents, lookup) || notified; + return notified; +} +function recursivelyAddParent(state, parent) { + let override; + const target = state[$TARGET]; + if (target) { + override = target[STORE_OVERRIDE]; + state = target[STORE_VALUE]; + } + if (parent) { + let parents = PARENTS.get(state); + if (!parents) + PARENTS.set(state, parent); + else if (parents !== parent) { + if (!(parents instanceof Set)) + PARENTS.set(state, parents = /* @__PURE__ */ new Set([parents])); + else if (parents.has(parent)) + return; + parents.add(parent); + } else + return; + } + if (Array.isArray(state)) { + const len = override?.length || state.length; + for (let i = 0; i < len; i++) { + const item = override && i in override ? override[i] : state[i]; + isWrappable(item) && recursivelyAddParent(item, state); + } + } else { + const keys = getKeys(state, override); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + const item = override && key in override ? override[key] : state[key]; + isWrappable(item) && recursivelyAddParent(item, state); + } + } +} +function deep(store) { + recursivelyAddParent(store); + return store[$DEEP]; +} + +// src/store/utils.ts +function snapshot(item, map, lookup) { + let target, isArray, override, result, unwrapped, v; + if (!isWrappable(item)) + return item; + if (map && map.has(item)) + return map.get(item); + if (!map) + map = /* @__PURE__ */ new Map(); + if (target = item[$TARGET] || lookup?.get(item)?.[$TARGET]) { + override = target[STORE_OVERRIDE]; + isArray = Array.isArray(target[STORE_VALUE]); + map.set( + item, + override ? result = isArray ? [] : Object.create(Object.getPrototypeOf(target[STORE_VALUE])) : target[STORE_VALUE] + ); + item = target[STORE_VALUE]; + lookup = storeLookup; + } else { + isArray = Array.isArray(item); + map.set(item, item); + } + if (isArray) { + const len = override?.length || item.length; + for (let i = 0; i < len; i++) { + v = override && i in override ? override[i] : item[i]; + if (v === $DELETED) + continue; + if ((unwrapped = snapshot(v, map, lookup)) !== v || result) { + if (!result) + map.set(item, result = [...item]); + result[i] = unwrapped; + } + } + } else { + const keys = getKeys(item, override); + for (let i = 0, l = keys.length; i < l; i++) { + let prop = keys[i]; + const desc = getPropertyDescriptor(item, override, prop); + if (desc.get) + continue; + v = override && prop in override ? override[prop] : item[prop]; + if ((unwrapped = snapshot(v, map, lookup)) !== item[prop] || result) { + if (!result) { + result = Object.create(Object.getPrototypeOf(item)); + Object.assign(result, item); + } + result[prop] = unwrapped; + } + } + } + return result || item; +} +function trueFn() { + return true; +} +var propTraps = { + get(_, property, receiver) { + if (property === $PROXY) + return receiver; + return _.get(property); + }, + has(_, property) { + if (property === $PROXY) + return true; + return _.has(property); + }, + set: trueFn, + deleteProperty: trueFn, + getOwnPropertyDescriptor(_, property) { + return { + configurable: true, + enumerable: true, + get() { + return _.get(property); + }, + set: trueFn, + deleteProperty: trueFn + }; + }, + ownKeys(_) { + return _.keys(); + } +}; +function resolveSource(s) { + return !(s = typeof s === "function" ? s() : s) ? {} : s; +} +var $SOURCES = Symbol(0); +function merge(...sources) { + if (sources.length === 1 && typeof sources[0] !== "function") + return sources[0]; + let proxy = false; + const flattened = []; + for (let i = 0; i < sources.length; i++) { + const s = sources[i]; + proxy = proxy || !!s && $PROXY in s; + const childSources = !!s && s[$SOURCES]; + if (childSources) + flattened.push(...childSources); + else + flattened.push( + typeof s === "function" ? (proxy = true, createMemo(s)) : s + ); + } + if (SUPPORTS_PROXY && proxy) { + return new Proxy( + { + get(property) { + if (property === $SOURCES) + return flattened; + for (let i = flattened.length - 1; i >= 0; i--) { + const s = resolveSource(flattened[i]); + if (property in s) + return s[property]; + } + }, + has(property) { + for (let i = flattened.length - 1; i >= 0; i--) { + if (property in resolveSource(flattened[i])) + return true; + } + return false; + }, + keys() { + const keys = []; + for (let i = 0; i < flattened.length; i++) + keys.push(...Object.keys(resolveSource(flattened[i]))); + return [...new Set(keys)]; + } + }, + propTraps + ); + } + const defined = /* @__PURE__ */ Object.create(null); + let nonTargetKey = false; + let lastIndex = flattened.length - 1; + for (let i = lastIndex; i >= 0; i--) { + const source = flattened[i]; + if (!source) { + i === lastIndex && lastIndex--; + continue; + } + const sourceKeys = Object.getOwnPropertyNames(source); + for (let j = sourceKeys.length - 1; j >= 0; j--) { + const key = sourceKeys[j]; + if (key === "__proto__" || key === "constructor") + continue; + if (!defined[key]) { + nonTargetKey = nonTargetKey || i !== lastIndex; + const desc = Object.getOwnPropertyDescriptor(source, key); + defined[key] = desc.get ? { + enumerable: true, + configurable: true, + get: desc.get.bind(source) + } : desc; + } + } + } + if (!nonTargetKey) + return flattened[lastIndex]; + const target = {}; + const definedKeys = Object.keys(defined); + for (let i = definedKeys.length - 1; i >= 0; i--) { + const key = definedKeys[i], desc = defined[key]; + if (desc.get) + Object.defineProperty(target, key, desc); + else + target[key] = desc.value; + } + target[$SOURCES] = flattened; + return target; +} +function omit(props, ...keys) { + const blocked = new Set(keys); + if (SUPPORTS_PROXY && $PROXY in props) { + return new Proxy( + { + get(property) { + return blocked.has(property) ? void 0 : props[property]; + }, + has(property) { + return !blocked.has(property) && property in props; + }, + keys() { + return Object.keys(props).filter((k) => !blocked.has(k)); + } + }, + propTraps + ); + } + const result = {}; + for (const propName of Object.getOwnPropertyNames(props)) { + if (!blocked.has(propName)) { + const desc = Object.getOwnPropertyDescriptor(props, propName); + !desc.get && !desc.set && desc.enumerable && desc.writable && desc.configurable ? result[propName] = desc.value : Object.defineProperty(result, propName, desc); + } + } + return result; +} + +// src/signals.ts +function createSignal(first, second, third) { + if (typeof first === "function") { + const memo = createMemo((p) => { + const node2 = new Computation( + first(p ? untrack(p[0]) : second), + null, + third + ); + return [node2.read.bind(node2), node2.write.bind(node2)]; + }); + return [() => memo()[0](), (value) => memo()[1](value)]; + } + const o = getOwner(); + const needsId = o?.id != null; + const node = new Computation( + first, + null, + needsId ? { id: o.getNextChildId(), ...second } : second + ); + return [node.read.bind(node), node.write.bind(node)]; +} +function createMemo(compute2, value, options) { + let node = new Computation( + value, + compute2, + options + ); + let resolvedValue; + return () => { + if (node) { + if (node.c === STATE_DISPOSED) { + node = void 0; + return resolvedValue; + } + resolvedValue = node.wait(); + if (!node.a?.length && node.m?.k !== node && !(node.h & UNINITIALIZED_BIT)) { + node.dispose(); + node = void 0; + } + } + return resolvedValue; + }; +} +function createAsync(compute2, value, options) { + let refreshing = false; + const node = new EagerComputation( + value, + (p) => { + const source = compute2(p, refreshing); + refreshing = false; + const isPromise = source instanceof Promise; + const iterator = source[Symbol.asyncIterator]; + if (!isPromise && !iterator) { + return source; + } + let abort = false; + onCleanup(() => abort = true); + let transition2 = ActiveTransition; + if (isPromise) { + source.then( + (value3) => { + if (abort) + return; + if (transition2) + return transition2.runTransition(() => { + node.write(value3, 0, true); + }, true); + node.write(value3, 0, true); + }, + (error) => { + if (abort) + return; + if (transition2) + return transition2.runTransition(() => node.E(error), true); + node.E(error); + } + ); + } else { + (async () => { + try { + for await (let value3 of source) { + if (abort) + return; + if (transition2) + return transition2.runTransition(() => { + node.write(value3, 0, true); + transition2 = null; + }, true); + node.write(value3, 0, true); + } + } catch (error) { + if (abort) + return; + if (transition2) + return transition2.runTransition(() => { + node.E(error); + transition2 = null; + }, true); + node.E(error); + } + })(); + } + throw new NotReadyError(); + }, + options + ); + const read = node.wait.bind(node); + read.refresh = () => { + let n = node; + if (ActiveTransition && !node.e) { + n = cloneGraph(node); + } + n.c = STATE_DIRTY; + refreshing = true; + n.K(); + }; + return read; +} +function createEffect(compute2, effect, value, options) { + void new Effect( + value, + compute2, + effect.effect ? effect.effect : effect, + effect.error, + options + ); +} +function createRenderEffect(compute2, effect, value, options) { + void new Effect(value, compute2, effect, void 0, { + render: true, + ...options + }); +} +function createRoot(init, options) { + const owner = new Owner(options?.id); + return compute(owner, !init.length ? init : () => init(() => owner.dispose()), null); +} +function runWithOwner(owner, run) { + return compute(owner, run, null); +} +function resolve(fn) { + return new Promise((res, rej) => { + createRoot((dispose) => { + new EagerComputation(void 0, () => { + try { + res(fn()); + } catch (err) { + if (err instanceof NotReadyError) + throw err; + rej(err); + } + dispose(); + }); + }); + }); +} +function createPending() { + const node = new Computation(false, null); + const reset = () => node.write(false); + function write() { + if (!ActiveTransition) + return false; + ActiveTransition.addOptimistic(reset); + queueMicrotask(() => reset.j && node.write(true)); + } + function read() { + const v = node.read(); + return ActiveTransition ? false : v; + } + return [read, write]; +} +function useTransition() { + const [pending, setPending] = createPending(); + function start(fn) { + transition((resume) => { + setPending(true); + return fn(resume); + }); + } + return [pending, start]; +} +function createOptimistic(first, second, options) { + let store, setStore; + if (typeof first === "function") { + [store, setStore] = createStore((s) => { + const value = first(s); + if (!ActiveTransition) + return value; + ActiveTransition.addOptimistic(reset); + }, {}); + } else + [store, setStore] = createStore(first); + const reset = () => setStore( + reconcile( + typeof first === "function" ? first(second) : first, + options?.key || "id", + options?.all + ) + ); + function write(v) { + if (!ActiveTransition) + throw new Error("createOptimistic can only be updated inside a transition"); + ActiveTransition.addOptimistic(reset); + queueMicrotask(() => reset.j && setStore(v)); + } + return [store, write]; +} + +// src/map.ts +function mapArray(list, map, options) { + const keyFn = typeof options?.keyed === "function" ? options.keyed : void 0; + return updateKeyedMap.bind({ + S: new Owner(), + o: 0, + ia: list, + G: [], + P: map, + i: [], + d: [], + Q: keyFn, + p: keyFn || options?.keyed === false ? [] : void 0, + q: map.length > 1 ? [] : void 0, + T: options?.fallback + }); +} +var pureOptions = { pureWrite: true }; +function updateKeyedMap() { + const newItems = this.ia() || [], newLen = newItems.length; + newItems[$TRACK]; + runWithOwner(this.S, () => { + let i, j, mapper = this.p ? () => { + this.p[j] = new Computation(newItems[j], null, pureOptions); + this.q && (this.q[j] = new Computation(j, null, pureOptions)); + return this.P( + Computation.prototype.read.bind(this.p[j]), + this.q ? Computation.prototype.read.bind(this.q[j]) : void 0 + ); + } : this.q ? () => { + const item = newItems[j]; + this.q[j] = new Computation(j, null, pureOptions); + return this.P(() => item, Computation.prototype.read.bind(this.q[j])); + } : () => { + const item = newItems[j]; + return this.P(() => item); + }; + if (newLen === 0) { + if (this.o !== 0) { + this.S.dispose(false); + this.d = []; + this.G = []; + this.i = []; + this.o = 0; + this.p && (this.p = []); + this.q && (this.q = []); + } + if (this.T && !this.i[0]) { + this.i[0] = compute( + this.d[0] = new Owner(), + this.T, + null + ); + } + } else if (this.o === 0) { + if (this.d[0]) + this.d[0].dispose(); + this.i = new Array(newLen); + for (j = 0; j < newLen; j++) { + this.G[j] = newItems[j]; + this.i[j] = compute(this.d[j] = new Owner(), mapper, null); + } + this.o = newLen; + } else { + let start, end, newEnd, item, key, newIndices, newIndicesNext, temp = new Array(newLen), tempNodes = new Array(newLen), tempRows = this.p ? new Array(newLen) : void 0, tempIndexes = this.q ? new Array(newLen) : void 0; + for (start = 0, end = Math.min(this.o, newLen); start < end && (this.G[start] === newItems[start] || this.p && compare(this.Q, this.G[start], newItems[start])); start++) { + if (this.p) + this.p[start].write(newItems[start]); + } + for (end = this.o - 1, newEnd = newLen - 1; end >= start && newEnd >= start && (this.G[end] === newItems[newEnd] || this.p && compare(this.Q, this.G[end], newItems[newEnd])); end--, newEnd--) { + temp[newEnd] = this.i[end]; + tempNodes[newEnd] = this.d[end]; + tempRows && (tempRows[newEnd] = this.p[end]); + tempIndexes && (tempIndexes[newEnd] = this.q[end]); + } + newIndices = /* @__PURE__ */ new Map(); + newIndicesNext = new Array(newEnd + 1); + for (j = newEnd; j >= start; j--) { + item = newItems[j]; + key = this.Q ? this.Q(item) : item; + i = newIndices.get(key); + newIndicesNext[j] = i === void 0 ? -1 : i; + newIndices.set(key, j); + } + for (i = start; i <= end; i++) { + item = this.G[i]; + key = this.Q ? this.Q(item) : item; + j = newIndices.get(key); + if (j !== void 0 && j !== -1) { + temp[j] = this.i[i]; + tempNodes[j] = this.d[i]; + tempRows && (tempRows[j] = this.p[i]); + tempIndexes && (tempIndexes[j] = this.q[i]); + j = newIndicesNext[j]; + newIndices.set(key, j); + } else + this.d[i].dispose(); + } + for (j = start; j < newLen; j++) { + if (j in temp) { + this.i[j] = temp[j]; + this.d[j] = tempNodes[j]; + if (tempRows) { + this.p[j] = tempRows[j]; + this.p[j].write(newItems[j]); + } + if (tempIndexes) { + this.q[j] = tempIndexes[j]; + this.q[j].write(j); + } + } else { + this.i[j] = compute(this.d[j] = new Owner(), mapper, null); + } + } + this.i = this.i.slice(0, this.o = newLen); + this.G = newItems.slice(0); + } + }); + return this.i; +} +function repeat(count, map, options) { + return updateRepeat.bind({ + S: new Owner(), + o: 0, + z: 0, + ja: count, + P: map, + d: [], + i: [], + ka: options?.from, + T: options?.fallback + }); +} +function updateRepeat() { + const newLen = this.ja(); + const from = this.ka?.() || 0; + runWithOwner(this.S, () => { + if (newLen === 0) { + if (this.o !== 0) { + this.S.dispose(false); + this.d = []; + this.i = []; + this.o = 0; + } + if (this.T && !this.i[0]) { + this.i[0] = compute( + this.d[0] = new Owner(), + this.T, + null + ); + } + return; + } + const to = from + newLen; + const prevTo = this.z + this.o; + if (this.o === 0 && this.d[0]) + this.d[0].dispose(); + for (let i = to; i < prevTo; i++) + this.d[i - this.z].dispose(); + if (this.z < from) { + let i = this.z; + while (i < from && i < this.o) + this.d[i++].dispose(); + this.d.splice(0, from - this.z); + this.i.splice(0, from - this.z); + } else if (this.z > from) { + let i = prevTo - this.z - 1; + let difference = this.z - from; + this.d.length = this.i.length = newLen; + while (i >= difference) { + this.d[i] = this.d[i - difference]; + this.i[i] = this.i[i - difference]; + i--; + } + for (let i2 = 0; i2 < difference; i2++) { + this.i[i2] = compute( + this.d[i2] = new Owner(), + () => this.P(i2 + from), + null + ); + } + } + for (let i = prevTo; i < to; i++) { + this.i[i - from] = compute( + this.d[i - from] = new Owner(), + () => this.P(i), + null + ); + } + this.i = this.i.slice(0, newLen); + this.z = from; + this.o = newLen; + }); + return this.i; +} +function compare(key, a, b) { + return key ? key(a) === key(b) : true; +} + +// src/boundaries.ts +var BoundaryComputation = class extends EagerComputation { + U; + constructor(compute2, propagationMask) { + super(void 0, compute2, { defer: true }); + this.U = propagationMask; + } + write(value, flags) { + super.write(value, flags & ~this.U); + if (this.U & LOADING_BIT && !(this.h & UNINITIALIZED_BIT || ActiveTransition)) { + flags &= ~LOADING_BIT; + } + getQueue(this).notify(this, this.U, flags); + return this.l; + } +}; +function createBoundChildren(owner, fn, queue, mask) { + const parentQueue = owner.B; + parentQueue.addChild(owner.B = queue); + onCleanup(() => parentQueue.removeChild(owner.B)); + return compute( + owner, + () => { + const c = new Computation(void 0, fn); + return new BoundaryComputation(() => flatten(c.wait()), mask); + }, + null + ); +} +var ConditionalQueue = class extends Queue { + t; + V = /* @__PURE__ */ new Set(); + s = /* @__PURE__ */ new Set(); + constructor(disabled) { + super(); + this.t = disabled; + } + run(type) { + if (!type || this.t.read()) + return; + return super.run(type); + } + notify(node, type, flags) { + if (ActiveTransition && ActiveTransition.r.has(this)) + return ActiveTransition.r.get(this).notify(node, type, flags); + if (this.t.read()) { + if (type & LOADING_BIT) { + if (flags & LOADING_BIT) { + this.s.add(node); + type &= ~LOADING_BIT; + } else if (this.s.delete(node)) + type &= ~LOADING_BIT; + } + if (type & ERROR_BIT) { + if (flags & ERROR_BIT) { + this.V.add(node); + type &= ~ERROR_BIT; + } else if (this.V.delete(node)) + type &= ~ERROR_BIT; + } + } + return type ? super.notify(node, type, flags) : true; + } + merge(queue) { + queue.s.forEach((n) => this.notify(n, LOADING_BIT, LOADING_BIT)); + queue.V.forEach((n) => this.notify(n, ERROR_BIT, ERROR_BIT)); + super.merge(queue); + } +}; +var CollectionQueue = class extends Queue { + J; + d = /* @__PURE__ */ new Set(); + t = new Computation(false, null, { pureWrite: true }); + constructor(type) { + super(); + this.J = type; + } + run(type) { + if (!type || this.t.read()) + return; + return super.run(type); + } + notify(node, type, flags) { + if (ActiveTransition && ActiveTransition.r.has(this)) + return ActiveTransition.r.get(this).notify(node, type, flags); + if (!(type & this.J)) + return super.notify(node, type, flags); + if (flags & this.J) { + this.d.add(node); + if (this.d.size === 1) + this.t.write(true); + } else if (this.d.size > 0) { + this.d.delete(node); + if (this.d.size === 0) + this.t.write(false); + } + type &= ~this.J; + return type ? super.notify(node, type, flags) : true; + } + merge(queue) { + queue.d.forEach((n) => this.notify(n, this.J, this.J)); + super.merge(queue); + } +}; +function createBoundary(fn, condition) { + const owner = new Owner(); + const queue = new ConditionalQueue( + new Computation(void 0, () => condition() === "hidden" /* HIDDEN */) + ); + const tree = createBoundChildren(owner, fn, queue, 0); + new EagerComputation(void 0, () => { + const disabled = queue.t.read(); + tree.U = disabled ? ERROR_BIT | LOADING_BIT : 0; + if (!disabled) { + queue.s.forEach((node) => queue.notify(node, LOADING_BIT, LOADING_BIT)); + queue.V.forEach((node) => queue.notify(node, ERROR_BIT, ERROR_BIT)); + queue.s.clear(); + queue.V.clear(); + } + }); + return () => queue.t.read() ? void 0 : tree.read(); +} +function createCollectionBoundary(type, fn, fallback) { + const owner = new Owner(); + const queue = new CollectionQueue(type); + const tree = createBoundChildren(owner, fn, queue, type); + const decision = new Computation(void 0, () => { + if (!queue.t.read()) { + const resolved = tree.read(); + if (!untrack(() => queue.t.read())) + return resolved; + } + return fallback(queue); + }); + return decision.read.bind(decision); +} +function createSuspense(fn, fallback) { + return createCollectionBoundary(LOADING_BIT, fn, () => fallback()); +} +function createErrorBoundary(fn, fallback) { + return createCollectionBoundary(ERROR_BIT, fn, (queue) => { + let node = getTransitionSource(queue.d.values().next().value); + return fallback(node.L, () => { + incrementClock(); + for (let node2 of queue.d) { + if (ActiveTransition && !node2.e) + node2 = cloneGraph(node2); + node2.c = STATE_DIRTY; + getQueue(node2).enqueue(node2.C, node2.F.bind(node2)); + } + }); + }); +} +function flatten(children, options) { + if (typeof children === "function" && !children.length) { + if (options?.doNotUnwrap) + return children; + do { + children = children(); + } while (typeof children === "function" && !children.length); + } + if (options?.skipNonRendered && (children == null || children === true || children === false || children === "")) + return; + if (Array.isArray(children)) { + let results = []; + if (flattenArray(children, results, options)) { + return () => { + let nested = []; + flattenArray(results, nested, { ...options, doNotUnwrap: false }); + return nested; + }; + } + return results; + } + return children; +} +function flattenArray(children, results = [], options) { + let notReady = null; + let needsUnwrap = false; + for (let i = 0; i < children.length; i++) { + try { + let child = children[i]; + if (typeof child === "function" && !child.length) { + if (options?.doNotUnwrap) { + results.push(child); + needsUnwrap = true; + continue; + } + do { + child = child(); + } while (typeof child === "function" && !child.length); + } + if (Array.isArray(child)) { + needsUnwrap = flattenArray(child, results, options); + } else if (options?.skipNonRendered && (child == null || child === true || child === false || child === "")) { + } else + results.push(child); + } catch (e) { + if (!(e instanceof NotReadyError)) + throw e; + notReady = e; + } + } + if (notReady) + throw notReady; + return needsUnwrap; +} + +export { $PROXY, $TARGET, $TRACK, Computation, ContextNotFoundError, NoOwnerError, NotReadyError, Owner, Queue, SUPPORTS_PROXY, createAsync, createBoundary, createContext, createEffect, createErrorBoundary, createMemo, createOptimistic, createProjection, createRenderEffect, createRoot, createSignal, createStore, createSuspense, deep, flatten, flush, getContext, getObserver, getOwner, hasContext, hasUpdated, isEqual, isPending, isWrappable, latest, mapArray, merge, omit, onCleanup, reconcile, repeat, resolve, runWithObserver, runWithOwner, setContext, snapshot, transition, untrack, useTransition }; diff --git a/packages/solidjs-signals/0.6.3/dist/types/boundaries.d.ts b/packages/solidjs-signals/0.6.3/dist/types/boundaries.d.ts new file mode 100644 index 000000000..e2256a3b6 --- /dev/null +++ b/packages/solidjs-signals/0.6.3/dist/types/boundaries.d.ts @@ -0,0 +1,22 @@ +import { Computation, Queue } from "./core/index.js"; +import type { Effect } from "./core/index.js"; +export declare class CollectionQueue extends Queue { + _collectionType: number; + _nodes: Set; + _disabled: Computation; + constructor(type: number); + run(type: number): void; + notify(node: Effect, type: number, flags: number): any; + merge(queue: CollectionQueue): void; +} +export declare enum BoundaryMode { + VISIBLE = "visible", + HIDDEN = "hidden" +} +export declare function createBoundary(fn: () => T, condition: () => BoundaryMode): () => T | undefined; +export declare function createSuspense(fn: () => any, fallback: () => any): () => any; +export declare function createErrorBoundary(fn: () => any, fallback: (error: unknown, reset: () => void) => U): () => any; +export declare function flatten(children: any, options?: { + skipNonRendered?: boolean; + doNotUnwrap?: boolean; +}): any; diff --git a/packages/solidjs-signals/0.6.3/dist/types/core/constants.d.ts b/packages/solidjs-signals/0.6.3/dist/types/core/constants.d.ts new file mode 100644 index 000000000..34e31ee8e --- /dev/null +++ b/packages/solidjs-signals/0.6.3/dist/types/core/constants.d.ts @@ -0,0 +1,14 @@ +/** + * See https://dev.to/modderme123/super-charging-fine-grained-reactive-performance-47ph + * State clean corresponds to a node where all the sources are fully up to date + * State check corresponds to a node where some sources (including grandparents) may have changed + * State dirty corresponds to a node where the direct parents of a node has changed + */ +export declare const STATE_CLEAN = 0; +export declare const STATE_CHECK = 1; +export declare const STATE_DIRTY = 2; +export declare const STATE_DISPOSED = 3; +export declare const EFFECT_PURE = 0; +export declare const EFFECT_RENDER = 1; +export declare const EFFECT_USER = 2; +export declare const SUPPORTS_PROXY: boolean; diff --git a/packages/solidjs-signals/0.6.3/dist/types/core/core.d.ts b/packages/solidjs-signals/0.6.3/dist/types/core/core.d.ts new file mode 100644 index 000000000..7010389f5 --- /dev/null +++ b/packages/solidjs-signals/0.6.3/dist/types/core/core.d.ts @@ -0,0 +1,162 @@ +/** + * Nodes for constructing a graph of reactive values and reactive computations. + * + * - The graph is acyclic. + * - The user inputs new values into the graph by calling .write() on one more computation nodes. + * - The user retrieves computed results from the graph by calling .read() on one or more computation nodes. + * - The library is responsible for running any necessary computations so that .read() is up to date + * with all prior .write() calls anywhere in the graph. + * - We call the input nodes 'roots' and the output nodes 'leaves' of the graph here. + * - Changes flow from roots to leaves. It would be effective but inefficient to immediately + * propagate all changes from a root through the graph to descendant leaves. Instead, we defer + * change most change propagation computation until a leaf is accessed. This allows us to + * coalesce computations and skip altogether recalculating unused sections of the graph. + * - Each computation node tracks its sources and its observers (observers are other + * elements that have this node as a source). Source and observer links are updated automatically + * as observer computations re-evaluate and call get() on their sources. + * - Each node stores a cache state (clean/check/dirty) to support the change propagation algorithm: + * + * In general, execution proceeds in three passes: + * + * 1. write() propagates changes down the graph to the leaves + * direct children are marked as dirty and their deeper descendants marked as check + * (no computations are evaluated) + * 2. read() requests that parent nodes updateIfNecessary(), which proceeds recursively up the tree + * to decide whether the node is clean (parents unchanged) or dirty (parents changed) + * 3. updateIfNecessary() evaluates the computation if the node is dirty (the computations are + * executed in root to leaf order) + */ +import { type Flags } from "./flags.js"; +import { Owner } from "./owner.js"; +import { type Transition } from "./scheduler.js"; +export interface SignalOptions { + id?: string; + name?: string; + equals?: ((prev: T, next: T) => boolean) | false; + pureWrite?: boolean; + unobserved?: () => void; +} +export interface SourceType { + _observers: ObserverType[] | null; + _unobserved?: () => void; + _updateIfNecessary: () => void; + _stateFlags: Flags; + _time: number; + _transition?: Transition; + _cloned?: Computation; +} +export interface ObserverType { + _sources: SourceType[] | null; + _notify: (state: number, skipQueue?: boolean) => void; + _handlerMask: Flags; + _notifyFlags: (mask: Flags, newFlags: Flags) => void; + _time: number; + _cloned?: Computation; +} +/** + * Returns the current observer. + */ +export declare function getObserver(): Computation | null; +export declare const UNCHANGED: unique symbol; +export type UNCHANGED = typeof UNCHANGED; +export declare class Computation extends Owner implements SourceType, ObserverType { + _sources: SourceType[] | null; + _observers: ObserverType[] | null; + _value: T | undefined; + _error: unknown; + _compute: null | ((p?: T) => T); + _name: string | undefined; + _equals: false | ((a: T, b: T) => boolean); + _unobserved: (() => void) | undefined; + _pureWrite: boolean; + /** Whether the computation is an error or has ancestors that are unresolved */ + _stateFlags: number; + /** Which flags raised by sources are handled, vs. being passed through. */ + _handlerMask: number; + _time: number; + _forceNotify: boolean; + _transition?: Transition | undefined; + _cloned?: Computation; + constructor(initialValue: T | undefined, compute: null | ((p?: T) => T), options?: SignalOptions); + _read(): T; + /** + * Return the current value of this computation + * Automatically re-executes the surrounding computation when the value changes + */ + read(): T; + /** + * Return the current value of this computation + * Automatically re-executes the surrounding computation when the value changes + * + * If the computation has any unresolved ancestors, this function waits for the value to resolve + * before continuing + */ + wait(): T; + /** Update the computation with a new value. */ + write(value: T | ((currentValue: T) => T) | UNCHANGED, flags?: number, raw?: boolean): T; + /** + * Set the current node's state, and recursively mark all of this node's observers as STATE_CHECK + */ + _notify(state: number, skipQueue?: boolean): void; + /** + * Notify the computation that one of its sources has changed flags. + * + * @param mask A bitmask for which flag(s) were changed. + * @param newFlags The source's new flags, masked to just the changed ones. + */ + _notifyFlags(mask: Flags, newFlags: Flags): void; + _setError(error: unknown): void; + /** + * This is the core part of the reactivity system, which makes sure that the values are updated + * before they are read. We've also adapted it to return the loading state of the computation, + * so that we can propagate that to the computation's observers. + * + * This function will ensure that the value and states we read from the computation are up to date + */ + _updateIfNecessary(): void; + /** + * Remove ourselves from the owner graph and the computation graph + */ + _disposeNode(): void; +} +/** + * Reruns a computation's _compute function, producing a new value and keeping track of dependencies. + * + * It handles the updating of sources and observers, disposal of previous executions, + * and error handling if the _compute function throws. It also sets the node as loading + * if it reads any parents that are currently loading. + */ +export declare function update(node: Computation): void; +export declare function isEqual(a: T, b: T): boolean; +/** + * Returns the current value stored inside the given compute function without triggering any + * dependencies. Use `untrack` if you want to also disable owner tracking. + */ +export declare function untrack(fn: () => T): T; +/** + * Returns true if the given functinon contains signals that have been updated since the last time + * the parent computation was run. + */ +export declare function hasUpdated(fn: () => any): boolean; +/** + * Returns an accessor that is true if the given function contains async signals that are out of date. + */ +export declare function isPending(fn: () => any): boolean; +export declare function isPending(fn: () => any, loadingValue: boolean): boolean; +/** + * Attempts to resolve value of expression synchronously returning the last resolved value for any async computation. + */ +export declare function latest(fn: () => T): T; +export declare function latest(fn: () => T, fallback: U): T | U; +/** + * Runs the given function in the given observer. + * + * Warning: Usually there are simpler ways of modeling a problem that avoid using this function + */ +export declare function runWithObserver(observer: Computation, run: () => T): T | undefined; +/** + * A convenient wrapper that calls `compute` with the `owner` and `observer` and is guaranteed + * to reset the global context after the computation is finished even if an error is thrown. + */ +export declare function compute(owner: Owner | null, fn: (val: T) => T, observer: Computation): T; +export declare function compute(owner: Owner | null, fn: (val: undefined) => T, observer: null): T; diff --git a/packages/solidjs-signals/0.6.3/dist/types/core/effect.d.ts b/packages/solidjs-signals/0.6.3/dist/types/core/effect.d.ts new file mode 100644 index 000000000..fef147c10 --- /dev/null +++ b/packages/solidjs-signals/0.6.3/dist/types/core/effect.d.ts @@ -0,0 +1,39 @@ +import { EFFECT_RENDER, EFFECT_USER } from "./constants.js"; +import { Computation, type SignalOptions } from "./core.js"; +import { type Flags } from "./flags.js"; +/** + * Effects are the leaf nodes of our reactive graph. When their sources change, they are + * automatically added to the queue of effects to re-execute, which will cause them to fetch their + * sources and recompute + */ +export declare class Effect extends Computation { + _effect: (val: T, prev: T | undefined) => void | (() => void); + _onerror: ((err: unknown, cleanup: () => void) => void) | undefined; + _cleanup: (() => void) | undefined; + _modified: boolean; + _prevValue: T | undefined; + _type: typeof EFFECT_RENDER | typeof EFFECT_USER; + constructor(initialValue: T, compute: (val?: T) => T, effect: (val: T, prev: T | undefined) => void | (() => void), error?: (err: unknown) => void | (() => void), options?: SignalOptions & { + render?: boolean; + defer?: boolean; + }); + write(value: T, flags?: number): T; + _notify(state: number, skipQueue?: boolean): void; + _notifyFlags(mask: Flags, newFlags: Flags): void; + _setError(error: unknown): void; + _disposeNode(): void; + _run(type: number): void; +} +export declare class EagerComputation extends Computation { + constructor(initialValue: T, compute: () => T, options?: SignalOptions & { + defer?: boolean; + }); + _notify(state: number, skipQueue?: boolean): void; + _run(): void; +} +export declare class FirewallComputation extends Computation { + firewall: boolean; + constructor(compute: () => void); + _notify(state: number, skipQueue?: boolean): void; + _run(): void; +} diff --git a/packages/solidjs-signals/0.6.3/dist/types/core/error.d.ts b/packages/solidjs-signals/0.6.3/dist/types/core/error.d.ts new file mode 100644 index 000000000..eea675ff9 --- /dev/null +++ b/packages/solidjs-signals/0.6.3/dist/types/core/error.d.ts @@ -0,0 +1,8 @@ +export declare class NotReadyError extends Error { +} +export declare class NoOwnerError extends Error { + constructor(); +} +export declare class ContextNotFoundError extends Error { + constructor(); +} diff --git a/packages/solidjs-signals/0.6.3/dist/types/core/flags.d.ts b/packages/solidjs-signals/0.6.3/dist/types/core/flags.d.ts new file mode 100644 index 000000000..b63bff2e2 --- /dev/null +++ b/packages/solidjs-signals/0.6.3/dist/types/core/flags.d.ts @@ -0,0 +1,11 @@ +export type Flags = number; +export declare const ERROR_OFFSET = 0; +export declare const ERROR_BIT: number; +export declare const ERROR: unique symbol; +export declare const LOADING_OFFSET = 1; +export declare const LOADING_BIT: number; +export declare const LOADING: unique symbol; +export declare const UNINITIALIZED_OFFSET = 2; +export declare const UNINITIALIZED_BIT: number; +export declare const UNINITIALIZED: unique symbol; +export declare const DEFAULT_FLAGS: number; diff --git a/packages/solidjs-signals/0.6.3/dist/types/core/index.d.ts b/packages/solidjs-signals/0.6.3/dist/types/core/index.d.ts new file mode 100644 index 000000000..a7f9c9efc --- /dev/null +++ b/packages/solidjs-signals/0.6.3/dist/types/core/index.d.ts @@ -0,0 +1,7 @@ +export { ContextNotFoundError, NoOwnerError, NotReadyError } from "./error.js"; +export { Owner, createContext, getContext, setContext, hasContext, getOwner, onCleanup, type Context, type ContextRecord, type Disposable } from "./owner.js"; +export { Computation, getObserver, isEqual, untrack, hasUpdated, isPending, latest, UNCHANGED, compute, runWithObserver, type SignalOptions } from "./core.js"; +export { Effect, EagerComputation } from "./effect.js"; +export { flush, Queue, incrementClock, transition, ActiveTransition, type IQueue } from "./scheduler.js"; +export * from "./constants.js"; +export * from "./flags.js"; diff --git a/packages/solidjs-signals/0.6.3/dist/types/core/owner.d.ts b/packages/solidjs-signals/0.6.3/dist/types/core/owner.d.ts new file mode 100644 index 000000000..83f9c4301 --- /dev/null +++ b/packages/solidjs-signals/0.6.3/dist/types/core/owner.d.ts @@ -0,0 +1,95 @@ +/** + * Owner tracking is used to enable nested tracking scopes with automatic cleanup. + * We also use owners to also keep track of which error handling context we are in. + * + * If you write the following + * + * const a = createOwner(() => { + * const b = createOwner(() => {}); + * + * const c = createOwner(() => { + * const d = createOwner(() => {}); + * }); + * + * const e = createOwner(() => {}); + * }); + * + * The owner tree will look like this: + * + * a + * /|\ + * b-c-e + * | + * d + * + * Following the _nextSibling pointers of each owner will first give you its children, and then its siblings (in reverse). + * a -> e -> c -> d -> b + * + * Note that the owner tree is largely orthogonal to the reactivity tree, and is much closer to the component tree. + */ +import { type IQueue } from "./scheduler.js"; +export type ContextRecord = Record; +export interface Disposable { + (): void; +} +/** + * Returns the currently executing parent owner. + */ +export declare function getOwner(): Owner | null; +export declare function setOwner(owner: Owner | null): Owner | null; +export declare class Owner { + _parent: Owner | null; + _nextSibling: Owner | null; + _prevSibling: Owner | null; + _state: number; + _disposal: Disposable | Disposable[] | null; + _context: ContextRecord; + _queue: IQueue; + _childCount: number; + id: string | null; + constructor(id?: string | null, skipAppend?: boolean); + append(child: Owner): void; + dispose(this: Owner, self?: boolean): void; + _disposeNode(): void; + emptyDisposal(): void; + getNextChildId(): string; +} +export interface Context { + readonly id: symbol; + readonly defaultValue: T | undefined; +} +/** + * Context provides a form of dependency injection. It is used to save from needing to pass + * data as props through intermediate components. This function creates a new context object + * that can be used with `getContext` and `setContext`. + * + * A default value can be provided here which will be used when a specific value is not provided + * via a `setContext` call. + */ +export declare function createContext(defaultValue?: T, description?: string): Context; +/** + * Attempts to get a context value for the given key. + * + * @throws `NoOwnerError` if there's no owner at the time of call. + * @throws `ContextNotFoundError` if a context value has not been set yet. + */ +export declare function getContext(context: Context, owner?: Owner | null): T; +/** + * Attempts to set a context value on the parent scope with the given key. + * + * @throws `NoOwnerError` if there's no owner at the time of call. + */ +export declare function setContext(context: Context, value?: T, owner?: Owner | null): void; +/** + * Whether the given context is currently defined. + */ +export declare function hasContext(context: Context, owner?: Owner | null): boolean; +/** + * Runs an effect once before the reactive scope is disposed + * @param fn an effect that should run only once on cleanup + * + * @returns the same {@link fn} function that was passed in + * + * @description https://docs.solidjs.com/reference/lifecycle/on-cleanup + */ +export declare function onCleanup(fn: Disposable): Disposable; diff --git a/packages/solidjs-signals/0.6.3/dist/types/core/scheduler.d.ts b/packages/solidjs-signals/0.6.3/dist/types/core/scheduler.d.ts new file mode 100644 index 000000000..f9bce8bc8 --- /dev/null +++ b/packages/solidjs-signals/0.6.3/dist/types/core/scheduler.d.ts @@ -0,0 +1,86 @@ +import type { Computation, ObserverType, SourceType } from "./core.js"; +import type { Effect } from "./effect.js"; +export declare let clock: number; +export declare function incrementClock(): void; +export declare let ActiveTransition: Transition | null; +export declare let Unobserved: SourceType[]; +export type QueueCallback = (type: number) => void; +export interface IQueue { + enqueue(type: number, fn: QueueCallback): void; + run(type: number): boolean | void; + flush(): void; + addChild(child: IQueue): void; + removeChild(child: IQueue): void; + created: number; + notify(...args: any[]): boolean; + merge(queue: IQueue): void; + _parent: IQueue | null; + _cloned?: IQueue | undefined; +} +export declare class Queue implements IQueue { + _parent: IQueue | null; + _running: boolean; + _queues: [QueueCallback[], QueueCallback[]]; + _children: IQueue[]; + created: number; + enqueue(type: number, fn: QueueCallback): void; + run(type: number): void; + flush(): void; + addChild(child: IQueue): any; + removeChild(child: IQueue): any; + notify(...args: any[]): boolean; + merge(queue: Queue): void; +} +export declare const globalQueue: Queue; +/** + * By default, changes are batched on the microtask queue which is an async process. You can flush + * the queue synchronously to get the latest updates by calling `flush()`. + */ +export declare function flush(): void; +export declare function removeSourceObservers(node: ObserverType, index: number): void; +export declare class Transition implements IQueue { + _sources: Map; + _pendingNodes: Set; + _promises: Set>; + _optimistic: Set<(() => void) & { + _transition?: Transition; + }>; + _done: Transition | boolean; + _queues: [QueueCallback[], QueueCallback[]]; + _clonedQueues: Map; + _pureQueue: QueueCallback[]; + _children: IQueue[]; + _parent: IQueue | null; + _running: boolean; + _scheduled: boolean; + _cloned: Queue; + created: number; + constructor(); + enqueue(type: number, fn: QueueCallback): void; + run(type: number): void; + flush(): void; + addChild(child: IQueue): void; + removeChild(child: IQueue): void; + notify(node: Effect, type: number, flags: number): boolean; + merge(queue: Transition): void; + schedule(): void; + runTransition(fn: () => any | Promise, force?: boolean): void; + addOptimistic(fn: (() => void) & { + _transition?: Transition; + }): void; +} +/** + * Runs the given function in a transition scope, allowing for batch updates and optimizations. + * This is useful for grouping multiple state updates together to avoid unnecessary re-renders. + * + * @param fn A function that receives a resume function to continue the transition. + * The resume function can be called with another function to continue the transition. + * + * @description https://docs.solidjs.com/reference/advanced-reactivity/transition + */ +export declare function transition(fn: (resume: (fn: () => any | Promise) => void) => any | Promise | Iterable): void; +export declare function cloneGraph(node: Computation): Computation; +export declare function getOGSource(input: T): T; +export declare function getTransitionSource(input: T): T; +export declare function getQueue(node: Computation): IQueue; +export declare function initialDispose(node: any): void; diff --git a/packages/solidjs-signals/0.6.3/dist/types/index.d.ts b/packages/solidjs-signals/0.6.3/dist/types/index.d.ts new file mode 100644 index 000000000..b797d264c --- /dev/null +++ b/packages/solidjs-signals/0.6.3/dist/types/index.d.ts @@ -0,0 +1,6 @@ +export { Computation, ContextNotFoundError, NoOwnerError, NotReadyError, Owner, Queue, createContext, flush, getContext, setContext, hasContext, getOwner, onCleanup, getObserver, isEqual, untrack, hasUpdated, isPending, latest, runWithObserver, transition, SUPPORTS_PROXY } from "./core/index.js"; +export type { SignalOptions, Context, ContextRecord, Disposable, IQueue } from "./core/index.js"; +export { mapArray, repeat, type Maybe } from "./map.js"; +export * from "./signals.js"; +export * from "./store/index.js"; +export { createSuspense, createErrorBoundary, createBoundary, flatten, type BoundaryMode } from "./boundaries.js"; diff --git a/packages/solidjs-signals/0.6.3/dist/types/map.d.ts b/packages/solidjs-signals/0.6.3/dist/types/map.d.ts new file mode 100644 index 000000000..74ed53672 --- /dev/null +++ b/packages/solidjs-signals/0.6.3/dist/types/map.d.ts @@ -0,0 +1,22 @@ +import type { Accessor } from "./signals.js"; +export type Maybe = T | void | null | undefined | false; +/** + * Reactively transforms an array with a callback function - underlying helper for the `` control flow + * + * similar to `Array.prototype.map`, but gets the value and index as accessors, transforms only values that changed and returns an accessor and reactively tracks changes to the list. + * + * @description https://docs.solidjs.com/reference/reactive-utilities/map-array + */ +export declare function mapArray(list: Accessor>, map: (value: Accessor, index: Accessor) => MappedItem, options?: { + keyed?: boolean | ((item: Item) => any); + fallback?: Accessor; +}): Accessor; +/** + * Reactively repeats a callback function the count provided - underlying helper for the `` control flow + * + * @description https://docs.solidjs.com/reference/reactive-utilities/repeat + */ +export declare function repeat(count: Accessor, map: (index: number) => any, options?: { + from?: Accessor; + fallback?: Accessor; +}): Accessor; diff --git a/packages/solidjs-signals/0.6.3/dist/types/signals.d.ts b/packages/solidjs-signals/0.6.3/dist/types/signals.d.ts new file mode 100644 index 000000000..528a0de98 --- /dev/null +++ b/packages/solidjs-signals/0.6.3/dist/types/signals.d.ts @@ -0,0 +1,180 @@ +import type { SignalOptions } from "./core/index.js"; +import { Owner } from "./core/index.js"; +import { type Store, type StoreSetter } from "./store/index.js"; +export type Accessor = () => T; +export type Setter = { + (...args: undefined extends T ? [] : [value: Exclude | ((prev: T) => U)]): undefined extends T ? undefined : U; + (value: (prev: T) => U): U; + (value: Exclude): U; + (value: Exclude | ((prev: T) => U)): U; +}; +export type Signal = [get: Accessor, set: Setter]; +export type ComputeFunction = (v: Prev) => Next; +export type EffectFunction = (v: Next, p?: Prev) => (() => void) | void; +export type EffectBundle = { + effect: EffectFunction; + error: (err: unknown, cleanup: () => void) => void; +}; +export interface EffectOptions { + name?: string; + defer?: boolean; +} +export interface MemoOptions { + name?: string; + equals?: false | ((prev: T, next: T) => boolean); +} +export type NoInfer = [T][T extends any ? 0 : never]; +/** + * Creates a simple reactive state with a getter and setter + * ```typescript + * const [state: Accessor, setState: Setter] = createSignal( + * value: T, + * options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } + * ) + * ``` + * @param value initial value of the state; if empty, the state's type will automatically extended with undefined; otherwise you need to extend the type manually if you want setting to undefined not be an error + * @param options optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity + * + * @returns ```typescript + * [state: Accessor, setState: Setter] + * ``` + * * the Accessor is a function that returns the current value and registers each call to the reactive root + * * the Setter is a function that allows directly setting or mutating the value: + * ```typescript + * const [count, setCount] = createSignal(0); + * setCount(count => count + 1); + * ``` + * + * @description https://docs.solidjs.com/reference/basic-reactivity/create-signal + */ +export declare function createSignal(): Signal; +export declare function createSignal(value: Exclude, options?: SignalOptions): Signal; +export declare function createSignal(fn: ComputeFunction, initialValue?: T, options?: SignalOptions): Signal; +/** + * Creates a readonly derived reactive memoized signal + * ```typescript + * export function createMemo( + * compute: (v: T) => T, + * value?: T, + * options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } + * ): () => T; + * ``` + * @param compute a function that receives its previous or the initial value, if set, and returns a new value used to react on a computation + * @param value an optional initial value for the computation; if set, fn will never receive undefined as first argument + * @param options allows to set a name in dev mode for debugging purposes and use a custom comparison function in equals + * + * @description https://docs.solidjs.com/reference/basic-reactivity/create-memo + */ +export declare function createMemo(compute: ComputeFunction, Next>): Accessor; +export declare function createMemo(compute: ComputeFunction, value: Init, options?: MemoOptions): Accessor; +/** + * Creates a readonly derived async reactive memoized signal + * ```typescript + * export function createAsync( + * compute: (v: T) => Promise | T, + * value?: T, + * options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } + * ): () => T; + * ``` + * @param compute a function that receives its previous or the initial value, if set, and returns a new value used to react on a computation + * @param value an optional initial value for the computation; if set, fn will never receive undefined as first argument + * @param options allows to set a name in dev mode for debugging purposes and use a custom comparison function in equals + * + * @description https://docs.solidjs.com/reference/basic-reactivity/create-async + */ +export declare function createAsync(compute: (prev: T | undefined, refreshing: boolean) => Promise | AsyncIterable | T, value?: T, options?: MemoOptions): Accessor & { + refresh: () => void; +}; +/** + * Creates a reactive effect that runs after the render phase + * ```typescript + * export function createEffect( + * compute: (prev: T) => T, + * effect: (v: T, prev: T) => (() => void) | void, + * value?: T, + * options?: { name?: string } + * ): void; + * ``` + * @param compute a function that receives its previous or the initial value, if set, and returns a new value used to react on a computation + * @param effect a function that receives the new value and is used to perform side effects, return a cleanup function to run on disposal + * @param error an optional function that receives an error if thrown during the computation + * @param value an optional initial value for the computation; if set, fn will never receive undefined as first argument + * @param options allows to set a name in dev mode for debugging purposes + * + * @description https://docs.solidjs.com/reference/basic-reactivity/create-effect + */ +export declare function createEffect(compute: ComputeFunction, Next>, effect: EffectFunction, Next> | EffectBundle, Next>): void; +export declare function createEffect(compute: ComputeFunction, effect: EffectFunction | EffectBundle, value: Init, options?: EffectOptions): void; +/** + * Creates a reactive computation that runs during the render phase as DOM elements are created and updated but not necessarily connected + * ```typescript + * export function createRenderEffect( + * compute: (prev: T) => T, + * effect: (v: T, prev: T) => (() => void) | void, + * value?: T, + * options?: { name?: string } + * ): void; + * ``` + * @param compute a function that receives its previous or the initial value, if set, and returns a new value used to react on a computation + * @param effect a function that receives the new value and is used to perform side effects + * @param value an optional initial value for the computation; if set, fn will never receive undefined as first argument + * @param options allows to set a name in dev mode for debugging purposes + * + * @description https://docs.solidjs.com/reference/secondary-primitives/create-render-effect + */ +export declare function createRenderEffect(compute: ComputeFunction, Next>, effect: EffectFunction, Next>): void; +export declare function createRenderEffect(compute: ComputeFunction, effect: EffectFunction, value: Init, options?: EffectOptions): void; +/** + * Creates a new non-tracked reactive context with manual disposal + * + * @param fn a function in which the reactive state is scoped + * @returns the output of `fn`. + * + * @description https://docs.solidjs.com/reference/reactive-utilities/create-root + */ +export declare function createRoot(init: ((dispose: () => void) => T) | (() => T), options?: { + id: string; +}): T; +/** + * Runs the given function in the given owner to move ownership of nested primitives and cleanups. + * This method untracks the current scope. + * + * Warning: Usually there are simpler ways of modeling a problem that avoid using this function + */ +export declare function runWithOwner(owner: Owner | null, run: () => T): T; +/** + * Returns a promise of the resolved value of a reactive expression + * @param fn a reactive expression to resolve + */ +export declare function resolve(fn: () => T): Promise; +/** Allows the user to mark a state change as non-urgent. + * + * @see {@link https://docs.solidjs.com/reference/advanced-reactivity/transition} + * + * @returns A tuple containing an accessor for the pending state and a function to start a transition. + */ +export declare function useTransition(): [ + get: Accessor, + start: (fn: (resume: (fn: () => any | Promise) => void) => any | Promise | Iterable) => void +]; +/** + * Creates an optimistic store that can be used to optimistically update a value + * and then revert it back to the previous value at end of transition. + * ```typescript + * export function createOptimistic( + * fn: (store: T) => void, + * initial: T, + * options?: { key?: string | ((item: NonNullable) => any); all?: boolean } + * ): [get: Store, set: StoreSetter]; + * ``` + * @param fn a function that receives the current store and can be used to mutate it directly inside a transition + * @param initial The initial value of the signal. + * @param options Optional signal options. + * + * @returns A tuple containing an accessor for the current value and a setter function to apply changes. + */ +export declare function createOptimistic(initial: T | Store): [get: Store, set: StoreSetter]; +export declare function createOptimistic(fn: (store: T) => void, initial: T | Store, options?: { + key?: string | ((item: NonNullable) => any); + all?: boolean; +}): [get: Store, set: StoreSetter]; diff --git a/packages/solidjs-signals/0.6.3/dist/types/store/index.d.ts b/packages/solidjs-signals/0.6.3/dist/types/store/index.d.ts new file mode 100644 index 000000000..faa557495 --- /dev/null +++ b/packages/solidjs-signals/0.6.3/dist/types/store/index.d.ts @@ -0,0 +1,6 @@ +export type { Store, StoreSetter, StoreNode, NotWrappable, SolidStore } from "./store.js"; +export type { Merge, Omit } from "./utils.js"; +export { isWrappable, createStore, deep, $TRACK, $PROXY, $TARGET } from "./store.js"; +export { createProjection } from "./projection.js"; +export { reconcile } from "./reconcile.js"; +export { snapshot, merge, omit } from "./utils.js"; diff --git a/packages/solidjs-signals/0.6.3/dist/types/store/projection.d.ts b/packages/solidjs-signals/0.6.3/dist/types/store/projection.d.ts new file mode 100644 index 000000000..188db4455 --- /dev/null +++ b/packages/solidjs-signals/0.6.3/dist/types/store/projection.d.ts @@ -0,0 +1,7 @@ +import { type Store, type StoreOptions } from "./store.js"; +/** + * Creates a mutable derived value + * + * @see {@link https://github.com/solidjs/x-reactivity#createprojection} + */ +export declare function createProjection(fn: (draft: T) => void | T, initialValue?: T, options?: StoreOptions): Store; diff --git a/packages/solidjs-signals/0.6.3/dist/types/store/reconcile.d.ts b/packages/solidjs-signals/0.6.3/dist/types/store/reconcile.d.ts new file mode 100644 index 000000000..01effdba8 --- /dev/null +++ b/packages/solidjs-signals/0.6.3/dist/types/store/reconcile.d.ts @@ -0,0 +1 @@ +export declare function reconcile(value: T, key: string | ((item: NonNullable) => any), all?: boolean): (state: U) => void; diff --git a/packages/solidjs-signals/0.6.3/dist/types/store/store.d.ts b/packages/solidjs-signals/0.6.3/dist/types/store/store.d.ts new file mode 100644 index 000000000..69e129368 --- /dev/null +++ b/packages/solidjs-signals/0.6.3/dist/types/store/store.d.ts @@ -0,0 +1,37 @@ +import { Computation } from "../core/index.js"; +export type Store = Readonly; +export type StoreSetter = (fn: (state: T) => T | void) => void; +export type StoreOptions = { + key?: string | ((item: NonNullable) => any); + all?: boolean; +}; +type DataNode = Computation; +type DataNodes = Record; +export declare const $TRACK: unique symbol, $DEEP: unique symbol, $TARGET: unique symbol, $PROXY: unique symbol, $DELETED: unique symbol; +export declare const STORE_VALUE = "v", STORE_OVERRIDE = "o", STORE_NODE = "n", STORE_HAS = "h", STORE_WRAP = "w", STORE_LOOKUP = "l"; +export type StoreNode = { + [$PROXY]: any; + [STORE_VALUE]: Record; + [STORE_OVERRIDE]?: Record; + [STORE_NODE]?: DataNodes; + [STORE_HAS]?: DataNodes; + [STORE_WRAP]?: (value: any, target?: StoreNode) => any; + [STORE_LOOKUP]?: WeakMap; +}; +export declare namespace SolidStore { + interface Unwrappable { + } +} +export type NotWrappable = string | number | bigint | symbol | boolean | Function | null | undefined | SolidStore.Unwrappable[keyof SolidStore.Unwrappable]; +export declare function createStoreProxy(value: T, traps?: ProxyHandler, extend?: Record): any; +export declare const storeLookup: WeakMap; +export declare function wrap>(value: T, target?: StoreNode): T; +export declare function isWrappable(obj: T | NotWrappable): obj is T; +export declare function getKeys(source: Record, override: Record | undefined, enumerable?: boolean): PropertyKey[]; +export declare function getPropertyDescriptor(source: Record, override: Record | undefined, property: PropertyKey): PropertyDescriptor | undefined; +export declare const storeTraps: ProxyHandler; +export declare function storeSetter(store: Store, fn: (draft: T) => T | void): void; +export declare function createStore(store: T | Store): [get: Store, set: StoreSetter]; +export declare function createStore(fn: (store: T) => void, store: T | Store, options?: StoreOptions): [get: Store, set: StoreSetter]; +export declare function deep(store: Store): Store; +export {}; diff --git a/packages/solidjs-signals/0.6.3/dist/types/store/utils.d.ts b/packages/solidjs-signals/0.6.3/dist/types/store/utils.d.ts new file mode 100644 index 000000000..42e497e15 --- /dev/null +++ b/packages/solidjs-signals/0.6.3/dist/types/store/utils.d.ts @@ -0,0 +1,36 @@ +/** + * Returns a non reactive copy of the store object. + * It will attempt to preserver the original reference unless the value has been modified. + * @param item store proxy object + */ +export declare function snapshot(item: T): T; +export declare function snapshot(item: T, map?: Map, lookup?: WeakMap): T; +type DistributeOverride = T extends undefined ? F : T; +type Override = T extends any ? U extends any ? { + [K in keyof T]: K extends keyof U ? DistributeOverride : T[K]; +} & { + [K in keyof U]: K extends keyof T ? DistributeOverride : U[K]; +} : T & U : T & U; +type OverrideSpread = T extends any ? { + [K in keyof ({ + [K in keyof T]: any; + } & { + [K in keyof U]?: any; + } & { + [K in U extends any ? keyof U : keyof U]?: any; + })]: K extends keyof T ? Exclude | T[K] : U extends any ? U[K & keyof U] : never; +} : T & U; +type Simplify = T extends any ? { + [K in keyof T]: T[K]; +} : T; +type _Merge = T extends [ + infer Next | (() => infer Next), + ...infer Rest +] ? _Merge> : T extends [...infer Rest, infer Next | (() => infer Next)] ? Override<_Merge, Next> : T extends [] ? Curr : T extends (infer I | (() => infer I))[] ? OverrideSpread : Curr; +export type Merge = Simplify<_Merge>; +export declare function merge(...sources: T): Merge; +export type Omit = { + [P in keyof T as Exclude]: T[P]; +}; +export declare function omit, K extends readonly (keyof T)[]>(props: T, ...keys: K): Omit; +export {}; diff --git a/websites/packages/solidjs-signals/index.js b/packages/solidjs-signals/index.js similarity index 100% rename from websites/packages/solidjs-signals/index.js rename to packages/solidjs-signals/index.js diff --git a/websites/packages/tsconfig.json b/packages/tsconfig.json similarity index 82% rename from websites/packages/tsconfig.json rename to packages/tsconfig.json index 22f948246..cfe38122e 100644 --- a/websites/packages/tsconfig.json +++ b/packages/tsconfig.json @@ -9,5 +9,5 @@ "lib": ["DOM", "DOM.Iterable", "ESNext", "WebWorker"], "skipLibCheck": true }, - "exclude": ["scripts/packages", "scripts/bridge"] + "exclude": ["dist"] } diff --git a/websites/packages/unpkg.sh b/packages/unpkg.sh similarity index 100% rename from websites/packages/unpkg.sh rename to packages/unpkg.sh diff --git a/websites/packages/brk/.gitignore b/websites/packages/brk/.gitignore deleted file mode 100644 index f11b74313..000000000 --- a/websites/packages/brk/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -pools.js -metrics.js diff --git a/websites/packages/brk/serde.js b/websites/packages/brk/serde.js deleted file mode 100644 index c467a87fa..000000000 --- a/websites/packages/brk/serde.js +++ /dev/null @@ -1,64 +0,0 @@ -// Should be generated by server -export const serdeIndex = { - /** - * @param {Index} v - */ - serialize(v) { - switch (v) { - case /** @satisfies {DateIndex} */ (0): - return "dateindex"; - case /** @satisfies {DecadeIndex} */ (1): - return "decadeindex"; - case /** @satisfies {DifficultyEpoch} */ (2): - return "difficultyepoch"; - case /** @satisfies {EmptyOutputIndex} */ (3): - return "emptyoutputindex"; - case /** @satisfies {HalvingEpoch} */ (4): - return "halvingepoch"; - case /** @satisfies {Height} */ (5): - return "height"; - case /** @satisfies {InputIndex} */ (6): - return "inputindex"; - case /** @satisfies {MonthIndex} */ (7): - return "monthindex"; - case /** @satisfies {OpReturnIndex} */ (8): - return "opreturnindex"; - case /** @satisfies {OutputIndex} */ (9): - return "outputindex"; - case /** @satisfies {P2AAddressIndex} */ (10): - return "p2aaddressindex"; - case /** @satisfies {P2MSOutputIndex} */ (11): - return "p2msoutputindex"; - case /** @satisfies {P2PK33AddressIndex} */ (12): - return "p2pk33addressindex"; - case /** @satisfies {P2PK65AddressIndex} */ (13): - return "p2pk65addressindex"; - case /** @satisfies {P2PKHAddressIndex} */ (14): - return "p2pkhaddressindex"; - case /** @satisfies {P2SHAddressIndex} */ (15): - return "p2shaddressindex"; - case /** @satisfies {P2TRAddressIndex} */ (16): - return "p2traddressindex"; - case /** @satisfies {P2WPKHAddressIndex} */ (17): - return "p2wpkhaddressindex"; - case /** @satisfies {P2WSHAddressIndex} */ (18): - return "p2wshaddressindex"; - case /** @satisfies {QuarterIndex} */ (19): - return "quarterindex"; - case /** @satisfies {SemesterIndex} */ (20): - return "semesterindex"; - case /** @satisfies {TxIndex} */ (21): - return "txindex"; - case /** @satisfies {UnknownOutputIndex} */ (22): - return "unknownoutputindex"; - case /** @satisfies {WeekIndex} */ (23): - return "weekindex"; - case /** @satisfies {YearIndex} */ (24): - return "yearindex"; - case /** @satisfies {LoadedAddressIndex} */ (25): - return "loadedaddressindex"; - case /** @satisfies {EmptyAddressIndex} */ (26): - return "emptyaddressindex"; - } - }, -}; diff --git a/websites/packages/brk/types.js b/websites/packages/brk/types.js deleted file mode 100644 index e3dce8294..000000000 --- a/websites/packages/brk/types.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - * @import { Signal, Signals, Accessor } from "../solidjs-signals/index"; - * - * @import { DateIndex, DecadeIndex, DifficultyEpoch, Index, HalvingEpoch, Height, MonthIndex, P2PK33AddressIndex, P2PK65AddressIndex, P2PKHAddressIndex, P2SHAddressIndex, P2MSOutputIndex, P2AAddressIndex, P2TRAddressIndex, P2WPKHAddressIndex, P2WSHAddressIndex, TxIndex, InputIndex, OutputIndex, WeekIndex, SemesterIndex, YearIndex, MetricToIndexes, QuarterIndex, EmptyOutputIndex, OpReturnIndex, UnknownOutputIndex, EmptyAddressIndex, LoadedAddressIndex } from "./metrics" - * - * @typedef {[number, number, number, number]} OHLCTuple - * - * @typedef {any} Metric - */