diff --git a/Cargo.lock b/Cargo.lock index 21d83443..d3259a38 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,24 +4,18 @@ version = 4 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ "gimli", ] -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aes" @@ -36,12 +30,12 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", - "getrandom", + "getrandom 0.3.3", "once_cell", "version_check", "zerocopy", @@ -58,15 +52,15 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7e1758e5d759c0114140152ae72032eafcfdd7b599e995ebbc8eeafa2b4c977" +checksum = "59febb24956a41c29bb5f450978fbe825bd6456b3f80586c8bd558dc882e7b6a" dependencies = [ "alloy-consensus", "alloy-contract", @@ -91,19 +85,20 @@ dependencies = [ [[package]] name = "alloy-chains" -version = "0.1.27" +version = "0.1.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b515e82c8468ddb6ff8db21c78a5997442f113fd8471fd5b2261b2602dd0c67" +checksum = "28e2652684758b0d9b389d248b209ed9fd9989ef489a550265fe4bb8454fe7eb" dependencies = [ + "alloy-primitives", "num_enum", "strum", ] [[package]] name = "alloy-consensus" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a205d0cbb7bfdf9f4fd4b0ec842bc4c5f926e8c14ec3072d3fd75dd363baf1e0" +checksum = "e88e1edea70787c33e11197d3f32ae380f3db19e6e061e539a5bcf8184a6b326" dependencies = [ "alloy-eips", "alloy-primitives", @@ -112,15 +107,15 @@ dependencies = [ "alloy-trie", "auto_impl", "c-kzg", - "derive_more", + "derive_more 1.0.0", "serde", ] [[package]] name = "alloy-consensus-any" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993c34090a3f281cb746fd1604520cf21f8407ffbeb006aaa34c0556bffa718e" +checksum = "57b1bb53f40c0273cd1975573cd457b39213e68584e36d1401d25fd0398a1d65" dependencies = [ "alloy-consensus", "alloy-eips", @@ -132,9 +127,9 @@ dependencies = [ [[package]] name = "alloy-contract" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aec7945dff98ba68489aa6da455bf66f6c0fee8157df06747fbae7cb03c368e2" +checksum = "1b668c78c4b1f12f474ede5a85e8ce550d0aa1ef7d49fd1d22855a43b960e725" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -148,14 +143,14 @@ dependencies = [ "alloy-transport", "futures", "futures-util", - "thiserror 2.0.7", + "thiserror 2.0.17", ] [[package]] name = "alloy-core" -version = "0.8.15" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c618bd382f0bc2ac26a7e4bfae01c9b015ca8f21b37ca40059ae35a7e62b3dc6" +checksum = "9d8bcce99ad10fe02640cfaec1c6bc809b837c783c1d52906aa5af66e2a196f6" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -166,9 +161,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "0.8.15" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41056bde53ae10ffbbf11618efbe1e0290859e5eab0fe9ef82ebdb62f12a866f" +checksum = "eb8e762aefd39a397ff485bc86df673465c4ad3ec8819cc60833a8a3ba5cdc87" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -178,7 +173,7 @@ dependencies = [ "itoa", "serde", "serde_json", - "winnow 0.6.18", + "winnow", ] [[package]] @@ -200,15 +195,15 @@ checksum = "4c986539255fb839d1533c128e190e557e52ff652c9ef62939e233a81dd93f7e" dependencies = [ "alloy-primitives", "alloy-rlp", - "derive_more", + "derive_more 1.0.0", "serde", ] [[package]] name = "alloy-eips" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1d9907c29ce622946759bf4fd3418166bfeae76c1c544b8081c7be3acd9b4be" +checksum = "5f9fadfe089e9ccc0650473f2d4ef0a28bc015bbca5631d9f0f09e49b557fdb3" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -216,7 +211,7 @@ dependencies = [ "alloy-rlp", "alloy-serde", "c-kzg", - "derive_more", + "derive_more 1.0.0", "once_cell", "serde", "sha2", @@ -224,9 +219,9 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f13f7405a8eb8021258994ed1beab490c3e509ebbe2c18e1c24ae10749d56b" +checksum = "2b2a4cf7b70f3495788e74ce1c765260ffe38820a2a774ff4aacb62e31ea73f9" dependencies = [ "alloy-primitives", "alloy-serde", @@ -236,9 +231,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "0.8.15" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c357da577dfb56998d01f574d81ad7a1958d248740a7981b205d69d65a7da404" +checksum = "fe6beff64ad0aa6ad1019a3db26fef565aefeb011736150ab73ed3366c3cfd1b" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -248,23 +243,23 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39a786ce6bc7539dc30cabac6b7875644247c9e7d780e71a9f254d42ebdc013c" +checksum = "e29040b9d5fe2fb70415531882685b64f8efd08dfbd6cc907120650504821105" dependencies = [ "alloy-primitives", "alloy-sol-types", "serde", "serde_json", - "thiserror 2.0.7", + "thiserror 2.0.17", "tracing", ] [[package]] name = "alloy-network" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99051f82f77159d5bee06108f33cffee02849e2861fc500bf74213aa2ae8a26e" +checksum = "510cc00b318db0dfccfdd2d032411cfae64fc144aef9679409e014145d3dacc4" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -282,14 +277,14 @@ dependencies = [ "futures-utils-wasm", "serde", "serde_json", - "thiserror 2.0.7", + "thiserror 2.0.17", ] [[package]] name = "alloy-network-primitives" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2aff127863f8279921397be8af0ac3f05a8757d5c4c972b491c278518fa07c7" +checksum = "9081c099e798b8a2bba2145eb82a9a146f01fc7a35e9ab6e7b43305051f97550" dependencies = [ "alloy-consensus", "alloy-eips", @@ -300,25 +295,24 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.8.15" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6259a506ab13e1d658796c31e6e39d2e2ee89243bcc505ddc613b35732e0a430" +checksum = "8c77490fe91a0ce933a1f219029521f20fc28c2c0ca95d53fa4da9c00b8d9d4e" dependencies = [ "alloy-rlp", "bytes", "cfg-if", "const-hex", - "derive_more", + "derive_more 2.0.1", "foldhash", - "hashbrown 0.15.2", - "hex-literal", + "hashbrown 0.15.5", "indexmap", "itoa", "k256", "keccak-asm", "paste", "proptest", - "rand", + "rand 0.8.5", "ruint", "rustc-hash", "serde", @@ -328,9 +322,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0280a4f68e0cefde9449ee989a248230efbe3f95255299d2a7a92009e154629d" +checksum = "dc2dfaddd9a30aa870a78a4e1316e3e115ec1e12e552cbc881310456b85c1f24" dependencies = [ "alloy-chains", "alloy-consensus", @@ -358,7 +352,7 @@ dependencies = [ "schnellru", "serde", "serde_json", - "thiserror 2.0.7", + "thiserror 2.0.17", "tokio", "tracing", "url", @@ -367,9 +361,9 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9475dc1a835bd8bb77275b6bccf8e177e7e669ba81277ce6bea0016ce994fafe" +checksum = "695809e743628d54510c294ad17a4645bd9f465aeb0d20ee9ce9877c9712dc9c" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -380,15 +374,15 @@ dependencies = [ "serde_json", "tokio", "tokio-stream", - "tower 0.5.2", + "tower", "tracing", ] [[package]] name = "alloy-rlp" -version = "0.3.10" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f542548a609dca89fcd72b3b9f355928cf844d4363c5eed9c5273a3dd225e097" +checksum = "5f70d83b765fdc080dbcd4f4db70d8d23fe4761f2f02ebfa9146b833900634b4" dependencies = [ "alloy-rlp-derive", "arrayvec", @@ -397,20 +391,20 @@ dependencies = [ [[package]] name = "alloy-rlp-derive" -version = "0.3.10" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a833d97bf8a5f0f878daf2c8451fff7de7f9de38baa5a45d936ec718d81255a" +checksum = "64b728d511962dda67c1bc7ea7c03736ec275ed2cf4c35d9585298ac9ccf3b73" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", ] [[package]] name = "alloy-rpc-client" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fc8b0f68619cfab3a2e15dca7b80ab266f78430bb4353dec546528e04b7449" +checksum = "531137b283547d5b9a5cafc96b006c64ef76810c681d606f28be9781955293b6" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -425,7 +419,7 @@ dependencies = [ "serde_json", "tokio", "tokio-stream", - "tower 0.5.2", + "tower", "tracing", "url", "wasmtimer", @@ -433,9 +427,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "986f23fe42ac95832901a24b93c20f7ed2b9644394c02b86222801230da60041" +checksum = "3410a472ce26c457e9780f708ee6bd540b30f88f1f31fdab7a11d00bd6aa1aee" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -445,9 +439,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57e3aa433d3657b42e98e257ee6fa201f5c853245648a33da8fbb7497a5008bf" +checksum = "ed98e1af55a7d856bfa385f30f63d8d56be2513593655c904a8f4a7ec963aa3e" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", @@ -456,9 +450,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0643cc497a71941f526454fe4fecb47e9307d3a7b6c05f70718a0341643bcc79" +checksum = "8737d7a6e37ca7bba9c23e9495c6534caec6760eb24abc9d5ffbaaba147818e1" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -468,7 +462,7 @@ dependencies = [ "alloy-rlp", "alloy-serde", "alloy-sol-types", - "derive_more", + "derive_more 1.0.0", "itertools 0.13.0", "serde", "serde_json", @@ -476,9 +470,9 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61b049d7ecc66a29f107970dae493d0908e366048f7484a1ca9b02c85f9b2b" +checksum = "5851bf8d5ad33014bd0c45153c603303e730acc8a209450a7ae6b4a12c2789e2" dependencies = [ "alloy-primitives", "serde", @@ -487,23 +481,23 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93461b0e79c2ddd791fec5f369ab5c2686a33bbb03530144972edf5248f8a2c7" +checksum = "7e10ca565da6500cca015ba35ee424d59798f2e1b85bc0dd8f81dafd401f029a" dependencies = [ "alloy-primitives", "async-trait", "auto_impl", "elliptic-curve", "k256", - "thiserror 2.0.7", + "thiserror 2.0.17", ] [[package]] name = "alloy-signer-ledger" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1ddc0349b2445b9d7821b4d361759b29b72a1ee48fb2601fa47532fbe1ee51" +checksum = "08367716d2eee6f15f0f7ee2e855decbfedd12be12fe5f490a2d2717deda95bf" dependencies = [ "alloy-consensus", "alloy-network", @@ -512,16 +506,16 @@ dependencies = [ "async-trait", "coins-ledger", "futures-util", - "semver 1.0.23", - "thiserror 2.0.7", + "semver 1.0.27", + "thiserror 2.0.17", "tracing", ] [[package]] name = "alloy-signer-local" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f08ec1bfa433f9e9f7c5af05af07e5cf86d27d93170de76b760e63b925f1c9c" +checksum = "47fababf5a745133490cde927d48e50267f97d3d1209b9fc9f1d1d666964d172" dependencies = [ "alloy-consensus", "alloy-network", @@ -530,46 +524,46 @@ dependencies = [ "async-trait", "eth-keystore", "k256", - "rand", - "thiserror 2.0.7", + "rand 0.8.5", + "thiserror 2.0.17", ] [[package]] name = "alloy-signer-trezor" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9c93d03376fd16c960d022954d2ccefbdb82357324b323bc1690823fda7906d" +checksum = "cfbd920ad5dc03e1904827d30fd2ed874968c33885e254b2c2f59503b33e4bb8" dependencies = [ "alloy-consensus", "alloy-network", "alloy-primitives", "alloy-signer", "async-trait", - "semver 1.0.23", - "thiserror 2.0.7", + "semver 1.0.27", + "thiserror 2.0.17", "tracing", "trezor-client", ] [[package]] name = "alloy-sol-macro" -version = "0.8.15" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9d64f851d95619233f74b310f12bcf16e0cbc27ee3762b6115c14a84809280a" +checksum = "e10ae8e9a91d328ae954c22542415303919aabe976fe7a92eb06db1b68fd59f2" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", ] [[package]] name = "alloy-sol-macro-expander" -version = "0.8.15" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bf7ed1574b699f48bf17caab4e6e54c6d12bc3c006ab33d58b1e227c1c3559f" +checksum = "83ad5da86c127751bc607c174d6c9fe9b85ef0889a9ca0c641735d77d4f98f26" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", @@ -579,43 +573,44 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", "syn-solidity", "tiny-keccak", ] [[package]] name = "alloy-sol-macro-input" -version = "0.8.15" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c02997ccef5f34f9c099277d4145f183b422938ed5322dc57a089fe9b9ad9ee" +checksum = "ba3d30f0d3f9ba3b7686f3ff1de9ee312647aac705604417a2f40c604f409a9e" dependencies = [ "alloy-json-abi", "const-hex", "dunce", "heck", + "macro-string", "proc-macro2", "quote", "serde_json", - "syn 2.0.90", + "syn 2.0.106", "syn-solidity", ] [[package]] name = "alloy-sol-type-parser" -version = "0.8.15" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce13ff37285b0870d0a0746992a4ae48efaf34b766ae4c2640fa15e5305f8e73" +checksum = "6d162f8524adfdfb0e4bd0505c734c985f3e2474eb022af32eef0d52a4f3935c" dependencies = [ "serde", - "winnow 0.6.18", + "winnow", ] [[package]] name = "alloy-sol-types" -version = "0.8.15" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1174cafd6c6d810711b4e00383037bdb458efc4fe3dbafafa16567e0320c54d8" +checksum = "d43d5e60466a440230c07761aa67671d4719d46f43be8ea6e7ed334d8db4a9ab" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -626,9 +621,9 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf656f983e14812df65b5aee37e7b37535f68a848295e6ed736b2054a405cb7" +checksum = "538a04a37221469cac0ce231b737fd174de2fdfcdd843bdd068cb39ed3e066ad" dependencies = [ "alloy-json-rpc", "base64 0.22.1", @@ -636,9 +631,9 @@ dependencies = [ "futures-utils-wasm", "serde", "serde_json", - "thiserror 2.0.7", + "thiserror 2.0.17", "tokio", - "tower 0.5.2", + "tower", "tracing", "url", "wasmtimer", @@ -646,24 +641,24 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec938d51a47b7953b1c0fd8ddeb89a29eb113cd4908dfc4e01c7893b252d669f" +checksum = "2ed40eb1e1265b2911512f6aa1dcece9702d078f5a646730c45e39e2be00ac1c" dependencies = [ "alloy-json-rpc", "alloy-transport", "reqwest", "serde_json", - "tower 0.5.2", + "tower", "tracing", "url", ] [[package]] name = "alloy-transport-ws" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fabdf2d18c0c87b6cfcf6a067f1d5a7db378f103faeb16130d6d174c73d006b" +checksum = "fba0e39d181d13c266dbb8ca54ed584a2c66d6e9279afca89c7a6b1825e98abb" dependencies = [ "alloy-pubsub", "alloy-transport", @@ -679,26 +674,20 @@ dependencies = [ [[package]] name = "alloy-trie" -version = "0.7.6" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a5fd8fea044cc9a8c8a50bb6f28e31f0385d820f116c5b98f6f4e55d6e5590b" +checksum = "d95a94854e420f07e962f7807485856cde359ab99ab6413883e15235ad996e8b" dependencies = [ "alloy-primitives", "alloy-rlp", "arrayvec", - "derive_more", + "derive_more 1.0.0", "nybbles", "serde", "smallvec", "tracing", ] -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - [[package]] name = "android_system_properties" version = "0.1.5" @@ -710,9 +699,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -725,43 +714,44 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "once_cell_polyfill", + "windows-sys 0.60.2", ] [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "ark-ff" @@ -797,7 +787,27 @@ dependencies = [ "num-bigint", "num-traits", "paste", - "rustc_version 0.4.0", + "rustc_version 0.4.1", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" +dependencies = [ + "ark-ff-asm 0.5.0", + "ark-ff-macros 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "arrayvec", + "digest 0.10.7", + "educe", + "itertools 0.13.0", + "num-bigint", + "num-traits", + "paste", "zeroize", ] @@ -821,6 +831,16 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ark-ff-asm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" +dependencies = [ + "quote", + "syn 2.0.106", +] + [[package]] name = "ark-ff-macros" version = "0.3.0" @@ -846,6 +866,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ark-ff-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "ark-serialize" version = "0.3.0" @@ -867,6 +900,18 @@ dependencies = [ "num-bigint", ] +[[package]] +name = "ark-serialize" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" +dependencies = [ + "ark-std 0.5.0", + "arrayvec", + "digest 0.10.7", + "num-bigint", +] + [[package]] name = "ark-std" version = "0.3.0" @@ -874,7 +919,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" dependencies = [ "num-traits", - "rand", + "rand 0.8.5", ] [[package]] @@ -884,7 +929,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ "num-traits", - "rand", + "rand 0.8.5", +] + +[[package]] +name = "ark-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" +dependencies = [ + "num-traits", + "rand 0.8.5", ] [[package]] @@ -898,9 +953,9 @@ dependencies = [ [[package]] name = "async-stream" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", @@ -909,24 +964,24 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", ] [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", ] [[package]] @@ -937,7 +992,7 @@ checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" dependencies = [ "futures", "pharos", - "rustc_version 0.4.0", + "rustc_version 0.4.1", ] [[package]] @@ -948,34 +1003,34 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "auto_impl" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", ] [[package]] name = "autocfg" -version = "1.3.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", - "miniz_oxide 0.7.4", + "miniz_oxide", "object", "rustc-demangle", + "windows-link 0.2.1", ] [[package]] @@ -998,9 +1053,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" [[package]] name = "bimap" @@ -1019,18 +1074,18 @@ dependencies = [ [[package]] name = "bit-set" -version = "0.5.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" dependencies = [ "bit-vec", ] [[package]] name = "bit-vec" -version = "0.6.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bitflags" @@ -1040,9 +1095,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" [[package]] name = "bitvec" @@ -1067,9 +1122,9 @@ dependencies = [ [[package]] name = "blst" -version = "0.3.13" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4378725facc195f1a538864863f6de233b500a8862747e7f165078a419d5e874" +checksum = "dcdb4c7013139a150f9fc55d123186dbfaba0d912817466282c73ac49e71fb45" dependencies = [ "cc", "glob", @@ -1079,15 +1134,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "byte-slice-cast" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" [[package]] name = "byteorder" @@ -1097,9 +1152,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" dependencies = [ "serde", ] @@ -1116,43 +1171,43 @@ dependencies = [ [[package]] name = "bzip2-sys" -version = "0.1.11+1.0.8" +version = "0.1.13+1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" dependencies = [ "cc", - "libc", "pkg-config", ] [[package]] name = "c-kzg" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf100c4cea8f207e883ff91ca886d621d8a166cb04971dfaa9bb8fd99ed95df" +checksum = "f0307f72feab3300336fb803a57134159f6e20139af1357f36c54cb90d8e8928" dependencies = [ "blst", "cc", "glob", "hex", "libc", + "once_cell", "serde", ] [[package]] name = "camino" -version = "1.1.9" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609" dependencies = [ - "serde", + "serde_core", ] [[package]] name = "cargo-platform" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" dependencies = [ "serde", ] @@ -1165,18 +1220,19 @@ checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" dependencies = [ "camino", "cargo-platform", - "semver 1.0.23", + "semver 1.0.27", "serde", "serde_json", - "thiserror 1.0.63", + "thiserror 1.0.69", ] [[package]] name = "cc" -version = "1.1.13" +version = "1.2.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" +checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" dependencies = [ + "find-msvc-tools", "jobserver", "libc", "shlex", @@ -1184,22 +1240,21 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ - "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] @@ -1214,18 +1269,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.16" +version = "4.5.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" +checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.15" +version = "4.5.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9" dependencies = [ "anstream", "anstyle", @@ -1235,9 +1290,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "coins-ledger" @@ -1249,13 +1304,13 @@ dependencies = [ "byteorder", "cfg-if", "const-hex", - "getrandom", + "getrandom 0.2.16", "hidapi-rusb", "js-sys", "log", "nix 0.26.4", "once_cell", - "thiserror 1.0.63", + "thiserror 1.0.69", "tokio", "tracing", "wasm-bindgen", @@ -1264,9 +1319,9 @@ dependencies = [ [[package]] name = "color-eyre" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" +checksum = "e5920befb47832a6d61ee3a3a846565cfa39b331331e68a3b1d1116630f2f26d" dependencies = [ "backtrace", "color-spantrace", @@ -1279,9 +1334,9 @@ dependencies = [ [[package]] name = "color-spantrace" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" +checksum = "b8b88ea9df13354b55bc7234ebcce36e6ef896aca2e42a15de9e10edce01b427" dependencies = [ "once_cell", "owo-colors", @@ -1291,21 +1346,20 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "const-hex" -version = "1.14.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0485bab839b018a8f1723fc5391819fea5f8f0f32288ef8a735fd096b6160c" +checksum = "b6407bff74dea37e0fa3dc1c1c974e5d46405f0c987bf9997a0762adce71eda6" dependencies = [ "cfg-if", "cpufeatures", - "hex", "proptest", - "serde", + "serde_core", ] [[package]] @@ -1314,6 +1368,26 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const_format" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -1338,42 +1412,42 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.13" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.13" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-bigint" @@ -1382,7 +1456,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", - "rand_core", + "rand_core 0.6.4", "subtle", "zeroize", ] @@ -1422,15 +1496,15 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.6.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] name = "der" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ "const-oid", "zeroize", @@ -1438,9 +1512,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.11" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071" dependencies = [ "powerfmt", ] @@ -1462,7 +1536,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" dependencies = [ - "derive_more-impl", + "derive_more-impl 1.0.0", +] + +[[package]] +name = "derive_more" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +dependencies = [ + "derive_more-impl 2.0.1", ] [[package]] @@ -1473,7 +1556,19 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", + "unicode-xid", +] + +[[package]] +name = "derive_more-impl" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", "unicode-xid", ] @@ -1519,6 +1614,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "dunce" version = "1.0.5" @@ -1539,11 +1645,23 @@ dependencies = [ "spki", ] +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "elliptic-curve" @@ -1558,7 +1676,7 @@ dependencies = [ "generic-array", "group", "pkcs8", - "rand_core", + "rand_core 0.6.4", "sec1", "subtle", "zeroize", @@ -1566,27 +1684,47 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] +[[package]] +name = "enum-ordinalize" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -1601,13 +1739,13 @@ dependencies = [ "hex", "hmac", "pbkdf2", - "rand", + "rand 0.8.5", "scrypt", "serde", "serde_json", "sha2", "sha3", - "thiserror 1.0.63", + "thiserror 1.0.69", "uuid", ] @@ -1623,9 +1761,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fastrlp" @@ -1638,16 +1776,33 @@ dependencies = [ "bytes", ] +[[package]] +name = "fastrlp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + [[package]] name = "ff" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ - "rand_core", + "rand_core 0.6.4", "subtle", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" + [[package]] name = "fixed-hash" version = "0.8.0" @@ -1655,19 +1810,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ "byteorder", - "rand", + "rand 0.8.5", "rustc-hex", "static_assertions", ] [[package]] name = "flate2" -version = "1.0.32" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c0596c1eac1f9e04ed902702e9878208b336edc9d6fddc8a48387349bab3666" +checksum = "dc5a4e564e38c699f2880d3fda590bedc2e69f3f84cd48b457bd892ce61d0aa9" dependencies = [ "crc32fast", - "miniz_oxide 0.8.0", + "miniz_oxide", ] [[package]] @@ -1678,9 +1833,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "foreign-types" @@ -1699,9 +1854,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -1723,9 +1878,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1738,9 +1893,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1748,15 +1903,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1765,38 +1920,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -1829,22 +1984,34 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.7+wasi-0.2.4", +] + [[package]] name = "gimli" -version = "0.28.1" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "git2" @@ -1852,7 +2019,7 @@ version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "232e6a7bfe35766bf715e55a88b39a700596c0ccfd88cd3680b4cdb40d66ef70" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.9.4", "libc", "libgit2-sys", "log", @@ -1863,9 +2030,9 @@ dependencies = [ [[package]] name = "glob" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "group" @@ -1874,15 +2041,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", - "rand_core", + "rand_core 0.6.4", "subtle", ] [[package]] name = "h2" -version = "0.4.6" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" dependencies = [ "atomic-waker", "bytes", @@ -1908,21 +2075,25 @@ name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", - "allocator-api2", -] [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ + "allocator-api2", + "equivalent", "foldhash", "serde", ] +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + [[package]] name = "heck" version = "0.5.0" @@ -1931,24 +2102,15 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.9" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -dependencies = [ - "serde", -] - -[[package]] -name = "hex-literal" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" [[package]] name = "hidapi-rusb" @@ -1973,9 +2135,9 @@ dependencies = [ [[package]] name = "http" -version = "1.1.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", @@ -1994,12 +2156,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", - "futures-util", + "futures-core", "http", "http-body", "pin-project-lite", @@ -2007,25 +2169,27 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "hyper" -version = "1.4.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" dependencies = [ + "atomic-waker", "bytes", "futures-channel", - "futures-util", + "futures-core", "h2", "http", "http-body", "httparse", "itoa", "pin-project-lite", + "pin-utils", "smallvec", "tokio", "want", @@ -2033,11 +2197,10 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.2" +version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "futures-util", "http", "hyper", "hyper-util", @@ -2066,29 +2229,35 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.7" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" dependencies = [ + "base64 0.22.1", "bytes", "futures-channel", + "futures-core", "futures-util", "http", "http-body", "hyper", + "ipnet", + "libc", + "percent-encoding", "pin-project-lite", "socket2", + "system-configuration", "tokio", - "tower 0.4.13", "tower-service", "tracing", + "windows-registry", ] [[package]] name = "hyperware_process_lib" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6be2438db0ae3a32f56bad480822df88fb01e201138d36ffd9faa8244e16f143" +checksum = "3f3abd008d22c3b96ee43300c4c8dffbf1d072a680a13635b5f9da11a0ce9395" dependencies = [ "alloy", "alloy-primitives", @@ -2097,28 +2266,31 @@ dependencies = [ "anyhow", "base64 0.22.1", "bincode", + "hex", "http", "mime_guess", - "rand", + "rand 0.8.5", "regex", "rmp-serde", "serde", "serde_json", - "thiserror 1.0.63", + "sha3", + "thiserror 1.0.69", "url", - "wit-bindgen", + "wit-bindgen 0.42.1", ] [[package]] name = "iana-time-zone" -version = "0.1.61" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", "windows-core", ] @@ -2132,6 +2304,92 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + [[package]] name = "id-arena" version = "2.2.1" @@ -2140,12 +2398,23 @@ checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" [[package]] name = "idna" -version = "0.5.0" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", ] [[package]] @@ -2159,46 +2428,68 @@ dependencies = [ [[package]] name = "impl-trait-for-tuples" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.106", ] [[package]] name = "indenter" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" +checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" [[package]] name = "indexmap" -version = "2.7.0" +version = "2.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown 0.16.0", "serde", + "serde_core", ] [[package]] name = "inout" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ "generic-array", ] +[[package]] +name = "io-uring" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" +dependencies = [ + "bitflags 2.9.4", + "cfg-if", + "libc", +] + [[package]] name = "ipnet" -version = "2.9.0" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] [[package]] name = "is_terminal_polyfill" @@ -2226,33 +2517,35 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jobserver" -version = "0.1.32" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ + "getrandom 0.3.3", "libc", ] [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" dependencies = [ + "once_cell", "wasm-bindgen", ] [[package]] name = "k256" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ "cfg-if", "ecdsa", @@ -2272,9 +2565,9 @@ dependencies = [ [[package]] name = "keccak-asm" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "422fbc7ff2f2f5bdffeb07718e5a5324dca72b0c9293d50df4026652385e3314" +checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" dependencies = [ "digest 0.10.7", "sha3-asm", @@ -2303,23 +2596,23 @@ dependencies = [ "regex", "reqwest", "rpassword", - "semver 1.0.23", + "semver 1.0.27", "serde", "serde_json", "sha2", "sha3", - "syn 2.0.90", + "syn 2.0.106", "tempfile", - "thiserror 1.0.63", + "thiserror 1.0.69", "tokio", "toml", - "toml_edit 0.22.20", + "toml_edit 0.22.27", "tracing", "tracing-appender", "tracing-error", "tracing-subscriber", "walkdir", - "wit-bindgen", + "wit-bindgen 0.42.1", "zip", ] @@ -2337,9 +2630,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libgit2-sys" @@ -2357,25 +2650,25 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.8" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.3" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.9.4", "libc", ] [[package]] name = "libssh2-sys" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc8a030b787e2119a731f1951d6a773e2280c660f8ec4b0f5e1505a386e71ee" +checksum = "220e4f05ad4a218192533b300327f5150e809b54c4ec83b5a1d91833601811b9" dependencies = [ "cc", "libc", @@ -2399,9 +2692,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.19" +version = "1.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc53a7799a7496ebc9fd29f31f7df80e83c9bda5299768af5f9e59eeea74647" +checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" dependencies = [ "cc", "libc", @@ -2411,49 +2704,65 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "litemap" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.22" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "lru" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.14.5", + "hashbrown 0.15.5", +] + +[[package]] +name = "macro-string" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", ] [[package]] name = "matchers" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ - "regex-automata 0.1.10", + "regex-automata", ] [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memoffset" @@ -2482,39 +2791,30 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - -[[package]] -name = "miniz_oxide" -version = "0.8.0" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", + "simd-adler32", ] [[package]] name = "mio" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ - "hermit-abi", "libc", - "wasi", - "windows-sys 0.52.0", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", ] [[package]] name = "native-tls" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" dependencies = [ "libc", "log", @@ -2546,19 +2846,18 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.9.4", "cfg-if", "libc", ] [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.50.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" dependencies = [ - "overload", - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -2598,9 +2897,9 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ "hermit-abi", "libc", @@ -2608,29 +2907,30 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" dependencies = [ "num_enum_derive", + "rustversion", ] [[package]] name = "num_enum_derive" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", ] [[package]] name = "nybbles" -version = "0.2.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95f06be0417d97f81fe4e5c86d7d01b392655a9cac9c19a848aa033e18937b23" +checksum = "8983bb634df7248924ee0c4c3a749609b5abcb082c28fffe3254b3eb3602b307" dependencies = [ "alloy-rlp", "const-hex", @@ -2641,26 +2941,32 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" [[package]] name = "openssl" -version = "0.10.66" +version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.9.4", "cfg-if", "foreign-types", "libc", @@ -2677,20 +2983,20 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", ] [[package]] name = "openssl-probe" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.103" +version = "0.9.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" dependencies = [ "cc", "libc", @@ -2704,49 +3010,45 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - [[package]] name = "owo-colors" -version = "3.5.0" +version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" [[package]] name = "parity-scale-codec" -version = "3.6.12" +version = "3.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" dependencies = [ "arrayvec", "bitvec", "byte-slice-cast", + "const_format", "impl-trait-for-tuples", "parity-scale-codec-derive", + "rustversion", "serde", ] [[package]] name = "parity-scale-codec-derive" -version = "3.6.12" +version = "3.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.106", ] [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -2754,15 +3056,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] @@ -2772,7 +3074,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" dependencies = [ "base64ct", - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -2796,18 +3098,17 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.7.11" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" +checksum = "989e7521a040efde50c3ab6bbadafbe15ab6dc042686926be59ac35d74607df4" dependencies = [ "memchr", - "thiserror 1.0.63", "ucd-trie", ] @@ -2818,34 +3119,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" dependencies = [ "futures", - "rustc_version 0.4.0", + "rustc_version 0.4.1", ] [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -2865,9 +3166,18 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "potential_utf" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +dependencies = [ + "zerovec", +] [[package]] name = "powerfmt" @@ -2877,21 +3187,21 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy", ] [[package]] name = "prettyplease" -version = "0.2.25" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.90", + "syn 2.0.106", ] [[package]] @@ -2907,11 +3217,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.1.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ - "toml_edit 0.21.1", + "toml_edit 0.23.7", ] [[package]] @@ -2933,33 +3243,33 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", ] [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] [[package]] name = "proptest" -version = "1.5.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" +checksum = "2bb0be07becd10686a0bb407298fb425360a5c44a663774406340c59a22de4ce" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.6.0", + "bitflags 2.9.4", "lazy_static", "num-traits", - "rand", - "rand_chacha", + "rand 0.9.2", + "rand_chacha 0.9.0", "rand_xorshift", - "regex-syntax 0.8.5", + "regex-syntax", "rusty-fork", "tempfile", "unarray", @@ -2973,7 +3283,7 @@ checksum = "b65f4a8ec18723a734e5dc09c173e0abf9690432da5340285d536edcb4dac190" dependencies = [ "once_cell", "protobuf-support", - "thiserror 1.0.63", + "thiserror 1.0.69", ] [[package]] @@ -2982,7 +3292,7 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6872f4d4f4b98303239a2b5838f5bbbb77b01ffc892d627957f37a22d7cfe69c" dependencies = [ - "thiserror 1.0.63", + "thiserror 1.0.69", ] [[package]] @@ -2993,13 +3303,19 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.36" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "radium" version = "0.7.0" @@ -3013,11 +3329,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", "serde", ] +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -3025,7 +3351,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", ] [[package]] @@ -3034,25 +3370,34 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", ] [[package]] name = "rand_xorshift" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" dependencies = [ - "rand_core", + "rand_core 0.9.3", ] [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.9.4", ] [[package]] @@ -3061,66 +3406,50 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom", + "getrandom 0.2.16", "libredox", - "thiserror 1.0.63", + "thiserror 1.0.69", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "8b5288124840bee7b386bc413c487869b360b2b4ec421ea56425128692f2a82c" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", + "regex-automata", + "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "833eb9ce86d40ef33cb1306d8accf7bc8ec2bfea4355cbdebb3df68b40925cad" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.5", + "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" [[package]] name = "reqwest" -version = "0.12.7" +version = "0.12.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" dependencies = [ "base64 0.22.1", "bytes", "encoding_rs", "futures-core", - "futures-util", "h2", "http", "http-body", @@ -3129,28 +3458,26 @@ dependencies = [ "hyper-rustls", "hyper-tls", "hyper-util", - "ipnet", "js-sys", "log", "mime", "native-tls", - "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", - "system-configuration", "tokio", "tokio-native-tls", + "tower", + "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "windows-registry", ] [[package]] @@ -3165,15 +3492,14 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.8" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom", + "getrandom 0.2.16", "libc", - "spin", "untrusted", "windows-sys 0.52.0", ] @@ -3212,45 +3538,49 @@ dependencies = [ [[package]] name = "rpassword" -version = "7.3.1" +version = "7.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80472be3c897911d0137b2d2b9055faf6eeac5b14e324073d83bc17b191d7e3f" +checksum = "66d4c8b64f049c6721ec8ccec37ddfc3d641c4a7fca57e8f2a89de509c73df39" dependencies = [ "libc", "rtoolbox", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "rtoolbox" -version = "0.0.2" +version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c247d24e63230cdb56463ae328478bd5eac8b8faa8c69461a77e8e323afac90e" +checksum = "a7cc970b249fbe527d6e02e0a227762c9108b2f49d81094fe357ffc6d14d7f6f" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "ruint" -version = "1.12.3" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c3cc4c2511671f327125da14133d0c5c5d137f006a1017a16f557bc85b16286" +checksum = "a68df0380e5c9d20ce49534f292a36a7514ae21350726efe1865bdb1fa91d278" dependencies = [ "alloy-rlp", "ark-ff 0.3.0", "ark-ff 0.4.2", + "ark-ff 0.5.0", "bytes", - "fastrlp", + "fastrlp 0.3.1", + "fastrlp 0.4.0", "num-bigint", + "num-integer", "num-traits", "parity-scale-codec", "primitive-types", "proptest", - "rand", + "rand 0.8.5", + "rand 0.9.2", "rlp", "ruint-macro", - "serde", + "serde_core", "valuable", "zeroize", ] @@ -3273,15 +3603,15 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] name = "rustc-hash" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustc-hex" @@ -3300,31 +3630,31 @@ dependencies = [ [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver 1.0.23", + "semver 1.0.27", ] [[package]] name = "rustix" -version = "0.38.34" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.9.4", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.12" +version = "0.23.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40" dependencies = [ "once_cell", "ring", @@ -3335,26 +3665,19 @@ dependencies = [ ] [[package]] -name = "rustls-pemfile" -version = "2.1.3" +name = "rustls-pki-types" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ - "base64 0.22.1", - "rustls-pki-types", + "zeroize", ] -[[package]] -name = "rustls-pki-types" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" - [[package]] name = "rustls-webpki" -version = "0.102.6" +version = "0.103.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +checksum = "e10b3f4191e8a80e6b43eebabfac91e5dcecebb27a71f04e820c47ec41d314bf" dependencies = [ "ring", "rustls-pki-types", @@ -3363,15 +3686,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "rusty-fork" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2" dependencies = [ "fnv", "quick-error", @@ -3381,9 +3704,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "salsa20" @@ -3405,18 +3728,18 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "schnellru" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9a8ef13a93c54d20580de1e5c413e624e53121d42fc7e2c11d10ef7f8b02367" +checksum = "356285bbf17bea63d9e52e96bd18f039672ac92b55b8cb997d6162a2a37d1649" dependencies = [ "ahash", "cfg-if", @@ -3461,7 +3784,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.9.4", "core-foundation", "core-foundation-sys", "libc", @@ -3470,9 +3793,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" dependencies = [ "core-foundation-sys", "libc", @@ -3489,18 +3812,19 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.23" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" dependencies = [ "serde", + "serde_core", ] [[package]] name = "semver-parser" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" dependencies = [ "pest", ] @@ -3513,41 +3837,52 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.208" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.208" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", ] [[package]] name = "serde_json" -version = "1.0.125" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] @@ -3577,9 +3912,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -3598,9 +3933,9 @@ dependencies = [ [[package]] name = "sha3-asm" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d79b758b7cb2085612b11a235055e485605a5103faccdd633f35bd7aee69dd" +checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" dependencies = [ "cc", "cfg-if", @@ -3623,9 +3958,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" dependencies = [ "libc", ] @@ -3637,43 +3972,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", - "rand_core", + "rand_core 0.6.4", ] +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "slab" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "smallvec" -version = "1.13.2" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" dependencies = [ "serde", ] [[package]] name = "socket2" -version = "0.5.7" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - [[package]] name = "spki" version = "0.7.3" @@ -3684,6 +4016,12 @@ dependencies = [ "der", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + [[package]] name = "static_assertions" version = "1.1.0" @@ -3698,24 +4036,23 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.26.3" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.26.4" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" dependencies = [ "heck", "proc-macro2", "quote", - "rustversion", - "syn 2.0.90", + "syn 2.0.106", ] [[package]] @@ -3737,9 +4074,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.90" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -3748,32 +4085,43 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.8.15" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219389c1ebe89f8333df8bdfb871f6631c552ff399c23cac02480b6088aad8f0" +checksum = "4560533fbd6914b94a8fb5cc803ed6801c3455668db3b810702c57612bac9412" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", ] [[package]] name = "sync_wrapper" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ "futures-core", ] [[package]] -name = "system-configuration" -version = "0.6.0" +name = "synstructure" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bc6ee10a9b4fcf576e9b0819d95ec16f4d2c02d39fd83ac1c8789785c4a42" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ - "bitflags 2.6.0", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.9.4", "core-foundation", "system-configuration-sys", ] @@ -3796,65 +4144,64 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.12.0" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ - "cfg-if", "fastrand", + "getrandom 0.3.3", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl 1.0.63", + "thiserror-impl 1.0.69", ] [[package]] name = "thiserror" -version = "2.0.7" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93605438cbd668185516ab499d589afb7ee1859ea3d5fc8f6b0755e1c7443767" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "thiserror-impl 2.0.7", + "thiserror-impl 2.0.17", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", ] [[package]] name = "thiserror-impl" -version = "2.0.7" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d8749b4531af2117677a5fcd12b1348a3fe2b81e36e61ffeac5c4aa3273e36" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", ] [[package]] name = "thread_local" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", - "once_cell", ] [[package]] @@ -3868,9 +4215,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" dependencies = [ "deranged", "itoa", @@ -3883,15 +4230,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.2" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" dependencies = [ "num-conv", "time-core", @@ -3907,46 +4254,43 @@ dependencies = [ ] [[package]] -name = "tinyvec" -version = "1.8.0" +name = "tinystr" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ - "tinyvec_macros", + "displaydoc", + "zerovec", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" -version = "1.39.3" +version = "1.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" +checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" dependencies = [ "backtrace", "bytes", + "io-uring", "libc", "mio", "pin-project-lite", "signal-hook-registry", + "slab", "socket2", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", ] [[package]] @@ -3961,20 +4305,19 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.0" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ "rustls", - "rustls-pki-types", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -3995,14 +4338,14 @@ dependencies = [ "tokio", "tokio-rustls", "tungstenite", - "webpki-roots", + "webpki-roots 0.26.11", ] [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" dependencies = [ "bytes", "futures-core", @@ -4013,74 +4356,104 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.19" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", - "toml_datetime", - "toml_edit 0.22.20", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", ] [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] [[package]] -name = "toml_edit" -version = "0.21.1" +name = "toml_datetime" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" dependencies = [ - "indexmap", - "toml_datetime", - "winnow 0.5.40", + "serde_core", ] [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", "serde", "serde_spanned", - "toml_datetime", - "winnow 0.6.18", + "toml_datetime 0.6.11", + "toml_write", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.23.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" +dependencies = [ + "indexmap", + "toml_datetime 0.7.3", + "toml_parser", + "winnow", ] +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + [[package]] name = "tower" -version = "0.4.13" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", - "pin-project", "pin-project-lite", + "sync_wrapper", "tokio", "tower-layer", "tower-service", ] [[package]] -name = "tower" -version = "0.5.2" +name = "tower-http" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" dependencies = [ - "futures-core", + "bitflags 2.9.4", + "bytes", "futures-util", + "http", + "http-body", + "iri-string", "pin-project-lite", - "sync_wrapper", + "tower", "tower-layer", "tower-service", ] @@ -4099,9 +4472,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", "tracing-attributes", @@ -4115,27 +4488,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" dependencies = [ "crossbeam-channel", - "thiserror 1.0.63", + "thiserror 1.0.69", "time", "tracing-subscriber", ] [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", "valuable", @@ -4143,9 +4516,9 @@ dependencies = [ [[package]] name = "tracing-error" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" dependencies = [ "tracing", "tracing-subscriber", @@ -4164,9 +4537,9 @@ dependencies = [ [[package]] name = "tracing-serde" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" dependencies = [ "serde", "tracing-core", @@ -4174,14 +4547,14 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" dependencies = [ "matchers", "nu-ansi-term", "once_cell", - "regex", + "regex-automata", "serde", "serde_json", "sharded-slab", @@ -4203,7 +4576,7 @@ dependencies = [ "hex", "protobuf", "rusb", - "thiserror 1.0.63", + "thiserror 1.0.69", "tracing", ] @@ -4225,25 +4598,25 @@ dependencies = [ "http", "httparse", "log", - "rand", + "rand 0.8.5", "rustls", "rustls-pki-types", "sha1", - "thiserror 1.0.63", + "thiserror 1.0.69", "utf-8", ] [[package]] name = "typenum" -version = "1.17.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "ucd-trie" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "uint" @@ -4265,39 +4638,21 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicase" -version = "2.7.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" [[package]] name = "unicode-xid" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "untrusted" @@ -4307,13 +4662,14 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -4322,6 +4678,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -4334,15 +4696,15 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom", + "getrandom 0.2.16", "serde", ] [[package]] name = "valuable" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "vcpkg" @@ -4358,9 +4720,9 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wait-timeout" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" dependencies = [ "libc", ] @@ -4386,53 +4748,73 @@ dependencies = [ [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasi" +version = "0.14.7+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" +dependencies = [ + "wasip2", +] + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen 0.46.0", +] [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" dependencies = [ "cfg-if", "once_cell", + "rustversion", "wasm-bindgen-macro", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.43" +version = "0.4.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4440,22 +4822,25 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +dependencies = [ + "unicode-ident", +] [[package]] name = "wasm-encoder" @@ -4485,17 +4870,17 @@ version = "0.230.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "808198a69b5a0535583370a51d459baa14261dfab04800c4864ee9e1a14346ed" dependencies = [ - "bitflags 2.6.0", - "hashbrown 0.15.2", + "bitflags 2.9.4", + "hashbrown 0.15.5", "indexmap", - "semver 1.0.23", + "semver 1.0.27", ] [[package]] name = "wasmtimer" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0048ad49a55b9deb3953841fa1fc5858f0efbcb7a18868c899a360269fac1b23" +checksum = "1c598d6b99ea013e35844697fc4670d08339d5cda15588f193c6beedd12f644b" dependencies = [ "futures", "js-sys", @@ -4507,9 +4892,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.70" +version = "0.3.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" dependencies = [ "js-sys", "wasm-bindgen", @@ -4517,81 +4902,123 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.3" +version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "rustls-pki-types", + "webpki-roots 1.0.3", ] [[package]] -name = "winapi" -version = "0.3.9" +name = "webpki-roots" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "32b130c0d2d49f8b6889abc456e795e82525204f27c42cf767cf0d7734e089b8" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "rustls-pki-types", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "winapi-util" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] [[package]] -name = "winapi-util" -version = "0.1.9" +name = "windows-core" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ - "windows-sys 0.59.0", + "windows-implement", + "windows-interface", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", ] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows-implement" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] [[package]] -name = "windows-core" -version = "0.52.0" +name = "windows-interface" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ - "windows-targets 0.52.6", + "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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-registry" -version = "0.2.0" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" dependencies = [ - "windows-result", - "windows-strings", - "windows-targets 0.52.6", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", ] [[package]] name = "windows-result" -version = "0.2.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-targets 0.52.6", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link 0.2.1", ] [[package]] name = "windows-strings" -version = "0.1.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-result", - "windows-targets 0.52.6", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link 0.2.1", ] [[package]] @@ -4621,6 +5048,24 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -4645,13 +5090,30 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -4664,6 +5126,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -4676,6 +5144,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -4688,12 +5162,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -4706,6 +5192,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -4718,6 +5210,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -4730,6 +5228,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -4743,19 +5247,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] -name = "winnow" -version = "0.5.40" +name = "windows_x86_64_msvc" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.6.18" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" dependencies = [ "memchr", ] @@ -4770,6 +5271,12 @@ dependencies = [ "wit-bindgen-rust-macro", ] +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + [[package]] name = "wit-bindgen-core" version = "0.42.1" @@ -4787,7 +5294,7 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "051105bab12bc78e161f8dfb3596e772dd6a01ebf9c4840988e00347e744966a" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.9.4", "futures", "once_cell", ] @@ -4802,7 +5309,7 @@ dependencies = [ "heck", "indexmap", "prettyplease", - "syn 2.0.90", + "syn 2.0.106", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -4818,7 +5325,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -4830,7 +5337,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b607b15ead6d0e87f5d1613b4f18c04d4e80ceeada5ffa608d8360e6909881df" dependencies = [ "anyhow", - "bitflags 2.6.0", + "bitflags 2.9.4", "indexmap", "log", "serde", @@ -4852,7 +5359,7 @@ dependencies = [ "id-arena", "indexmap", "log", - "semver 1.0.23", + "semver 1.0.27", "serde", "serde_derive", "serde_json", @@ -4860,20 +5367,26 @@ dependencies = [ "wasmparser", ] +[[package]] +name = "writeable" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + [[package]] name = "ws_stream_wasm" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7999f5f4217fe3818726b66257a4475f71e74ffd190776ad053fa159e50737f5" +checksum = "6c173014acad22e83f16403ee360115b38846fe754e735c5d9d3803fe70c6abc" dependencies = [ "async_io_stream", "futures", "js-sys", "log", "pharos", - "rustc_version 0.4.0", + "rustc_version 0.4.1", "send_wrapper", - "thiserror 1.0.63", + "thiserror 2.0.17", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -4888,32 +5401,76 @@ dependencies = [ "tap", ] +[[package]] +name = "yoke" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", + "synstructure", +] + [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" dependencies = [ - "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", + "synstructure", ] [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" dependencies = [ "zeroize_derive", ] @@ -4926,7 +5483,40 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.106", +] + +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", ] [[package]] @@ -4970,9 +5560,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.13+zstd.1.5.6" +version = "2.0.16+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" dependencies = [ "cc", "pkg-config", diff --git a/src/main.rs b/src/main.rs index 6d363f75..7a53298d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1106,7 +1106,7 @@ async fn make_app(current_dir: &std::ffi::OsString) -> Result { .short('t') .long("template") .help("Template to create") - .value_parser(["blank", "chat", "echo", "fibonacci", "file-transfer"]) + .value_parser(["blank", "chat", "echo", "fibonacci", "file-transfer", "hyperapp-skeleton"]) .default_value("chat") ) .arg(Arg::new("UI") diff --git a/src/new/mod.rs b/src/new/mod.rs index 1b5f1e82..8ea42ab8 100644 --- a/src/new/mod.rs +++ b/src/new/mod.rs @@ -23,6 +23,7 @@ pub enum Template { Echo, Fibonacci, FileTransfer, + HyperappSkeleton, } impl Language { @@ -44,6 +45,7 @@ impl Template { Template::Echo => "echo", Template::Fibonacci => "fibonacci", Template::FileTransfer => "file-transfer", + Template::HyperappSkeleton => "hyperapp-skeleton", } .to_string() } @@ -68,7 +70,8 @@ impl From<&String> for Template { "echo" => Template::Echo, "fibonacci" => Template::Fibonacci, "file-transfer" => Template::FileTransfer, - _ => panic!("kit: template must be 'blank', 'chat', 'echo', or 'fibonacci'; not '{s}'"), + "hyperapp-skeleton" => Template::HyperappSkeleton, + _ => panic!("kit: template must be 'blank', 'chat', 'echo', 'fibonacci', or 'hyperapp-skeleton'; not '{s}'"), } } } diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/Cargo.toml b/src/new/templates/rust/ui/hyperapp-skeleton/Cargo.toml new file mode 100644 index 00000000..b750850e --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/Cargo.toml @@ -0,0 +1,11 @@ +[profile.release] +lto = true +opt-level = "s" +panic = "abort" + +[workspace] +members = [ + "skeleton-app", + "target/hyperapp-skeleton-caller-util?", +] +resolver = "2" diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/README.md b/src/new/templates/rust/ui/hyperapp-skeleton/README.md new file mode 100644 index 00000000..6cb2270a --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/README.md @@ -0,0 +1,249 @@ +# Hyperware Skeleton App + +A minimal, well-commented skeleton application for the Hyperware platform using the Hyperapp framework. +This skeleton provides a starting point for building Hyperware applications with a React/TypeScript frontend and Rust backend. + +Either prompt your favorite LLM directly with instructions on how to build your app or add them to `instructions.md`! + +Recommended usage: +- Create a skeleton repo using a kit template: + ```bash + kit new foo --template hyperapp-skeleton --ui + cd foo + ``` +- Write a detailed document describing what you want your app to do. + Save this in `instructions.md`. +- Prompt your LLM agent (i.e. Claude Code) with something like: + ``` + ## GOAL + + + + ## Instructions + + Read the README.md and follow the Instructions > Create an implementation plan + ``` + +- After creating an implementation plan, clear your LLM agent's context and then prompt it again with something like: + + ``` + ## GOAL + + + + ## Instructions + + Read the README.md and follow the Instructions > Implement the plan + ``` + +The rest of this document is aimed at *LLMs* not *humans*. + +## Quick Start + +### Prerequisites + +- Hyperware development environment (`kit` command) +- Rust toolchain +- Node.js and npm + +### Building + +Always build with +```bash +kit build --hyperapp +``` + +## Project Structure + +``` +hyperapp-skeleton/ +├── Cargo.toml # Workspace configuration +├── metadata.json # App metadata +├── skeleton-app/ # Main Rust process +│ ├── Cargo.toml # Process dependencies +│ └── src/ +│ ├── lib.rs # Main app logic (well-commented) +│ └── icon # App icon file +├── ui/ # Frontend application +│ ├── package.json # Node dependencies +│ ├── index.html # Entry point (includes /our.js) +│ ├── vite.config.ts # Build configuration +│ └── src/ +│ ├── App.tsx # Main React component +│ ├── store/ # Zustand state management +│ ├── types/ # TypeScript type definitions +│ └── utils/ # API utilities +├── api/ # Generated WIT files (after build) +└── pkg/ # The final build product, including manifest.json, scripts.json and built package output +``` + +## Key Concepts + +### 1. The Hyperprocess Macro + +The `#[hyperprocess]` macro is the core of the Hyperapp framework. It provides: +- Async/await support without tokio +- Automatic WIT generation +- State persistence +- HTTP/WebSocket endpoint configuration + +### 2. Required Patterns + +#### HTTP Endpoints +ALL HTTP endpoints MUST be tagged with `#[http]`: +```rust +#[http] +async fn my_endpoint(&self) -> String { + // Implementation +} +``` + +#### Frontend API Calls +Parameters must be sent as tuples for multi-parameter methods: +```typescript +// Single parameter +{ "MethodName": value } + +// Multiple parameters +{ "MethodName": [param1, param2] } +``` + +#### The /our.js Script +MUST be included in index.html: +```html + +``` + +### 3. State Persistence + +Your app's state is automatically persisted based on the `save_config` option: +- `OnDiff`: Save when state changes (strongly recommended) +- `Never`: No automatic saves +- `EveryMessage`: Save after each message (safest; slowest) +- `EveeyNMessage(u64)`: Save every N messages received +- `EveeyNSeconds(u64)`: Save every N seconds + +## Customization Guide + +### 1. Modify App State + +Edit `AppState` in `skeleton-app/src/lib.rs`: +```rust +#[derive(Default, Serialize, Deserialize)] +pub struct AppState { + // Add your fields here + my_data: Vec, +} +``` + +### 2. Add HTTP Endpoints + +For UI interaction: +```rust +#[http] +async fn my_method(&mut self) -> Result { + // Parse request, update state, return response +} +``` + +### 3. Add Capabilities + +Add system permissions in `pkg/manifest.json`: +```json +"request_capabilities": [ + "homepage:homepage:sys", + "http-server:distro:sys", + "vfs:distro:sys" // Add as needed +] +``` + +These are required to message other local processes. +They can also be granted so other local processes can message us. +There is also a `request_networking` field that must be true to send messages over the network p2p. + +### 4. Update Frontend + +1. Add types in `ui/src/types/skeleton.ts` +2. Update store in `ui/src/store/skeleton.ts` +3. Modify UI in `ui/src/App.tsx` + +### 5. Rename as appropriate + +Change names throughout from `hyperapp-skeleton` (and variants) as appropriate if user describes app name. + +## Common Issues and Solutions + +### "Failed to deserialize HTTP request" +- Check parameter format (tuple vs object) + +### "Node not connected" +- Verify `/our.js` is included in index.html +- Check that the app is running in Hyperware environment + +### WIT Generation Errors +- Use simple types or return JSON strings +- No HashMap (use Vec<(K,V)>) +- No fixed arrays (use Vec) +- Add #[derive(PartialEq)] to structs + +### Import Errors +- Don't add `hyperware_process_lib` to Cargo.toml +- Use imports from `hyperprocess_macro` + +## Testing Your App + +1. Deploy app to a Hyperware node (after building, if requested): + ```bash + kit start-packages + ``` +2. Your app will be automatically installed and available at `http://localhost:8080` +3. Check the Hyperware homepage for your app icon + +## Instructions + +### Create an implementation plan + +Carefully read the prompt; look carefully at `instructions.md` (if it exists) and in the resources/ directory. +In particular, note the example applications `resources/example-apps/sign/`, `resources/example-apps/id/`, and `resources/example-apps/file-explorer`. Note that `file-explorer` example contains an `api`, which is generated by the compiler, and not human or LLM written. +`sign` and `id` demonstrate local messaging. +`file-explorer` demonstrates VFS interactions. + +Expand the prompt and/or `instructions.md` into a detailed implementation plan. +The implementor will be starting from this existing template that exists at `skeleton-app/` and `ui/`. + +Note in particular that bindings for the UI will be generated when the app is built with `kit build --hyperapp`. +As such, first design and implement the backend; the interface will be generated from the backend; finally design and implement the frontend to consume the interface. +Subsequent changes to the interface must follow this pattern as well: start in backend, generate interface, finish in frontend + +Do NOT create the API. +The API is machine generated. +You create types that end up in the API by defining and using them in functions in the Rust backend "hyperapp" + +Do NOT write code: just create a detailed `IMPLEMENTATION_PLAN.md` that will be used by the implementor. +The implementor will have access to `resources/` but will be working from `IMPLEMENTATION_PLAN.md`, so include all relevant context in the PLAN. +You can refer the implementor to `resources/` but do not assume the implementor has read them unless you refer them there. + +### Implement the plan + +Look carefully at `IMPLEMENTATION_PLAN.md` and in the `resources/` directory, if relevant. +In particular, note the example applications `resources/example-apps/sign/`, `resources/example-apps/id/`, and `resources/example-apps/file-explorer`. +Use them if useful. + +Work from the existing template that exists at `skeleton-app/` and `ui/`. + +Note in particular that bindings for the UI will be generated when the app is built with `kit build --hyperapp`. +As such, first design and implement the backend; the interface will be generated from the backend; finally design and implement the frontend to consume the interface. +Subsequent changes to the interface must follow this pattern as well: start in backend, generate interface, finish in frontend + +Do NOT create the API. +The API is machine generated. +You create types that end up in the API by defining and using them in functions in the Rust backend "hyperapp" + +Do not worry about serialization/deserialization when using `send` and `send_rmp` functions for p2p communication. +Notice that this all happens within those functions: just take the rust types as args and return rust types as return values. + +If you create a GUI for the app you MUST use target/ui/caller-utils.ts for HTTP requests to the backend. +Do NOT edit this file: it is machine generated. +Do NOT do `fetch` or other HTTP requests manually to the backend: use the functions in this machine generated interface. + +Implement the application described in the `IMPLEMENTATION_PLAN.md`. diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/metadata.json b/src/new/templates/rust/ui/hyperapp-skeleton/metadata.json new file mode 100644 index 00000000..73173a9e --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/metadata.json @@ -0,0 +1,18 @@ +{ + "name": "SkeletonApp", + "description": "A minimal skeleton app for the Hyperware platform using the Hyperapp framework - demonstrates basic state management and HTTP endpoints", + "image": "", + "properties": { + "package_name": "skeleton-app", + "current_version": "0.1.0", + "publisher": "skeleton.os", + "mirrors": [], + "code_hashes": { + "0.1.0": "" + }, + "wit_version": 1, + "dependencies": [] + }, + "external_url": "", + "animation_url": "" +} \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/pkg/manifest.json b/src/new/templates/rust/ui/hyperapp-skeleton/pkg/manifest.json new file mode 100644 index 00000000..b400f8b7 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/pkg/manifest.json @@ -0,0 +1,19 @@ +[ + { + "process_name": "skeleton-app", + "process_wasm_path": "/skeleton-app.wasm", + "on_exit": "Restart", + "request_networking": false, + "request_capabilities": [ + "homepage:homepage:sys", + "http-server:distro:sys", + "vfs:distro:sys" + ], + "grant_capabilities": [ + "homepage:homepage:sys", + "http-server:distro:sys", + "vfs:distro:sys" + ], + "public": false + } +] diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/README.md b/src/new/templates/rust/ui/hyperapp-skeleton/resources/README.md new file mode 100644 index 00000000..da38ba19 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/README.md @@ -0,0 +1,84 @@ +# 📚 Hyperware Skeleton App Resources + +This directory contains all the resources needed to transform the skeleton app into any type of Hyperware application. + +## 📖 Development Guides + +The [`guides/`](./guides/) directory contains comprehensive documentation for building Hyperware apps: + +- **[Quick Reference](./guides/00-QUICK-REFERENCE.md)** - Essential rules and syntax +- **[Common Patterns](./guides/01-COMMON-PATTERNS.md)** - Ready-to-use code recipes +- **[Troubleshooting](./guides/02-TROUBLESHOOTING.md)** - Fix common errors +- **[WIT Types Guide](./guides/03-WIT-TYPES-DATA-MODELING.md)** - Data modeling constraints +- **[P2P Patterns](./guides/04-P2P-PATTERNS.md)** - Node-to-node communication +- **[Frontend Guide](./guides/05-UI-FRONTEND-GUIDE.md)** - React/TypeScript development +- **[Testing Guide](./guides/06-TESTING-DEBUGGING.md)** - Debug and test strategies +- **[Complete Examples](./guides/07-COMPLETE-EXAMPLES.md)** - Full working apps +- **[Manifest & Deployment](./guides/08-MANIFEST-AND-DEPLOYMENT.md)** - Understanding manifest.json +- **[Capabilities Guide](./guides/09-CAPABILITIES-GUIDE.md)** - System permissions reference + +See the [Guides README](./guides/README.md) for detailed navigation help. + +## 💡 Example App Ideas + +The [`example-apps/TODO.md`](./example-apps/TODO.md) file contains 12+ app ideas ranging from basic to advanced: + +- Todo lists and notepads +- P2P chat and file sharing +- Collaborative tools +- Games and marketplaces +- System utilities + +Each idea includes implementation notes and key concepts to demonstrate. + +## 🎯 How to Use These Resources + +### Starting a New App +1. Copy the skeleton app +2. Read the Quick Reference guide +3. Find a similar example in Complete Examples +4. Use Common Patterns for specific features + +### When You're Stuck +1. Check Troubleshooting for your error +2. Verify all requirements in Quick Reference +3. Look for working patterns in Complete Examples +4. Test with simpler code first + +### For Specific Features +- **State Management** → Common Patterns section 1 +- **P2P Communication** → P2P Patterns guide +- **File Handling** → Common Patterns section 4 +- **UI Development** → Frontend Guide + +## 🔑 Key Principles + +1. **Start Simple** - Get basic functionality working first +2. **Test Incrementally** - Don't write everything before testing +3. **Follow Patterns** - Use proven patterns from the guides +4. **Handle Errors** - Always provide user feedback +5. **Design for P2P** - Remember there's no central server + +## 📝 Quick Reminders + +### Must-Have Requirements +- `` in your HTML +- Tuple format `[p1, p2]` for multi-parameter calls +- `.expects_response(30)` on remote requests + +### Common Fixes +- **Build errors** → Usually missing requirements above +- **Type errors** → Use JSON strings for complex types +- **P2P failures** → Check node names and ProcessId format +- **UI issues** → Verify /our.js is included +- **manifest.json missing** → Run `kit b --hyperapp` to generate it +- **Capability errors** → Check Capabilities Guide for required permissions + +## 🚀 Next Steps + +1. Review the skeleton app's heavily commented `lib.rs` +2. Pick an example from Complete Examples to study +3. Start modifying the skeleton incrementally +4. Test with multiple nodes for P2P features + +Remember: The skeleton app is designed to compile and run immediately. Build on that working foundation! \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/Cargo.toml b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/Cargo.toml new file mode 100644 index 00000000..299a6ba1 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/Cargo.toml @@ -0,0 +1,10 @@ +[profile.release] +lto = true +opt-level = "s" +panic = "abort" + +[workspace] +members = [ + "explorer", +] +resolver = "2" diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/api/file-explorer-sys-v0.wit b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/api/file-explorer-sys-v0.wit new file mode 100644 index 00000000..bce33874 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/api/file-explorer-sys-v0.wit @@ -0,0 +1,4 @@ +world file-explorer-sys-v0 { + import file-explorer; + include process-v1; +} \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/api/file-explorer.wit b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/api/file-explorer.wit new file mode 100644 index 00000000..5219834a --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/api/file-explorer.wit @@ -0,0 +1,151 @@ +interface file-explorer { +use standard.{address}; + + variant auth-scheme { + public, + private + } + + record file-info { + name: string, + path: string, + size: u64, + created: u64, + modified: u64, + is-directory: bool, + permissions: string + } + + // Function signature for: copy-file (http) + // HTTP: POST /api/copy-file + record copy-file-signature-http { + target: string, + source: string, + destination: string, + returning: result + } + + // Function signature for: create-directory (http) + // HTTP: POST /api/create-directory + record create-directory-signature-http { + target: string, + path: string, + returning: result + } + + // Function signature for: create-file (http) + // HTTP: POST /api/create-file + record create-file-signature-http { + target: string, + path: string, + content: list, + returning: result + } + + // Function signature for: delete-directory (http) + // HTTP: POST /api/delete-directory + record delete-directory-signature-http { + target: string, + path: string, + returning: result + } + + // Function signature for: delete-file (http) + // HTTP: POST /api/delete-file + record delete-file-signature-http { + target: string, + path: string, + returning: result + } + + // Function signature for: get-current-directory (http) + // HTTP: POST /api/get-current-directory + record get-current-directory-signature-http { + target: string, + returning: result + } + + // Function signature for: get-share-link (http) + // HTTP: POST /api/get-share-link + record get-share-link-signature-http { + target: string, + path: string, + returning: result, string> + } + + // Function signature for: list-directory (http) + // HTTP: POST /api/list-directory + record list-directory-signature-http { + target: string, + path: string, + returning: result, string> + } + + // Function signature for: move-file (http) + // HTTP: POST /api/move-file + record move-file-signature-http { + target: string, + source: string, + destination: string, + returning: result + } + + // Function signature for: read-file (http) + // HTTP: POST /api/read-file + record read-file-signature-http { + target: string, + path: string, + returning: result, string> + } + + // Function signature for: serve-shared-file (http) + // HTTP: POST /api/serve-shared-file + record serve-shared-file-signature-http { + target: string, + returning: result, string> + } + + // Function signature for: set-current-directory (http) + // HTTP: POST /api/set-current-directory + record set-current-directory-signature-http { + target: string, + path: string, + returning: result + } + + // Function signature for: share-file (http) + // HTTP: POST /api/share-file + record share-file-signature-http { + target: string, + path: string, + auth: auth-scheme, + returning: result + } + + // Function signature for: unshare-file (http) + // HTTP: POST /api/unshare-file + record unshare-file-signature-http { + target: string, + path: string, + returning: result + } + + // Function signature for: update-file (http) + // HTTP: POST /api/update-file + record update-file-signature-http { + target: string, + path: string, + content: list, + returning: result + } + + // Function signature for: upload-file (http) + // HTTP: POST /api/upload-file + record upload-file-signature-http { + target: string, + path: string, + filename: string, + content: list, + returning: result + } +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/api/types-file-explorer-sys-v0.wit b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/api/types-file-explorer-sys-v0.wit new file mode 100644 index 00000000..56be0975 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/api/types-file-explorer-sys-v0.wit @@ -0,0 +1,4 @@ +world types-file-explorer-sys-v0 { + import file-explorer; + include lib; +} \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/explorer/Cargo.toml b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/explorer/Cargo.toml new file mode 100644 index 00000000..884c9dee --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/explorer/Cargo.toml @@ -0,0 +1,34 @@ +[dependencies] +anyhow = "1.0" +md5 = "0.7" +process_macros = "0.1" +serde_json = "1.0" +serde_urlencoded = "0.7" +tracing = "0.1.37" +wit-bindgen = "0.42.1" + +[dependencies.hyperprocess_macro] +git = "https://github.com/hyperware-ai/hyperprocess-macro" +rev = "66884c0" + +[dependencies.hyperware_process_lib] +features = ["hyperapp"] +git = "https://github.com/hyperware-ai/process_lib" +rev = "4beff93" + +[dependencies.serde] +features = ["derive"] +version = "1.0" + +[lib] +crate-type = ["cdylib"] +name = "explorer" +path = "src/lib.rs" + +[package] +edition = "2021" +name = "explorer" +version = "0.1.0" + +[package.metadata.component] +package = "hyperware:process" diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/explorer/src/icon b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/explorer/src/icon new file mode 100644 index 00000000..d0d597fd --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/explorer/src/icon @@ -0,0 +1 @@ +data:image/png;base64,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 \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/explorer/src/lib.rs b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/explorer/src/lib.rs new file mode 100644 index 00000000..ec0b85a6 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/explorer/src/lib.rs @@ -0,0 +1,498 @@ +use hyperprocess_macro::hyperprocess; +use hyperware_process_lib::hyperapp::{add_response_header, get_path, send, SaveOptions}; +use hyperware_process_lib::logging::{debug, error, info, init_logging, Level}; +use hyperware_process_lib::our; +use hyperware_process_lib::vfs::{ + self, create_drive, vfs_request, FileType, VfsAction, VfsResponse, +}; +use std::collections::HashMap; + +const ICON: &str = include_str!("./icon"); +const PROCESS_ID_LINK: &str = "explorer:file-explorer:sys"; + +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct FileInfo { + pub name: String, + pub path: String, + pub size: u64, + pub created: u64, + pub modified: u64, + pub is_directory: bool, + pub permissions: String, +} + +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +pub enum AuthScheme { + Public, + Private, +} + +#[derive(Default, Debug, serde::Serialize, serde::Deserialize)] +struct FileExplorerState { + // HashMap to track shared files and their auth schemes + shared_files: HashMap, + // Current working directory for the user + cwd: String, +} + +#[hyperprocess( + name = "file-explorer", + ui = Some(HttpBindingConfig::default().secure_subdomain(true)), + endpoints = vec![ + Binding::Http { + path: "/api", + config: HttpBindingConfig::default().secure_subdomain(true), + }, + Binding::Ws { + path: "/ws", + config: WsBindingConfig::default().secure_subdomain(true), + }, + Binding::Http { + path: "/shared/*", + config: HttpBindingConfig::default().authenticated(false), + } + ], + save_config = SaveOptions::Never, + wit_world = "file-explorer-sys-v0", +)] +impl FileExplorerState { + #[init] + async fn init(&mut self) { + init_logging(Level::DEBUG, Level::INFO, None, None, None).unwrap(); + + // Create home drive for the user + let package_id = our().package_id(); + match create_drive(package_id.clone(), "home", Some(5)) { + Ok(home_path) => { + info!("Created home drive at: {}", home_path); + self.cwd = home_path; + } + Err(e) => { + error!( + "Failed to create home drive: {:?}. Using root as default.", + e + ); + self.cwd = "/".to_string(); + } + } + + hyperware_process_lib::homepage::add_to_homepage( + "File Explorer", + Some(ICON), + Some(""), + None, + ); + } + + #[http] + async fn list_directory(&mut self, path: String) -> Result, String> { + info!("list_directory called with path: {}", path); + + // For root path, read from VFS root to get all drives + let vfs_path = if path == "/" || path.is_empty() { + "/".to_string() + } else { + path.clone() + }; + + // Just list the current directory - no recursion + list_directory_contents(&vfs_path).await + } + + #[http] + async fn create_file(&mut self, path: String, content: Vec) -> Result { + info!("create_file called with path: {}", path); + + let vfs_path = path.clone(); + debug!("VFS path: {}", vfs_path); + + // Create file and write content + let file = vfs::create_file(&vfs_path, Some(5)) + .map_err(|e| format!("Failed to create file: {}", e))?; + + file.write(&content) + .map_err(|e| format!("Failed to write file: {}", e))?; + + // Get metadata for response + let meta = file + .metadata() + .map_err(|e| format!("Failed to get metadata: {}", e))?; + + Ok(FileInfo { + name: path.split('/').last().unwrap_or("").to_string(), + path, + size: meta.len, + created: 0, + modified: 0, + is_directory: false, + permissions: "rw".to_string(), + }) + } + + #[http] + async fn read_file(&mut self, path: String) -> Result, String> { + info!("read_file called with path: {}", path); + + let vfs_path = path.clone(); + + let file = vfs::open_file(&vfs_path, false, Some(5)) + .map_err(|e| format!("Failed to open file: {}", e))?; + + file.read() + .map_err(|e| format!("Failed to read file: {}", e)) + } + + #[http] + async fn update_file(&mut self, path: String, content: Vec) -> Result { + info!("update_file called with path: {}", path); + + let vfs_path = path.clone(); + + let file = vfs::open_file(&vfs_path, false, Some(5)) + .map_err(|e| format!("Failed to open file: {}", e))?; + + file.write(&content) + .map_err(|e| format!("Failed to write file: {}", e))?; + + let meta = file + .metadata() + .map_err(|e| format!("Failed to get metadata: {}", e))?; + + Ok(FileInfo { + name: path.split('/').last().unwrap_or("").to_string(), + path, + size: meta.len, + created: 0, + modified: 0, + is_directory: false, + permissions: "rw".to_string(), + }) + } + + #[http] + async fn delete_file(&mut self, path: String) -> Result { + info!("delete_file called with path: {}", path); + + let vfs_path = path.clone(); + + vfs::remove_file(&vfs_path, Some(5)) + .await + .map_err(|e| format!("Failed to delete file: {}", e))?; + + Ok(true) + } + + #[http] + async fn create_directory(&mut self, path: String) -> Result { + info!("create_directory called with path: {}", path); + + let vfs_path = path.clone(); + + let _dir = vfs::open_dir(&vfs_path, true, Some(5)) + .map_err(|e| format!("Failed to create directory: {}", e))?; + + Ok(FileInfo { + name: path.split('/').last().unwrap_or("").to_string(), + path, + size: 0, + created: 0, + modified: 0, + is_directory: true, + permissions: "rw".to_string(), + }) + } + + #[http] + async fn delete_directory(&mut self, path: String) -> Result { + info!("delete_directory called with path: {}", path); + + let vfs_path = path.clone(); + let timeout = 5; + + // Create a VFS request with RemoveDirAll action to handle non-empty directories + let request = vfs_request(&vfs_path, VfsAction::RemoveDirAll).expects_response(timeout); + + // Send the request and await response + let response: Result = send(request).await; + + match response { + Ok(VfsResponse::Ok) => Ok(true), + Ok(VfsResponse::Err(e)) => Err(format!("Failed to delete directory: {:?}", e)), + Ok(_) => Err("Unexpected response from VFS".to_string()), + Err(e) => Err(format!("Failed to send VFS request: {}", e)), + } + } + + #[http] + async fn upload_file( + &mut self, + path: String, + filename: String, + content: Vec, + ) -> Result { + let full_path = format!("{}/{}", path, filename); + self.create_file(full_path, content).await + } + + #[http] + async fn share_file(&mut self, path: String, auth: AuthScheme) -> Result { + // Generate share ID from path hash + let share_id = format!("{:x}", md5::compute(&path)); + + // Add to shared_files HashMap + self.shared_files.insert(path.clone(), auth); + + // Return share link with full path + Ok(format!("/{PROCESS_ID_LINK}/shared/{share_id}")) + } + + #[http] + async fn unshare_file(&mut self, path: String) -> Result { + Ok(self.shared_files.remove(&path).is_some()) + } + + #[http] + async fn get_share_link(&mut self, path: String) -> Result, String> { + // Check if file is shared + if self.shared_files.contains_key(&path) { + let share_id = format!("{:x}", md5::compute(&path)); + Ok(Some(format!("/{PROCESS_ID_LINK}/shared/{share_id}"))) + } else { + Ok(None) + } + } + + #[http] + async fn serve_shared_file(&mut self) -> Result, String> { + // Use get_path() to handle routing + let request_path = get_path(); + + // Extract the file path from the request + if let Some(request_path_str) = request_path { + if let Some(share_id) = request_path_str.strip_prefix("/shared/") { + // Find the original path from share_id + for (path, auth_scheme) in &self.shared_files { + if format!("{:x}", md5::compute(path)) == share_id { + match auth_scheme { + AuthScheme::Public => { + // Extract filename from path + let filename = path.split('/').last().unwrap_or("download"); + + // Set Content-Disposition header to preserve original filename + add_response_header( + "Content-Disposition".to_string(), + format!("attachment; filename=\"{}\"", filename), + ); + + // Set appropriate Content-Type based on file extension + let content_type = match filename.split('.').last() { + Some("txt") => "text/plain", + Some("html") | Some("htm") => "text/html", + Some("css") => "text/css", + Some("js") => "application/javascript", + Some("json") => "application/json", + Some("png") => "image/png", + Some("jpg") | Some("jpeg") => "image/jpeg", + Some("gif") => "image/gif", + Some("pdf") => "application/pdf", + Some("zip") => "application/zip", + _ => "application/octet-stream", + }; + add_response_header( + "Content-Type".to_string(), + content_type.to_string(), + ); + + // Read and return file content + return self.read_file(path.clone()).await; + } + AuthScheme::Private => { + return Err("Access denied: Private file".to_string()); + } + } + } + } + Err("File not found or not shared".to_string()) + } else { + Err("Invalid shared file path".to_string()) + } + } else { + Err("No request path provided".to_string()) + } + } + + #[http] + async fn get_current_directory(&mut self) -> Result { + info!("get_current_directory called, returning: {}", self.cwd); + Ok(self.cwd.clone()) + } + + #[http] + async fn set_current_directory(&mut self, path: String) -> Result { + self.cwd = path.clone(); + Ok(path) + } + + #[http] + async fn move_file(&mut self, source: String, destination: String) -> Result { + // Read file content + let content = self.read_file(source.clone()).await?; + + // Create file at destination + let file_info = self.create_file(destination, content).await?; + + // Delete source file + self.delete_file(source).await?; + + Ok(file_info) + } + + #[http] + async fn copy_file(&mut self, source: String, destination: String) -> Result { + // Read file content + let content = self.read_file(source).await?; + + // Create file at destination + self.create_file(destination, content).await + } +} + +// Helper function to list directory contents with 2 levels of depth +async fn list_directory_contents(path: &str) -> Result, String> { + debug!("list_directory_contents: path='{}'", path); + + // Open directory + let dir = vfs::Directory { + path: path.to_string(), + timeout: 5, + }; + + // Read directory entries + let entries = dir + .read() + .map_err(|e| format!("Failed to read directory '{}': {}", path, e))?; + + debug!("VFS returned {} entries for path '{}'", entries.len(), path); + + let mut all_files = Vec::new(); + + // Convert to FileInfo - Level 1 + for (i, entry) in entries.iter().enumerate() { + debug!( + "Entry[{}]: path='{}', file_type={:?}", + i, entry.path, entry.file_type + ); + + // VFS already provides absolute paths in entry.path + let full_path = entry.path.clone(); + + // Extract filename from the path + let filename = entry.path.split('/').last().unwrap_or("").to_string(); + + debug!( + "Constructed: filename='{}', full_path='{}'", + filename, full_path + ); + + if entry.file_type == FileType::Directory { + // Get directory size + let sub_dir = vfs::Directory { + path: full_path.clone(), + timeout: 5, + }; + + let dir_size = match sub_dir.read() { + Ok(contents) => { + let count = contents.len() as u64; + debug!("Directory '{}' has {} items", full_path, count); + count + } + Err(e) => { + error!("Failed to read subdirectory '{}': {}", full_path, e); + 0 + } + }; + + let file_info = FileInfo { + name: filename, + path: full_path.clone(), + size: dir_size, + created: 0, + modified: 0, + is_directory: true, + permissions: "rw".to_string(), + }; + + all_files.push(file_info); + + // Load one level deep into directories + let sub_dir2 = vfs::Directory { + path: full_path.clone(), + timeout: 5, + }; + + if let Ok(sub_entries) = sub_dir2.read() { + debug!( + "Loading {} sub-entries from '{}'", + sub_entries.len(), + full_path + ); + + for sub_entry in sub_entries { + // VFS already provides absolute paths in sub_entry.path + let sub_full_path = sub_entry.path.clone(); + let sub_filename = sub_entry.path.split('/').last().unwrap_or("").to_string(); + + debug!( + "Sub-entry: path='{}', filename='{}', file_type={:?}", + sub_full_path, sub_filename, sub_entry.file_type + ); + + if sub_entry.file_type == FileType::Directory { + all_files.push(FileInfo { + name: sub_filename, + path: sub_full_path, + size: 0, // Don't load deeper + created: 0, + modified: 0, + is_directory: true, + permissions: "rw".to_string(), + }); + } else { + // For files, try to get metadata + if let Ok(meta) = vfs::metadata(&sub_full_path, Some(5)).await { + all_files.push(FileInfo { + name: sub_filename, + path: sub_full_path, + size: meta.len, + created: 0, + modified: 0, + is_directory: false, + permissions: "rw".to_string(), + }); + } + } + } + } + } else { + // For files, get metadata + let meta = vfs::metadata(&full_path, Some(5)) + .await + .map_err(|e| format!("Failed to get metadata for '{}': {}", entry.path, e))?; + + all_files.push(FileInfo { + name: filename, + path: full_path, + size: meta.len, + created: 0, + modified: 0, + is_directory: false, + permissions: "rw".to_string(), + }); + } + } + + debug!("Returning {} files total", all_files.len()); + Ok(all_files) +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/metadata.json b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/metadata.json new file mode 100644 index 00000000..df958b85 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/metadata.json @@ -0,0 +1,18 @@ +{ + "name": "file-explorer", + "description": "File Explorer & Sharing", + "image": "https://raw.githubusercontent.com/hyperware-ai/hyperdrive/refs/heads/main/ui/public/assets/file-explorer-256.png", + "properties": { + "package_name": "file-explorer", + "current_version": "0.1.0", + "publisher": "sys", + "mirrors": [], + "code_hashes": { + "0.1.0": "" + }, + "wit_version": 1, + "dependencies": [] + }, + "external_url": "https://hyperware.ai", + "animation_url": "" +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/pkg/manifest.json b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/pkg/manifest.json new file mode 100644 index 00000000..4eb54b2a --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/pkg/manifest.json @@ -0,0 +1,25 @@ +[ + { + "process_name": "explorer", + "process_wasm_path": "/explorer.wasm", + "on_exit": "Restart", + "request_networking": false, + "request_capabilities": [ + "homepage:homepage:sys", + "http-server:distro:sys", + "vfs:distro:sys", + { + "process": "vfs:distro:sys", + "params": { + "root": true + } + } + ], + "grant_capabilities": [ + "homepage:homepage:sys", + "http-server:distro:sys", + "vfs:distro:sys" + ], + "public": false + } +] diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/.eslintrc.cjs b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/.eslintrc.cjs new file mode 100644 index 00000000..d6c95379 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/.eslintrc.cjs @@ -0,0 +1,18 @@ +module.exports = { + root: true, + env: { browser: true, es2020: true }, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:react-hooks/recommended', + ], + ignorePatterns: ['dist', '.eslintrc.cjs'], + parser: '@typescript-eslint/parser', + plugins: ['react-refresh'], + rules: { + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/.gitignore b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/.gitignore new file mode 100644 index 00000000..a547bf36 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/README.md b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/README.md new file mode 100644 index 00000000..b0e896f4 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/README.md @@ -0,0 +1,56 @@ +# Hyperware UI Template + +Based on the Vite React Typescript template. + +## Setup + +When using `kit new`, the `BASE_URL` on line 9 of `vite.config.ts` will be set automatically. +The `BASE_URL` will be the first process in `manifest.json`, the `package` from `metadata.json`, and `publisher` from `metadata.json`. +If you have multiple processes in `manifest.json`, make sure the first process will be the one serving the UI. + +## Development + +Run `npm i` and then `npm run dev` to start working on the UI. + +You may see an error: + +``` +[vite] Pre-transform error: Failed to load url /our.js (resolved id: /our.js). Does the file exist? +``` + +You can safely ignore this error. The file will be served by the node via the proxy. + +## public vs assets + +The `public/assets` folder contains files that are referenced in `index.html`, `src/assets` is for asset files that are only referenced in `src` code. + +## About Vite + React + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: + +- Configure the top-level `parserOptions` property like this: + +```js +export default { + // other rules... + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + project: ['./tsconfig.json', './tsconfig.node.json'], + tsconfigRootDir: __dirname, + }, +} +``` + +- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked` +- Optionally add `plugin:@typescript-eslint/stylistic-type-checked` +- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/index.html b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/index.html new file mode 100644 index 00000000..e8c7cf37 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/index.html @@ -0,0 +1,16 @@ + + + + + + + + + + File Explorer + + +
+ + + diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/package-lock.json b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/package-lock.json new file mode 100644 index 00000000..94bbed10 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/package-lock.json @@ -0,0 +1,3628 @@ +{ + "name": "ui-template", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "ui-template", + "version": "0.0.0", + "dependencies": { + "@hyperware-ai/client-api": "^0.1.4", + "qrcode": "^1.5.4", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "zustand": "^4.5.7" + }, + "devDependencies": { + "@types/node": "^20.10.4", + "@types/qrcode": "^1.5.5", + "@types/react": "^18.2.43", + "@types/react-dom": "^18.2.17", + "@typescript-eslint/eslint-plugin": "^6.14.0", + "@typescript-eslint/parser": "^6.14.0", + "@vitejs/plugin-react": "^4.2.1", + "eslint": "^8.55.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.5", + "http-proxy-middleware": "^2.0.6", + "typescript": "^5.2.2", + "vite": "^5.0.8" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.6.tgz", + "integrity": "sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.6", + "@babel/parser": "^7.23.6", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.6", + "@babel/types": "^7.23.6", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.6.tgz", + "integrity": "sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.6", + "@babel/types": "^7.23.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.23.3.tgz", + "integrity": "sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.23.3.tgz", + "integrity": "sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.6.tgz", + "integrity": "sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", + "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.10.tgz", + "integrity": "sha512-Q+mk96KJ+FZ30h9fsJl+67IjNJm3x2eX+GBWGmocAKgzp27cowCOOqSdscX80s0SpdFXZnIv/+1xD1EctFx96Q==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.10.tgz", + "integrity": "sha512-7W0bK7qfkw1fc2viBfrtAEkDKHatYfHzr/jKAHNr9BvkYDXPcC6bodtm8AyLJNNuqClLNaeTLuwURt4PRT9d7w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.10.tgz", + "integrity": "sha512-1X4CClKhDgC3by7k8aOWZeBXQX8dHT5QAMCAQDArCLaYfkppoARvh0fit3X2Qs+MXDngKcHv6XXyQCpY0hkK1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.10.tgz", + "integrity": "sha512-O/nO/g+/7NlitUxETkUv/IvADKuZXyH4BHf/g/7laqKC4i/7whLpB0gvpPc2zpF0q9Q6FXS3TS75QHac9MvVWw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.10.tgz", + "integrity": "sha512-YSRRs2zOpwypck+6GL3wGXx2gNP7DXzetmo5pHXLrY/VIMsS59yKfjPizQ4lLt5vEI80M41gjm2BxrGZ5U+VMA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.10.tgz", + "integrity": "sha512-alfGtT+IEICKtNE54hbvPg13xGBe4GkVxyGWtzr+yHO7HIiRJppPDhOKq3zstTcVf8msXb/t4eavW3jCDpMSmA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.10.tgz", + "integrity": "sha512-dMtk1wc7FSH8CCkE854GyGuNKCewlh+7heYP/sclpOG6Cectzk14qdUIY5CrKDbkA/OczXq9WesqnPl09mj5dg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.10.tgz", + "integrity": "sha512-G5UPPspryHu1T3uX8WiOEUa6q6OlQh6gNl4CO4Iw5PS+Kg5bVggVFehzXBJY6X6RSOMS8iXDv2330VzaObm4Ag==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.10.tgz", + "integrity": "sha512-j6gUW5aAaPgD416Hk9FHxn27On28H4eVI9rJ4az7oCGTFW48+LcgNDBN+9f8rKZz7EEowo889CPKyeaD0iw9Kg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.10.tgz", + "integrity": "sha512-QxaouHWZ+2KWEj7cGJmvTIHVALfhpGxo3WLmlYfJ+dA5fJB6lDEIg+oe/0//FuyVHuS3l79/wyBxbHr0NgtxJQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.10.tgz", + "integrity": "sha512-4ub1YwXxYjj9h1UIZs2hYbnTZBtenPw5NfXCRgEkGb0b6OJ2gpkMvDqRDYIDRjRdWSe/TBiZltm3Y3Q8SN1xNg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.10.tgz", + "integrity": "sha512-lo3I9k+mbEKoxtoIbM0yC/MZ1i2wM0cIeOejlVdZ3D86LAcFXFRdeuZmh91QJvUTW51bOK5W2BznGNIl4+mDaA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.10.tgz", + "integrity": "sha512-J4gH3zhHNbdZN0Bcr1QUGVNkHTdpijgx5VMxeetSk6ntdt+vR1DqGmHxQYHRmNb77tP6GVvD+K0NyO4xjd7y4A==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.10.tgz", + "integrity": "sha512-tgT/7u+QhV6ge8wFMzaklOY7KqiyitgT1AUHMApau32ZlvTB/+efeCtMk4eXS+uEymYK249JsoiklZN64xt6oQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.10.tgz", + "integrity": "sha512-0f/spw0PfBMZBNqtKe5FLzBDGo0SKZKvMl5PHYQr3+eiSscfJ96XEknCe+JoOayybWUFQbcJTrk946i3j9uYZA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.10.tgz", + "integrity": "sha512-pZFe0OeskMHzHa9U38g+z8Yx5FNCLFtUnJtQMpwhS+r4S566aK2ci3t4NCP4tjt6d5j5uo4h7tExZMjeKoehAA==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.10.tgz", + "integrity": "sha512-SpYNEqg/6pZYoc+1zLCjVOYvxfZVZj6w0KROZ3Fje/QrM3nfvT2llI+wmKSrWuX6wmZeTapbarvuNNK/qepSgA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.10.tgz", + "integrity": "sha512-ACbZ0vXy9zksNArWlk2c38NdKg25+L9pr/mVaj9SUq6lHZu/35nx2xnQVRGLrC1KKQqJKRIB0q8GspiHI3J80Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.10.tgz", + "integrity": "sha512-PxcgvjdSjtgPMiPQrM3pwSaG4kGphP+bLSb+cihuP0LYdZv1epbAIecHVl5sD3npkfYBZ0ZnOjR878I7MdJDFg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.10.tgz", + "integrity": "sha512-ZkIOtrRL8SEJjr+VHjmW0znkPs+oJXhlJbNwfI37rvgeMtk3sxOQevXPXjmAPZPigVTncvFqLMd+uV0IBSEzqA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.10.tgz", + "integrity": "sha512-+Sa4oTDbpBfGpl3Hn3XiUe4f8TU2JF7aX8cOfqFYMMjXp6ma6NJDztl5FDG8Ezx0OjwGikIHw+iA54YLDNNVfw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.10.tgz", + "integrity": "sha512-EOGVLK1oWMBXgfttJdPHDTiivYSjX6jDNaATeNOaCOFEVcfMjtbx7WVQwPSE1eIfCp/CaSF2nSrDtzc4I9f8TQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.10.tgz", + "integrity": "sha512-whqLG6Sc70AbU73fFYvuYzaE4MNMBIlR1Y/IrUeOXFrWHxBEjjbZaQ3IXIQS8wJdAzue2GwYZCjOrgrU1oUHoA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, + "node_modules/@hyperware-ai/client-api": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@hyperware-ai/client-api/-/client-api-0.1.4.tgz", + "integrity": "sha512-/P9HNzSkoYAR8lDwwMlyJCchL9gvALIIwvLp901S+tZ8/Yv+U2wnjhUfFfN32JwvQ2v4MjekB+RunB7Dv25awA==", + "dependencies": { + "buffer": "^6.0.3", + "node-forge": "^1.3.1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.1.tgz", + "integrity": "sha512-6vMdBZqtq1dVQ4CWdhFwhKZL6E4L1dV6jUjuBvsavvNJSppzi6dLBbuV+3+IyUREaj9ZFvQefnQm28v4OCXlig==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.1.tgz", + "integrity": "sha512-Jto9Fl3YQ9OLsTDWtLFPtaIMSL2kwGyGoVCmPC8Gxvym9TCZm4Sie+cVeblPO66YZsYH8MhBKDMGZ2NDxuk/XQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.1.tgz", + "integrity": "sha512-LtYcLNM+bhsaKAIGwVkh5IOWhaZhjTfNOkGzGqdHvhiCUVuJDalvDxEdSnhFzAn+g23wgsycmZk1vbnaibZwwA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.1.tgz", + "integrity": "sha512-KyP/byeXu9V+etKO6Lw3E4tW4QdcnzDG/ake031mg42lob5tN+5qfr+lkcT/SGZaH2PdW4Z1NX9GHEkZ8xV7og==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.1.tgz", + "integrity": "sha512-Yqz/Doumf3QTKplwGNrCHe/B2p9xqDghBZSlAY0/hU6ikuDVQuOUIpDP/YcmoT+447tsZTmirmjgG3znvSCR0Q==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.1.tgz", + "integrity": "sha512-u3XkZVvxcvlAOlQJ3UsD1rFvLWqu4Ef/Ggl40WAVCuogf4S1nJPHh5RTgqYFpCOvuGJ7H5yGHabjFKEZGExk5Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.1.tgz", + "integrity": "sha512-0XSYN/rfWShW+i+qjZ0phc6vZ7UWI8XWNz4E/l+6edFt+FxoEghrJHjX1EY/kcUGCnZzYYRCl31SNdfOi450Aw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.1.tgz", + "integrity": "sha512-LmYIO65oZVfFt9t6cpYkbC4d5lKHLYv5B4CSHRpnANq0VZUQXGcCPXHzbCXCz4RQnx7jvlYB1ISVNCE/omz5cw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.1.tgz", + "integrity": "sha512-kr8rEPQ6ns/Lmr/hiw8sEVj9aa07gh1/tQF2Y5HrNCCEPiCBGnBUt9tVusrcBBiJfIt1yNaXN6r1CCmpbFEDpg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.1.tgz", + "integrity": "sha512-t4QSR7gN+OEZLG0MiCgPqMWZGwmeHhsM4AkegJ0Kiy6TnJ9vZ8dEIwHw1LcZKhbHxTY32hp9eVCMdR3/I8MGRw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.1.tgz", + "integrity": "sha512-7XI4ZCBN34cb+BH557FJPmh0kmNz2c25SCQeT9OiFWEgf8+dL6ZwJ8f9RnUIit+j01u07Yvrsuu1rZGxJCc51g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.1.tgz", + "integrity": "sha512-yE5c2j1lSWOH5jp+Q0qNL3Mdhr8WuqCNVjc6BxbVfS5cAS6zRmdiw7ktb8GNpDCEUJphILY6KACoFoRtKoqNQg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.1.tgz", + "integrity": "sha512-PyJsSsafjmIhVgaI1Zdj7m8BB8mMckFah/xbpplObyHfiXzKcI5UOUXRyOdHW7nz4DpMCuzLnF7v5IWHenCwYA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.4", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.4.tgz", + "integrity": "sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/http-proxy": { + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.10.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz", + "integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.11", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", + "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==", + "devOptional": true + }, + "node_modules/@types/qrcode": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.5.tgz", + "integrity": "sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/react": { + "version": "18.2.45", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.45.tgz", + "integrity": "sha512-TtAxCNrlrBp8GoeEp1npd5g+d/OejJHFxS3OWmrPBMFaVQMSN0OFySozJio5BHxTuTeug00AVXVAjfDSfk+lUg==", + "devOptional": true, + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.2.18", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz", + "integrity": "sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==", + "devOptional": true + }, + "node_modules/@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.15.0.tgz", + "integrity": "sha512-j5qoikQqPccq9QoBAupOP+CBu8BaJ8BLjaXSioDISeTZkVO3ig7oSIKh3H+rEpee7xCXtWwSB4KIL5l6hWZzpg==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.15.0", + "@typescript-eslint/type-utils": "6.15.0", + "@typescript-eslint/utils": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.15.0.tgz", + "integrity": "sha512-MkgKNnsjC6QwcMdlNAel24jjkEO/0hQaMDLqP4S9zq5HBAUJNQB6y+3DwLjX7b3l2b37eNAxMPLwb3/kh8VKdA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.15.0", + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/typescript-estree": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.15.0.tgz", + "integrity": "sha512-+BdvxYBltqrmgCNu4Li+fGDIkW9n//NrruzG9X1vBzaNK+ExVXPoGB71kneaVw/Jp+4rH/vaMAGC6JfMbHstVg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.15.0.tgz", + "integrity": "sha512-CnmHKTfX6450Bo49hPg2OkIm/D/TVYV7jO1MCfPYGwf6x3GO0VU8YMO5AYMn+u3X05lRRxA4fWCz87GFQV6yVQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.15.0", + "@typescript-eslint/utils": "6.15.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.15.0.tgz", + "integrity": "sha512-yXjbt//E4T/ee8Ia1b5mGlbNj9fB9lJP4jqLbZualwpP2BCQ5is6BcWwxpIsY4XKAhmdv3hrW92GdtJbatC6dQ==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.15.0.tgz", + "integrity": "sha512-7mVZJN7Hd15OmGuWrp2T9UvqR2Ecg+1j/Bp1jXUEY2GZKV6FXlOIoqVDmLpBiEiq3katvj/2n2mR0SDwtloCew==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.15.0.tgz", + "integrity": "sha512-eF82p0Wrrlt8fQSRL0bGXzK5nWPRV2dYQZdajcfzOD9+cQz9O7ugifrJxclB+xVOvWvagXfqS4Es7vpLP4augw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.15.0", + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/typescript-estree": "6.15.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.15.0.tgz", + "integrity": "sha512-1zvtdC1a9h5Tb5jU9x3ADNXO9yjP8rXlaoChu0DQX40vf5ACVpYIVIZhIMZ6d5sDXH7vq4dsZBT1fEGj8D2n2w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.15.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz", + "integrity": "sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.5", + "@babel/plugin-transform-react-jsx-self": "^7.23.3", + "@babel/plugin-transform-react-jsx-source": "^7.23.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0" + } + }, + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001571", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001571.tgz", + "integrity": "sha512-tYq/6MoXhdezDLFZuCO/TKboTzuQ/xR5cFdgXPfDtM7/kchBO3b4VWghE/OAi/DV7tTdhmLjZiZBZi1fA/GheQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "devOptional": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/dijkstrajs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", + "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==" + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.616", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.616.tgz", + "integrity": "sha512-1n7zWYh8eS0L9Uy+GskE0lkBUNK83cXTVJI0pU3mGprFsbfSdAc15VTFbo+A+Bq4pwstmL30AVcEU3Fo463lNg==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/esbuild": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.10.tgz", + "integrity": "sha512-S1Y27QGt/snkNYrRcswgRFqZjaTG5a5xM3EQo97uNBnH505pdzSNe/HLBq1v0RO7iK/ngdbhJB6mDAp0OK+iUA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.10", + "@esbuild/android-arm": "0.19.10", + "@esbuild/android-arm64": "0.19.10", + "@esbuild/android-x64": "0.19.10", + "@esbuild/darwin-arm64": "0.19.10", + "@esbuild/darwin-x64": "0.19.10", + "@esbuild/freebsd-arm64": "0.19.10", + "@esbuild/freebsd-x64": "0.19.10", + "@esbuild/linux-arm": "0.19.10", + "@esbuild/linux-arm64": "0.19.10", + "@esbuild/linux-ia32": "0.19.10", + "@esbuild/linux-loong64": "0.19.10", + "@esbuild/linux-mips64el": "0.19.10", + "@esbuild/linux-ppc64": "0.19.10", + "@esbuild/linux-riscv64": "0.19.10", + "@esbuild/linux-s390x": "0.19.10", + "@esbuild/linux-x64": "0.19.10", + "@esbuild/netbsd-x64": "0.19.10", + "@esbuild/openbsd-x64": "0.19.10", + "@esbuild/sunos-x64": "0.19.10", + "@esbuild/win32-arm64": "0.19.10", + "@esbuild/win32-ia32": "0.19.10", + "@esbuild/win32-x64": "0.19.10" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.5.tgz", + "integrity": "sha512-D53FYKJa+fDmZMtriODxvhwrO+IOqrxoEo21gMA0sjHdU6dPVH4OhyFip9ypl8HOF5RV5KdTo+rBQLvnY2cO8w==", + "dev": true, + "peerDependencies": { + "eslint": ">=7" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", + "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/postcss": { + "version": "8.4.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", + "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qrcode": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", + "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", + "dependencies": { + "dijkstrajs": "^1.0.1", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "bin": { + "qrcode": "bin/qrcode" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-refresh": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", + "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.1.tgz", + "integrity": "sha512-pgPO9DWzLoW/vIhlSoDByCzcpX92bKEorbgXuZrqxByte3JFk2xSW2JEeAcyLc9Ru9pqcNNW+Ob7ntsk2oT/Xw==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.9.1", + "@rollup/rollup-android-arm64": "4.9.1", + "@rollup/rollup-darwin-arm64": "4.9.1", + "@rollup/rollup-darwin-x64": "4.9.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.9.1", + "@rollup/rollup-linux-arm64-gnu": "4.9.1", + "@rollup/rollup-linux-arm64-musl": "4.9.1", + "@rollup/rollup-linux-riscv64-gnu": "4.9.1", + "@rollup/rollup-linux-x64-gnu": "4.9.1", + "@rollup/rollup-linux-x64-musl": "4.9.1", + "@rollup/rollup-win32-arm64-msvc": "4.9.1", + "@rollup/rollup-win32-ia32-msvc": "4.9.1", + "@rollup/rollup-win32-x64-msvc": "4.9.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/vite": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.12.tgz", + "integrity": "sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==", + "dev": true, + "dependencies": { + "esbuild": "^0.19.3", + "postcss": "^8.4.32", + "rollup": "^4.2.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zustand": { + "version": "4.5.7", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz", + "integrity": "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==", + "dependencies": { + "use-sync-external-store": "^1.2.2" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0.6", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } + } + } +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/package.json b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/package.json new file mode 100644 index 00000000..6462d9a9 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/package.json @@ -0,0 +1,37 @@ +{ + "name": "ui-template", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite --port 3000", + "start": "vite --port 3000", + "build": "tsc && vite build", + "copy": "mkdir -p ../pkg/ui && rm -rf ../pkg/ui/* && cp -r dist/* ../pkg/ui/", + "build:copy": "npm run build && npm run copy", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview" + }, + "dependencies": { + "@hyperware-ai/client-api": "^0.1.4", + "qrcode": "^1.5.4", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "zustand": "^4.5.7" + }, + "devDependencies": { + "@types/node": "^20.10.4", + "@types/qrcode": "^1.5.5", + "@types/react": "^18.2.43", + "@types/react-dom": "^18.2.17", + "@typescript-eslint/eslint-plugin": "^6.14.0", + "@typescript-eslint/parser": "^6.14.0", + "@vitejs/plugin-react": "^4.2.1", + "eslint": "^8.55.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.5", + "http-proxy-middleware": "^2.0.6", + "typescript": "^5.2.2", + "vite": "^5.0.8" + } +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/App.css b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/App.css new file mode 100644 index 00000000..ea483108 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/App.css @@ -0,0 +1,167 @@ +/* Root styles moved to index.css */ + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: filter 300ms; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 1em; +} + +.read-the-docs { + color: #888; +} + +.message-list { + display: flex; + flex-direction: column; + margin-bottom: 0.5em; + text-align: left; +} + +.message-list li { + margin-bottom: 1em; + padding: 1em; + border-radius: 0.5em; + background-color: #f5f5f5; + border: 1px solid #e0e0e0; + overflow-wrap: break-word; + width: 90%; +} + +.signed-message { + display: flex; + flex-direction: column; + gap: 0.5em; +} + +.message-content { + display: flex; + flex-direction: column; + gap: 0.5em; +} + +.message-text { + font-weight: 500; +} + +.message-signature { + font-family: monospace; + font-size: 0.85em; + color: #666; + background-color: #efefef; + padding: 0.5em; + border-radius: 0.3em; + border: 1px solid #ddd; + overflow-x: auto; +} + +.verification { + display: flex; + align-items: center; + gap: 1em; + margin-top: 0.5em; +} + +.verify-button { + background-color: #4b9ad8; + border: none; + color: white; + padding: 0.5em 1em; + border-radius: 0.3em; + cursor: pointer; + font-size: 0.9em; +} + +.verify-button:hover { + background-color: #357abd; +} + +.verification-result { + font-size: 1.2em; + font-weight: bold; + padding: 0.2em 0.5em; + border-radius: 50%; + display: inline-flex; + align-items: center; + justify-content: center; +} + +.verification-result.verified { + color: white; + background-color: #4caf50; +} + +.verification-result.failed { + color: white; + background-color: #f44336; +} + +.node-not-connected { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + background-color: rgba(255, 255, 255, 0.9); + z-index: 1000; +} + +.input-row { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + width: 100%; +} + +.input-row > button { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + padding: 0.5em 1.2em; + background-color: #4b9ad8; + color: white; + font-weight: 600; +} + +.input-row > button:hover { + background-color: #357abd; +} + +.input-row > input { + border: 1px solid #ccc; + padding: 0.5em 0.8em; + font-size: 1em; + border-radius: 0.25em; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + width: 100%; +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/App.tsx b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/App.tsx new file mode 100644 index 00000000..773fe64c --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/App.tsx @@ -0,0 +1,66 @@ +import { useState, useEffect } from "react"; +import HyperwareClientApi from "@hyperware-ai/client-api"; +import "./App.css"; +import FileExplorer from "./components/FileExplorer/FileExplorer"; +import { ThemeProvider } from "./contexts/ThemeContext"; + +const BASE_URL = import.meta.env.BASE_URL; +if (window.our) window.our.process = BASE_URL?.replace("/", ""); + +const PROXY_TARGET = `${(import.meta.env.VITE_NODE_URL || "http://localhost:8080")}${BASE_URL}`; + +const WEBSOCKET_URL = import.meta.env.DEV + ? `${PROXY_TARGET.replace('http', 'ws')}` + : undefined; + +function App() { + const [nodeConnected, setNodeConnected] = useState(true); + const [api, setApi] = useState(); + + useEffect(() => { + // Connect to the Hyperdrive via websocket + console.log('WEBSOCKET URL', WEBSOCKET_URL) + if (window.our?.node && window.our?.process) { + const api = new HyperwareClientApi({ + uri: WEBSOCKET_URL, + nodeId: window.our.node, + processId: window.our.process, + onOpen: (_event, _api) => { + console.log("Connected to Hyperware"); + }, + onMessage: (json, _api) => { + console.log('WEBSOCKET MESSAGE', json) + try { + const data = JSON.parse(json); + console.log("WebSocket received message", data); + } catch (error) { + console.error("Error parsing WebSocket message", error); + } + }, + }); + + setApi(api); + } else { + setNodeConnected(false); + } + }, []); + + return ( + +
+ {!nodeConnected && ( +
+

Node not connected

+

+ You need to start a node at {PROXY_TARGET} before you can use this UI + in development. +

+
+ )} + {nodeConnected && } +
+
+ ); +} + +export default App; \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/assets/react.svg b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/assets/react.svg new file mode 100644 index 00000000..6c87de9b --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/assets/vite.svg b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/assets/vite.svg new file mode 100644 index 00000000..e7b8dfb1 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/assets/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/ContextMenu/ContextMenu.css b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/ContextMenu/ContextMenu.css new file mode 100644 index 00000000..3840b150 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/ContextMenu/ContextMenu.css @@ -0,0 +1,37 @@ +.context-menu { + position: fixed; + background-color: var(--bg-primary); + border: 1px solid var(--border-color); + border-radius: 4px; + box-shadow: 0 2px 8px var(--shadow-color); + padding: 4px 0; + min-width: 160px; + z-index: 1000; + /* Ensure context menu appears above iOS touch callouts */ + -webkit-touch-callout: none; + -webkit-user-select: none; + user-select: none; +} + +.context-menu button { + display: block; + width: 100%; + padding: 8px 16px; + border: none; + background: none; + text-align: left; + cursor: pointer; + font-size: 14px; + color: var(--text-primary); + transition: background-color 0.2s; +} + +.context-menu button:hover { + background-color: var(--bg-hover); +} + +.context-menu hr { + margin: 4px 0; + border: none; + border-top: 1px solid var(--border-color); +} \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/ContextMenu/ContextMenu.tsx b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/ContextMenu/ContextMenu.tsx new file mode 100644 index 00000000..6564be00 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/ContextMenu/ContextMenu.tsx @@ -0,0 +1,130 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { FileExplorer } from '../../lib/api'; +import useFileExplorerStore from '../../store/fileExplorer'; +import './ContextMenu.css'; + +interface ContextMenuProps { + position: { x: number; y: number }; + file: FileExplorer.FileInfo; + onClose: () => void; + onShare: () => void; + onDelete: () => void; + openedByTouch?: boolean; +} + +const ContextMenu: React.FC = ({ position, file, onClose, onShare, onDelete, openedByTouch }) => { + const menuRef = useRef(null); + const { isFileShared, removeSharedLink } = useFileExplorerStore(); + const isShared = !file.is_directory && isFileShared(file.path); + + // Track if a new touch has started after menu opened + const touchStartedRef = useRef(false); + + useEffect(() => { + // For touch-opened menus, delay adding the outside click handlers + // This prevents the menu from immediately closing on iOS + let timeoutId: number | undefined; + + const handleClickOutside = (e: MouseEvent) => { + if (menuRef.current && !menuRef.current.contains(e.target as Node)) { + onClose(); + } + }; + + const handleTouchOutside = (e: TouchEvent) => { + // If the touch is inside the menu, don't close + if (menuRef.current && menuRef.current.contains(e.target as Node)) { + return; + } + + // For touch-opened menus, only close on deliberate outside tap + if (openedByTouch) { + // Check if this is a new touch interaction (not the same one that opened the menu) + const touch = e.touches[0]; + if (touch) { + // Store this touch interaction + touchStartedRef.current = true; + } + } else { + // For non-touch opened menus, close immediately + onClose(); + } + }; + + const handleTouchEndOutside = (e: TouchEvent) => { + // Only close if menu was opened by touch and user tapped outside + if (openedByTouch && touchStartedRef.current) { + if (menuRef.current && !menuRef.current.contains(e.target as Node)) { + onClose(); + } + } + touchStartedRef.current = false; + }; + + if (openedByTouch) { + // Delay adding touch handlers for touch-opened menus + timeoutId = window.setTimeout(() => { + document.addEventListener('touchstart', handleTouchOutside, { passive: false }); + document.addEventListener('touchend', handleTouchEndOutside, { passive: false }); + }, 100); // Small delay to let the opening touch complete + } else { + // Add handlers immediately for mouse-opened menus + document.addEventListener('mousedown', handleClickOutside); + } + + return () => { + if (timeoutId) { + clearTimeout(timeoutId); + } + document.removeEventListener('mousedown', handleClickOutside); + document.removeEventListener('touchstart', handleTouchOutside); + document.removeEventListener('touchend', handleTouchEndOutside); + }; + }, [onClose, openedByTouch]); + + const handleUnshare = async () => { + try { + await FileExplorer.unshare_file(file.path); + removeSharedLink(file.path); + onClose(); + } catch (err) { + console.error('Failed to unshare file:', err); + } + }; + + + return ( +
+ + + + {!file.is_directory && ( + isShared ? ( + + ) : ( + + ) + )} +
+ +
+ ); +}; + +export default ContextMenu; diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/Breadcrumb.css b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/Breadcrumb.css new file mode 100644 index 00000000..283eb2fe --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/Breadcrumb.css @@ -0,0 +1,70 @@ +.breadcrumb-container { + position: relative; + background-color: var(--bg-secondary); + border-bottom: 1px solid var(--border-color); + flex-shrink: 0; +} + +.breadcrumb { + display: flex; + align-items: center; + padding: 8px 16px; + overflow-x: auto; + scroll-behavior: smooth; + -webkit-overflow-scrolling: touch; + scrollbar-width: thin; + scrollbar-color: var(--text-secondary) transparent; +} + +/* Custom scrollbar styling */ +.breadcrumb::-webkit-scrollbar { + height: 4px; +} + +.breadcrumb::-webkit-scrollbar-track { + background: transparent; +} + +.breadcrumb::-webkit-scrollbar-thumb { + background-color: var(--text-secondary); + border-radius: 2px; +} + +.breadcrumb-item { + padding: 4px 8px; + background: none; + border: none; + cursor: pointer; + color: var(--link-color); + font-size: 14px; + transition: color 0.2s; + white-space: nowrap; + flex-shrink: 0; +} + +.breadcrumb-item:hover { + text-decoration: underline; + color: var(--link-hover); +} + +.breadcrumb-separator { + margin: 0 4px; + color: var(--text-secondary); + flex-shrink: 0; +} + +/* Mobile adjustments */ +@media (max-width: 480px) { + .breadcrumb { + padding: 6px 12px; + } + + .breadcrumb-item { + font-size: 13px; + padding: 4px 6px; + } + + .breadcrumb-separator { + margin: 0 2px; + } +} \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/Breadcrumb.tsx b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/Breadcrumb.tsx new file mode 100644 index 00000000..6eea6d8e --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/Breadcrumb.tsx @@ -0,0 +1,49 @@ +import React from 'react'; +import './Breadcrumb.css'; + +interface BreadcrumbProps { + currentPath: string; + onNavigate: (path: string) => void; +} + +const Breadcrumb: React.FC = ({ currentPath, onNavigate }) => { + const pathParts = currentPath.split('/').filter(Boolean); + const scrollRef = React.useRef(null); + + // Scroll to the end when path changes + React.useEffect(() => { + if (scrollRef.current) { + scrollRef.current.scrollLeft = scrollRef.current.scrollWidth; + } + }, [currentPath]); + + return ( +
+
+ + + {pathParts.map((part, index) => { + const path = '/' + pathParts.slice(0, index + 1).join('/'); + return ( + + / + + + ); + })} +
+
+ ); +}; + +export default Breadcrumb; \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/FileExplorer.css b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/FileExplorer.css new file mode 100644 index 00000000..a78bbcca --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/FileExplorer.css @@ -0,0 +1,18 @@ +.file-explorer { + display: flex; + flex-direction: column; + height: 100%; + background-color: var(--bg-primary); + color: var(--text-primary); + overflow: hidden; +} + +.error-message { + background-color: var(--bg-secondary); + color: var(--error-color); + padding: 12px; + margin: 8px; + border-radius: 4px; + border: 1px solid var(--error-color); + opacity: 0.9; +} \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/FileExplorer.tsx b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/FileExplorer.tsx new file mode 100644 index 00000000..a317c949 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/FileExplorer.tsx @@ -0,0 +1,311 @@ +import React, { useEffect, useState } from 'react'; +import useFileExplorerStore from '../../store/fileExplorer'; +import { FileExplorer as FileExplorerAPI } from '../../lib/api'; +import FileList from './FileList'; +import Breadcrumb from './Breadcrumb'; +import Toolbar from './Toolbar'; +import UploadZone from '../Upload/UploadZone'; +import './FileExplorer.css'; + +const FileExplorer: React.FC = () => { + const { + currentPath, + files, + selectedFiles, + loading, + error, + setCurrentPath, + setFiles, + setLoading, + setError, + clearSelection + } = useFileExplorerStore(); + + const [viewMode, setViewMode] = useState<'list' | 'grid'>('list'); + const [showNewMenu, setShowNewMenu] = useState(false); + const newMenuRef = React.useRef(null); + + // Close new menu when clicking outside + React.useEffect(() => { + const handleClickOutside = (e: MouseEvent) => { + if (newMenuRef.current && !newMenuRef.current.contains(e.target as Node)) { + setShowNewMenu(false); + } + }; + + if (showNewMenu) { + document.addEventListener('mousedown', handleClickOutside); + return () => document.removeEventListener('mousedown', handleClickOutside); + } + }, [showNewMenu]); + + const loadDirectory = async (path: string) => { + try { + setLoading(true); + setError(null); + const fileList = await FileExplorerAPI.list_directory(path); + + // Backend returns files for the requested directory with 2 levels of depth + // We need to include all files so the tree structure works, but we'll filter + // what's shown at the top level in FileList + const filteredFiles = fileList.filter(file => { + if (file.path === path) return false; // Exclude the directory itself + + // For the tree to work properly, we need to include all files + // The FileList component will handle showing only direct children at top level + return true; + }); + + setFiles(filteredFiles); + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to load directory'); + } finally { + setLoading(false); + } + }; + + const loadSubdirectory = async (path: string): Promise => { + try { + const fileList = await FileExplorerAPI.list_directory(path); + + // Filter out the directory itself and return only its contents + const filteredFiles = fileList.filter(file => { + if (file.path === path) return false; // Exclude the directory itself + return true; + }); + + return filteredFiles; + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to load subdirectory'); + return []; + } + }; + + // Initialize with home directory on first load + useEffect(() => { + const initializeDirectory = async () => { + try { + const cwd = await FileExplorerAPI.get_current_directory(); + setCurrentPath(cwd); + } catch (err) { + // If getting cwd fails, fall back to root + console.error('Failed to get current directory:', err); + setCurrentPath('/'); + } + }; + + initializeDirectory(); + }, []); + + // Load directory whenever path changes + useEffect(() => { + if (currentPath) { + loadDirectory(currentPath); + } + }, [currentPath]); + + const handleNavigate = (path: string) => { + clearSelection(); + setCurrentPath(path); + }; + + const handleCreateFolder = async () => { + setShowNewMenu(false); + const folderName = prompt('Enter folder name:'); + if (!folderName) return; + + const newPath = currentPath === '/' + ? `/${folderName}` + : `${currentPath}/${folderName}`; + + try { + await FileExplorerAPI.create_directory(newPath); + await loadDirectory(currentPath); + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to create folder'); + } + }; + + const handleCreateFile = async () => { + setShowNewMenu(false); + const fileName = prompt('Enter file name:'); + if (!fileName) return; + + const newPath = currentPath === '/' + ? `/${fileName}` + : `${currentPath}/${fileName}`; + + try { + // Create an empty file + await FileExplorerAPI.create_file(newPath, []); + await loadDirectory(currentPath); + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to create file'); + } + }; + + const handleDelete = async () => { + if (selectedFiles.length === 0) return; + + if (!confirm(`Delete ${selectedFiles.length} item(s)?`)) return; + + try { + for (const path of selectedFiles) { + const file = files.find(f => f.path === path); + if (file?.is_directory) { + await FileExplorerAPI.delete_directory(path); + } else { + await FileExplorerAPI.delete_file(path); + } + } + clearSelection(); + await loadDirectory(currentPath); + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to delete items'); + } + }; + + const handleRefresh = () => { + loadDirectory(currentPath); + }; + + const handleNewMenu = () => { + setShowNewMenu(!showNewMenu); + }; + + const handleFileUpload = () => { + const fileInput = document.createElement('input'); + fileInput.type = 'file'; + fileInput.multiple = true; + + fileInput.onchange = async (e) => { + const target = e.target as HTMLInputElement; + const files = target.files; + if (!files || files.length === 0) return; + + // Trigger the upload process for each file + const event = new CustomEvent('upload-files', { + detail: { files: Array.from(files) } + }); + window.dispatchEvent(event); + }; + + fileInput.click(); + }; + + const handleFolderUpload = () => { + const fileInput = document.createElement('input'); + fileInput.type = 'file'; + fileInput.multiple = true; + // Enable folder selection + fileInput.webkitdirectory = true; + (fileInput as any).directory = true; + + fileInput.onchange = async (e) => { + const target = e.target as HTMLInputElement; + const files = target.files; + if (!files || files.length === 0) return; + + // Trigger the upload process for each file + const event = new CustomEvent('upload-files', { + detail: { files: Array.from(files) } + }); + window.dispatchEvent(event); + }; + + fileInput.click(); + }; + + return ( +
+ + + {showNewMenu && ( +
+ + +
+ )} + + + + {error && ( +
+ {error} +
+ )} + + loadDirectory(currentPath)} + > + loadDirectory(currentPath)} + /> + +
+ ); +}; + +export default FileExplorer; \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/FileItem.css b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/FileItem.css new file mode 100644 index 00000000..9e13843a --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/FileItem.css @@ -0,0 +1,115 @@ +.file-item { + display: flex; + align-items: center; + padding: 8px 12px; + cursor: pointer; + user-select: none; + border-radius: 4px; + transition: background-color 0.2s; + color: var(--text-primary); + position: relative; + /* Prevent iOS default touch behaviors */ + -webkit-touch-callout: none; + -webkit-tap-highlight-color: transparent; +} + +.file-item:hover { + background-color: var(--bg-hover); +} + +.file-item.selected { + background-color: var(--bg-selected); +} + +.file-item-list { + gap: 16px; +} + +.file-item-grid { + flex-direction: column; + text-align: left; + padding: 16px 8px; + align-items: flex-start; +} + +.file-icon { + font-size: 20px; + margin-right: 8px; + display: inline-flex; + align-items: center; +} + +.file-item-grid .file-icon { + font-size: 48px; + margin-bottom: 8px; + margin-right: 0; +} + +.file-icon.clickable-folder { + cursor: pointer; + transition: transform 0.2s; +} + +.file-icon.clickable-folder:hover { + transform: scale(1.1); +} + +.file-name { + flex: 1 1 auto; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + text-align: left; + min-width: 0; /* Allow flex item to shrink below content size */ + margin-right: 16px; +} + +.file-size, +.file-modified { + color: var(--text-secondary); + font-size: 14px; + flex: 0 0 auto; + text-align: right; +} + +.file-size { + min-width: 80px; + margin-right: 16px; +} + +.file-modified { + min-width: 100px; +} + +/* On small screens, hide other columns to prioritize file name */ +@media (max-width: 768px) { + .file-modified { + display: none; + } +} + +@media (max-width: 480px) { + .file-size { + display: none; + } + + .file-name { + margin-right: 8px; + } +} + +.file-children { + /* Nested files container */ +} + +.shared-indicator { + font-size: 16px; + margin-left: 8px; + opacity: 0.7; + transition: opacity 0.2s; + cursor: help; +} + +.file-item:hover .shared-indicator { + opacity: 1; +} \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/FileItem.tsx b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/FileItem.tsx new file mode 100644 index 00000000..f97bbfdd --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/FileItem.tsx @@ -0,0 +1,311 @@ +import React, { useState, useRef, useEffect } from 'react'; +import { FileExplorer } from '../../lib/api'; +import useFileExplorerStore from '../../store/fileExplorer'; +import ContextMenu from '../ContextMenu/ContextMenu'; +import ShareDialog from '../ShareDialog/ShareDialog'; +import './FileItem.css'; + +interface FileItemProps { + file: FileExplorer.FileInfo & { children?: FileExplorer.FileInfo[] }; + viewMode: 'list' | 'grid'; + onNavigate: (path: string) => void; + depth?: number; + onLoadSubdirectory?: (path: string) => Promise; + onDelete?: () => void; +} + +const FileItem: React.FC = ({ file, viewMode, onNavigate, depth = 0, onLoadSubdirectory, onDelete }) => { + const { selectedFiles, toggleFileSelection, isFileShared } = useFileExplorerStore(); + const [contextMenuOpen, setContextMenuOpen] = useState(false); + const [contextMenuPosition, setContextMenuPosition] = useState({ x: 0, y: 0 }); + const [shareDialogOpen, setShareDialogOpen] = useState(false); + const [menuOpenedByTouch, setMenuOpenedByTouch] = useState(false); + + const isSelected = selectedFiles.includes(file.path); + const isShared = !file.is_directory && isFileShared(file.path); + + const [isExpanded, setIsExpanded] = useState(false); + const [childrenLoaded, setChildrenLoaded] = useState(false); + const [loadedChildren, setLoadedChildren] = useState<(FileExplorer.FileInfo & { children?: FileExplorer.FileInfo[] })[]>([]); + + // Touch handling for iOS long-press + const touchTimerRef = useRef(null); + const touchStartPos = useRef<{ x: number; y: number } | null>(null); + const longPressTriggered = useRef(false); + + const handleClick = (e: React.MouseEvent) => { + if (e.ctrlKey || e.metaKey) { + toggleFileSelection(file.path); + } else if (file.is_directory) { + // Single click navigates into directories + onNavigate(file.path); + } + // Remove file selection on single click - no action for files + }; + + const buildTreeFromFlatList = (flatList: FileExplorer.FileInfo[], parentPath: string): (FileExplorer.FileInfo & { children?: FileExplorer.FileInfo[] })[] => { + const fileMap = new Map(); + const topLevelFiles: (FileExplorer.FileInfo & { children?: FileExplorer.FileInfo[] })[] = []; + + // First pass: create map of all files + flatList.forEach(file => { + fileMap.set(file.path, { ...file, children: [] }); + }); + + // Second pass: build parent-child relationships + flatList.forEach(file => { + const fileWithChildren = fileMap.get(file.path)!; + const fileParentPath = file.path.substring(0, file.path.lastIndexOf('/')); + + if (fileMap.has(fileParentPath)) { + // This file has a parent in our list + const parent = fileMap.get(fileParentPath)!; + if (!parent.children) parent.children = []; + parent.children.push(fileWithChildren); + } else if (fileParentPath === parentPath) { + // This is a direct child of the parent directory + topLevelFiles.push(fileWithChildren); + } + }); + + // Sort files: directories first, then by name + const sortFiles = (files: (FileExplorer.FileInfo & { children?: FileExplorer.FileInfo[] })[]) => { + return [...files].sort((a, b) => { + if (a.is_directory && !b.is_directory) return -1; + if (!a.is_directory && b.is_directory) return 1; + return a.name.localeCompare(b.name); + }); + }; + + // Recursively sort all children + const sortRecursive = (files: (FileExplorer.FileInfo & { children?: FileExplorer.FileInfo[] })[]) => { + const sorted = sortFiles(files); + sorted.forEach(file => { + if (file.children && file.children.length > 0) { + file.children = sortRecursive(file.children); + } + }); + return sorted; + }; + + return sortRecursive(topLevelFiles); + }; + + const handleExpandToggle = async (e: React.MouseEvent) => { + e.stopPropagation(); + + // If expanding and we haven't loaded children yet, load them + if (!isExpanded && file.is_directory && !childrenLoaded && onLoadSubdirectory) { + const flatChildren = await onLoadSubdirectory(file.path); + const treeChildren = buildTreeFromFlatList(flatChildren, file.path); + setLoadedChildren(treeChildren); + setChildrenLoaded(true); + } + + setIsExpanded(!isExpanded); + }; + + const handleContextMenu = (e: React.MouseEvent) => { + e.preventDefault(); + setContextMenuPosition({ x: e.clientX, y: e.clientY }); + setMenuOpenedByTouch(false); + setContextMenuOpen(true); + }; + + // Touch event handlers for iOS compatibility + const handleTouchStart = (e: React.TouchEvent) => { + const touch = e.touches[0]; + touchStartPos.current = { x: touch.clientX, y: touch.clientY }; + longPressTriggered.current = false; + + // Start long press timer (500ms) + touchTimerRef.current = window.setTimeout(() => { + if (touchStartPos.current) { + longPressTriggered.current = true; + // Trigger context menu + setContextMenuPosition({ x: touchStartPos.current.x, y: touchStartPos.current.y }); + setMenuOpenedByTouch(true); + setContextMenuOpen(true); + // Prevent default touch behavior + e.preventDefault(); + } + }, 500); + }; + + const handleTouchMove = (e: React.TouchEvent) => { + // If the touch moves more than 10px, cancel the long press + if (touchStartPos.current && touchTimerRef.current) { + const touch = e.touches[0]; + const deltaX = Math.abs(touch.clientX - touchStartPos.current.x); + const deltaY = Math.abs(touch.clientY - touchStartPos.current.y); + + if (deltaX > 10 || deltaY > 10) { + if (touchTimerRef.current) { + clearTimeout(touchTimerRef.current); + touchTimerRef.current = null; + } + } + } + }; + + const handleTouchEnd = (e: React.TouchEvent) => { + // Clear the timer + if (touchTimerRef.current) { + clearTimeout(touchTimerRef.current); + touchTimerRef.current = null; + } + + // If long press was triggered, prevent default click behavior + if (longPressTriggered.current) { + e.preventDefault(); + e.stopPropagation(); // Stop propagation to prevent menu from closing + longPressTriggered.current = false; + } else if (!e.defaultPrevented) { + // Normal tap - handle as click + if (file.is_directory) { + onNavigate(file.path); + } + } + + touchStartPos.current = null; + }; + + // Clean up timer on unmount + useEffect(() => { + return () => { + if (touchTimerRef.current) { + clearTimeout(touchTimerRef.current); + } + }; + }, []); + + const handleDelete = async () => { + if (!confirm(`Delete ${file.name}?`)) return; + + try { + if (file.is_directory) { + await FileExplorer.delete_directory(file.path); + } else { + await FileExplorer.delete_file(file.path); + } + // Call the parent's onDelete callback to refresh the list + if (onDelete) { + onDelete(); + } + } catch (err) { + console.error('Failed to delete:', err); + alert(`Failed to delete ${file.name}: ${err instanceof Error ? err.message : 'Unknown error'}`); + } + }; + + const getFileIcon = () => { + if (file.is_directory) { + return isExpanded ? '📂' : '📁'; + } + const ext = file.name.split('.').pop()?.toLowerCase(); + switch (ext) { + case 'txt': return '📄'; + case 'pdf': return '📕'; + case 'jpg': + case 'jpeg': + case 'png': + case 'gif': return '🖼️'; + case 'mp3': + case 'wav': return '🎵'; + case 'mp4': + case 'avi': return '🎬'; + case 'zip': + case 'rar': return '📦'; + default: return '📄'; + } + }; + + const formatFileSize = (bytes: number) => { + if (bytes === 0) return '0 B'; + const k = 1024; + const sizes = ['B', 'KB', 'MB', 'GB']; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; + }; + + // Determine which children to use - loaded children take precedence + const childrenToRender = childrenLoaded ? loadedChildren : (file.children || []); + const hasChildren = file.is_directory && (childrenToRender.length > 0 || !childrenLoaded); + + return ( + <> +
+ + {getFileIcon()} + + {file.name} + {isShared && ( + + 🔗 + + )} + {viewMode === 'list' && ( + <> + + {file.is_directory ? `${file.size} items` : formatFileSize(file.size)} + + + {file.modified ? new Date(file.modified * 1000).toLocaleDateString() : '-'} + + + )} +
+ + + {isExpanded && viewMode === 'list' && childrenToRender.length > 0 && ( +
+ {childrenToRender.map((child) => ( + + ))} +
+ )} + + {contextMenuOpen && ( + setContextMenuOpen(false)} + onShare={() => { + setShareDialogOpen(true); + setContextMenuOpen(false); + }} + onDelete={handleDelete} + openedByTouch={menuOpenedByTouch} + /> + )} + + {shareDialogOpen && ( + setShareDialogOpen(false)} + /> + )} + + ); +}; + +export default FileItem; diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/FileList.css b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/FileList.css new file mode 100644 index 00000000..b544f138 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/FileList.css @@ -0,0 +1,30 @@ +.file-list { + flex: 1; + overflow-y: auto; + overflow-x: hidden; + padding: 16px; + background-color: var(--bg-primary); + min-height: 0; /* Important for flex children with overflow */ +} + +.file-list-loading, +.file-list-empty { + display: flex; + align-items: center; + justify-content: center; + height: 100%; + color: var(--text-secondary); + font-size: 16px; +} + +.file-list-list { + display: flex; + flex-direction: column; + gap: 2px; +} + +.file-list-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); + gap: 16px; +} \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/FileList.tsx b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/FileList.tsx new file mode 100644 index 00000000..2f38a20a --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/FileList.tsx @@ -0,0 +1,104 @@ +import React from 'react'; +import { FileExplorer } from '../../lib/api'; +import FileItem from './FileItem'; +import './FileList.css'; + +interface FileListProps { + files: FileExplorer.FileInfo[]; + viewMode: 'list' | 'grid'; + loading: boolean; + onNavigate: (path: string) => void; + currentPath: string; + onLoadSubdirectory?: (path: string) => Promise; + onDelete?: () => void; +} + +const FileList: React.FC = ({ files, viewMode, loading, onNavigate, currentPath, onLoadSubdirectory, onDelete }) => { + if (loading) { + return
Loading...
; + } + + if (files.length === 0) { + return
No files in this directory
; + } + + // Build tree structure from flat list + const fileMap = new Map(); + const topLevelFiles: (FileExplorer.FileInfo & { children?: FileExplorer.FileInfo[] })[] = []; + + // First pass: create map of all files + files.forEach(file => { + fileMap.set(file.path, { ...file, children: [] }); + }); + + // Second pass: build ALL parent-child relationships first + files.forEach(file => { + const fileWithChildren = fileMap.get(file.path)!; + const parentPath = file.path.substring(0, file.path.lastIndexOf('/')); + + + if (fileMap.has(parentPath)) { + // This file has a parent in our list + const parent = fileMap.get(parentPath)!; + if (!parent.children) parent.children = []; + parent.children.push(fileWithChildren); + } + }); + + // Third pass: determine what goes at the top level + // Handle potential leading slash mismatch between breadcrumb and double-click navigation + const normalizedCurrentPath = currentPath.startsWith('/') && currentPath !== '/' + ? currentPath.substring(1) + : currentPath; + const expectedParent = normalizedCurrentPath === '/' ? '' : normalizedCurrentPath; + + files.forEach(file => { + const fileWithChildren = fileMap.get(file.path)!; + const parentPath = file.path.substring(0, file.path.lastIndexOf('/')); + + // Only add to top level if it's a direct child of current directory and has no parent in the list + if (!fileMap.has(parentPath) && parentPath === expectedParent) { + topLevelFiles.push(fileWithChildren); + } + }); + + // Sort files: directories first, then by name + const sortFiles = (files: (FileExplorer.FileInfo & { children?: FileExplorer.FileInfo[] })[]) => { + return [...files].sort((a, b) => { + if (a.is_directory && !b.is_directory) return -1; + if (!a.is_directory && b.is_directory) return 1; + return a.name.localeCompare(b.name); + }); + }; + + // Recursively sort all children + const sortRecursive = (files: (FileExplorer.FileInfo & { children?: FileExplorer.FileInfo[] })[]) => { + const sorted = sortFiles(files); + sorted.forEach(file => { + if (file.children && file.children.length > 0) { + file.children = sortRecursive(file.children); + } + }); + return sorted; + }; + + const sortedFiles = sortRecursive(topLevelFiles); + + return ( +
+ {sortedFiles.map((file) => ( + + ))} +
+ ); +}; + +export default FileList; \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/Toolbar.css b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/Toolbar.css new file mode 100644 index 00000000..2e563128 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/Toolbar.css @@ -0,0 +1,47 @@ +.toolbar { + display: flex; + justify-content: space-between; + padding: 8px 16px; + background-color: var(--bg-secondary); + border-bottom: 1px solid var(--border-color); + flex-shrink: 0; +} + +.toolbar-group { + display: flex; + gap: 8px; +} + +.toolbar button { + padding: 6px 12px; + border: 1px solid var(--border-color); + background-color: var(--bg-primary); + color: var(--text-primary); + cursor: pointer; + border-radius: 4px; + transition: background-color 0.2s, border-color 0.2s; +} + +.toolbar button.icon-button { + padding: 6px 10px; + font-size: 18px; + min-width: 36px; + display: flex; + align-items: center; + justify-content: center; +} + +.toolbar button:hover:not(:disabled) { + background-color: var(--bg-hover); + border-color: var(--text-secondary); +} + +.toolbar button:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.toolbar button.active { + background-color: var(--bg-selected); + border-color: var(--link-color); +} \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/Toolbar.tsx b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/Toolbar.tsx new file mode 100644 index 00000000..0d669aed --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/FileExplorer/Toolbar.tsx @@ -0,0 +1,55 @@ +import React from 'react'; +import './Toolbar.css'; + +interface ToolbarProps { + viewMode: 'list' | 'grid'; + onViewModeChange: (mode: 'list' | 'grid') => void; + onNewMenu: () => void; + onUploadFiles: () => void; + onUploadFolder: () => void; + onRefresh: () => void; +} + +const Toolbar: React.FC = ({ + viewMode, + onViewModeChange, + onNewMenu, + onUploadFiles, + onUploadFolder, + onRefresh +}) => { + const toggleViewMode = () => { + onViewModeChange(viewMode === 'list' ? 'grid' : 'list'); + }; + + return ( +
+
+ + + + +
+ +
+ +
+
+ ); +}; + +export default Toolbar; \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/ShareDialog/ShareDialog.css b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/ShareDialog/ShareDialog.css new file mode 100644 index 00000000..79f42251 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/ShareDialog/ShareDialog.css @@ -0,0 +1,193 @@ +.share-dialog-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; +} + +.share-dialog { + background-color: var(--bg-primary); + color: var(--text-primary); + border-radius: 8px; + padding: 24px; + width: 90%; + max-width: 500px; + max-height: 90vh; + overflow-y: auto; + box-shadow: 0 4px 16px var(--shadow-color); + border: 1px solid var(--border-color); +} + +.share-dialog h3 { + margin-top: 0; + margin-bottom: 16px; + word-break: break-word; + font-size: 1.2rem; +} + +.share-options { + display: flex; + flex-direction: column; + gap: 12px; + margin-bottom: 20px; +} + +.share-options label { + display: flex; + align-items: center; + gap: 8px; + cursor: pointer; + color: var(--text-primary); +} + +.share-button { + width: 100%; + padding: 10px; + background-color: var(--link-color); + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + font-size: 16px; + transition: background-color 0.2s; +} + +.share-button:hover:not(:disabled) { + background-color: var(--link-hover); +} + +.share-button:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +.share-link-container { + display: flex; + gap: 8px; + margin-top: 16px; + flex-wrap: wrap; +} + +.share-link-input { + flex: 1; + min-width: 0; + padding: 8px; + border: 1px solid var(--border-color); + background-color: var(--bg-secondary); + color: var(--text-primary); + border-radius: 4px; + font-family: monospace; + font-size: 12px; + word-break: break-all; +} + +.share-link-container button { + flex-shrink: 0; + padding: 8px 16px; + background-color: var(--bg-secondary); + color: var(--text-primary); + border: 1px solid var(--border-color); + border-radius: 4px; + cursor: pointer; + transition: background-color 0.2s; +} + +.share-link-container button:hover { + background-color: var(--bg-hover); +} + +.dialog-actions { + display: flex; + justify-content: flex-end; + margin-top: 20px; + gap: 8px; +} + +.dialog-actions button { + padding: 8px 16px; + border: 1px solid var(--border-color); + background-color: var(--bg-secondary); + color: var(--text-primary); + border-radius: 4px; + cursor: pointer; + transition: background-color 0.2s; +} + +.dialog-actions button:hover { + background-color: var(--bg-hover); +} + +.loading-container { + text-align: center; + padding: 20px 0; +} + +.share-success-message { + background-color: #d4edda; + color: #155724; + padding: 12px; + border-radius: 4px; + margin-bottom: 16px; + text-align: center; +} + +.qr-container { + margin-top: 20px; + text-align: center; + padding: 16px; + background-color: var(--bg-secondary); + border-radius: 8px; + border: 1px solid var(--border-color); +} + +.qr-code canvas, +.qr-code img { + border: 1px solid var(--border-color); + border-radius: 4px; + max-width: 200px; + width: 100%; + height: auto; + display: block; + margin: 0 auto; +} + +/* Mobile responsiveness */ +@media (max-width: 480px) { + .share-dialog { + padding: 16px; + width: 95%; + } + + .share-dialog h3 { + font-size: 1rem; + } + + .share-link-input { + font-size: 11px; + padding: 6px; + } + + .share-link-container { + flex-direction: column; + } + + .share-link-container button { + width: 100%; + } + + .qr-code canvas, + .qr-code img { + max-width: 150px; + } + + .share-success-message { + font-size: 0.9rem; + padding: 10px; + } +} \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/ShareDialog/ShareDialog.tsx b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/ShareDialog/ShareDialog.tsx new file mode 100644 index 00000000..d88efb86 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/ShareDialog/ShareDialog.tsx @@ -0,0 +1,193 @@ +import React, { useState, useEffect, useRef } from 'react'; +import { FileExplorer } from '../../lib/api'; +import useFileExplorerStore from '../../store/fileExplorer'; +import QRCode from 'qrcode'; +import './ShareDialog.css'; + +interface ShareDialogProps { + file: FileExplorer.FileInfo; + onClose: () => void; +} + +const ShareDialog: React.FC = ({ file, onClose }) => { + const [authScheme, setAuthScheme] = useState(FileExplorer.AuthScheme.Public); + const [shareLink, setShareLink] = useState(''); + const [loading, setLoading] = useState(false); + const [qrCodeDataUrl, setQrCodeDataUrl] = useState(''); + const [copied, setCopied] = useState(false); + const { addSharedLink } = useFileExplorerStore(); + const canvasRef = useRef(null); + + // Detect if we're in iOS standalone mode (PWA) + const isIosPwa = () => { + return (window.navigator as any).standalone === true || + window.matchMedia('(display-mode: standalone)').matches; + }; + + // Auto-generate share link on mount + useEffect(() => { + handleShare(); + }, []); + + // Generate QR code when share link is available + useEffect(() => { + if (shareLink) { + const generateQrCode = async () => { + try { + if (isIosPwa()) { + // For iOS PWA, use canvas rendering + if (canvasRef.current) { + await QRCode.toCanvas(canvasRef.current, shareLink, { + width: 200, + margin: 2, + color: { + dark: '#000000', + light: '#FFFFFF' + } + }); + } + } else { + // For desktop and regular mobile browsers, use data URL + const dataUrl = await QRCode.toDataURL(shareLink, { + width: 200, + margin: 2, + color: { + dark: '#000000', + light: '#FFFFFF' + } + }); + setQrCodeDataUrl(dataUrl); + } + } catch (err) { + console.error('Failed to generate QR code:', err); + } + }; + + generateQrCode(); + } + }, [shareLink]); + + const handleShare = async () => { + setLoading(true); + try { + const link = await FileExplorer.share_file(file.path, authScheme); + + // Remove first element of origin (e.g., http://foo.bar.com -> http://bar.com) + let origin = window.location.origin; + const urlParts = new URL(origin); + const hostParts = urlParts.hostname.split('.'); + if (hostParts.length > 2) { + // Remove the first subdomain + hostParts.shift(); + urlParts.hostname = hostParts.join('.'); + origin = urlParts.toString().replace(/\/$/, ''); // Remove trailing slash + } + + const fullLink = `${origin}${link}`; + setShareLink(fullLink); + addSharedLink(file.path, fullLink); + + // Auto-copy to clipboard with fallback + try { + await navigator.clipboard.writeText(fullLink); + setCopied(true); + } catch (clipboardErr) { + // Fallback for when clipboard API fails + const textArea = document.createElement('textarea'); + textArea.value = fullLink; + textArea.style.position = 'fixed'; + textArea.style.left = '-999999px'; + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + try { + document.execCommand('copy'); + setCopied(true); + } catch (e) { + console.error('Failed to copy to clipboard:', e); + } + document.body.removeChild(textArea); + } + } catch (err) { + console.error('Failed to share file:', err); + } finally { + setLoading(false); + } + }; + + const copyToClipboard = async () => { + try { + await navigator.clipboard.writeText(shareLink); + setCopied(true); + } catch (clipboardErr) { + // Fallback for when clipboard API fails + const textArea = document.createElement('textarea'); + textArea.value = shareLink; + textArea.style.position = 'fixed'; + textArea.style.left = '-999999px'; + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + try { + document.execCommand('copy'); + setCopied(true); + } catch (e) { + console.error('Failed to copy to clipboard:', e); + } + document.body.removeChild(textArea); + } + setTimeout(() => setCopied(false), 2000); + }; + + return ( +
+
e.stopPropagation()}> +

Share File: {file.name}

+ + {loading ? ( +
+

Generating share link...

+
+ ) : shareLink ? ( + <> +
+

✓ Share link created and copied to clipboard!

+
+ +
+ + +
+ + {shareLink && ( +
+
+ {isIosPwa() ? ( + + ) : ( + qrCodeDataUrl && QR Code + )} +
+
+ )} + + ) : ( +

Failed to generate share link

+ )} + +
+ +
+
+
+ ); +}; + +export default ShareDialog; diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/Upload/UploadZone.css b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/Upload/UploadZone.css new file mode 100644 index 00000000..5772d204 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/Upload/UploadZone.css @@ -0,0 +1,38 @@ +.upload-zone { + position: relative; + flex: 1; + display: flex; + flex-direction: column; +} + +.upload-zone.dragging { + background-color: rgba(33, 150, 243, 0.1); +} + +.upload-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(33, 150, 243, 0.2); + display: flex; + align-items: center; + justify-content: center; + pointer-events: none; + z-index: 10; +} + +[data-theme="dark"] .upload-overlay { + background-color: rgba(100, 181, 246, 0.2); +} + +.upload-message { + padding: 24px 48px; + background-color: var(--link-color); + color: white; + border-radius: 8px; + font-size: 18px; + font-weight: 500; + box-shadow: 0 4px 8px var(--shadow-color); +} \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/Upload/UploadZone.tsx b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/Upload/UploadZone.tsx new file mode 100644 index 00000000..921ca79b --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/components/Upload/UploadZone.tsx @@ -0,0 +1,187 @@ +import React, { useState, useRef } from 'react'; +import { FileExplorer } from '../../lib/api'; +import useFileExplorerStore from '../../store/fileExplorer'; +import './UploadZone.css'; + +interface UploadZoneProps { + currentPath: string; + onUploadComplete: () => void; + children: React.ReactNode; +} + +const UploadZone: React.FC = ({ currentPath, onUploadComplete, children }) => { + const [isDragging, setIsDragging] = useState(false); + const { updateUploadProgress, setError } = useFileExplorerStore(); + const dragCounter = useRef(0); + + // Listen for upload events from the toolbar + React.useEffect(() => { + const handleUploadEvent = async (e: CustomEvent) => { + const files = e.detail.files as File[]; + for (const file of files) { + await handleFileUpload(file); + } + }; + + window.addEventListener('upload-files', handleUploadEvent as EventListener); + return () => { + window.removeEventListener('upload-files', handleUploadEvent as EventListener); + }; + }, [currentPath, onUploadComplete]); + + const handleDrag = (e: React.DragEvent) => { + e.preventDefault(); + e.stopPropagation(); + }; + + const handleDragIn = (e: React.DragEvent) => { + e.preventDefault(); + e.stopPropagation(); + dragCounter.current++; + if (e.dataTransfer.items && e.dataTransfer.items.length > 0) { + setIsDragging(true); + } + }; + + const handleDragOut = (e: React.DragEvent) => { + e.preventDefault(); + e.stopPropagation(); + dragCounter.current--; + if (dragCounter.current === 0) { + setIsDragging(false); + } + }; + + const handleDrop = async (e: React.DragEvent) => { + e.preventDefault(); + e.stopPropagation(); + setIsDragging(false); + dragCounter.current = 0; + + // Handle both files and folders + const items = e.dataTransfer.items; + if (items) { + // Use DataTransferItemList interface when available + const files: File[] = []; + + for (let i = 0; i < items.length; i++) { + const item = items[i]; + if (item.kind === 'file') { + const entry = item.webkitGetAsEntry?.(); + if (entry) { + await processEntry(entry, '', files); + } else { + // Fallback to getAsFile for browsers that don't support webkitGetAsEntry + const file = item.getAsFile(); + if (file) files.push(file); + } + } + } + + // Upload all collected files + for (const file of files) { + await handleFileUpload(file); + } + } else { + // Fallback for browsers that don't support DataTransferItemList + const files = Array.from(e.dataTransfer.files); + for (const file of files) { + await handleFileUpload(file); + } + } + }; + + // Recursively process file system entries (for folder support) + const processEntry = async (entry: any, path: string, files: File[]): Promise => { + if (entry.isFile) { + // Handle file + return new Promise((resolve) => { + entry.file((file: File) => { + // Add the relative path to the file object + Object.defineProperty(file, 'webkitRelativePath', { + value: path + file.name, + writable: false + }); + files.push(file); + resolve(); + }); + }); + } else if (entry.isDirectory) { + // Handle directory + const dirReader = entry.createReader(); + return new Promise((resolve) => { + dirReader.readEntries(async (entries: any[]) => { + for (const childEntry of entries) { + await processEntry(childEntry, path + entry.name + '/', files); + } + resolve(); + }); + }); + } + }; + + const handleFileUpload = async (file: File) => { + const fileId = `${file.name}-${Date.now()}`; + + try { + updateUploadProgress(fileId, 0); + + const content = await file.arrayBuffer(); + const contentArray = Array.from(new Uint8Array(content)); + + // Check if file is part of a folder upload + const relativePath = (file as any).webkitRelativePath || ''; + let uploadPath = currentPath; + let fileName = file.name; + + if (relativePath) { + // Handle folder structure + const pathParts = relativePath.split('/'); + fileName = pathParts.pop() || file.name; + + // Create nested folder structure + for (const folderName of pathParts) { + uploadPath = uploadPath === '/' ? `/${folderName}` : `${uploadPath}/${folderName}`; + try { + await FileExplorer.create_directory(uploadPath); + } catch (err) { + // Ignore if directory already exists + console.log(`Directory ${uploadPath} might already exist`); + } + } + } + + // Simulate upload progress + updateUploadProgress(fileId, 50); + + await FileExplorer.upload_file(uploadPath, fileName, contentArray); + + updateUploadProgress(fileId, 100); + onUploadComplete(); + } catch (err) { + setError(err instanceof Error ? err.message : 'Upload failed'); + updateUploadProgress(fileId, 100); // Remove from progress + } + }; + + return ( +
+ {children} + {isDragging && ( +
+
+ Drop files or folders here to upload +
+
+ )} +
+ ); +}; + +export default UploadZone; \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/contexts/ThemeContext.tsx b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/contexts/ThemeContext.tsx new file mode 100644 index 00000000..4394b10a --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/contexts/ThemeContext.tsx @@ -0,0 +1,56 @@ +import React, { createContext, useContext, useEffect, useState } from 'react'; + +type Theme = 'light' | 'dark'; + +interface ThemeContextType { + theme: Theme; + toggleTheme: () => void; +} + +const ThemeContext = createContext(undefined); + +export const useTheme = () => { + const context = useContext(ThemeContext); + if (!context) { + throw new Error('useTheme must be used within a ThemeProvider'); + } + return context; +}; + +export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + // Auto-detect system theme preference + const getSystemTheme = (): Theme => { + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + return 'dark'; + } + return 'light'; + }; + + const [theme, setTheme] = useState(getSystemTheme()); + + useEffect(() => { + // Apply theme to document root + document.documentElement.setAttribute('data-theme', theme); + }, [theme]); + + useEffect(() => { + // Listen for system theme changes + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + const handleChange = (e: MediaQueryListEvent) => { + setTheme(e.matches ? 'dark' : 'light'); + }; + + mediaQuery.addEventListener('change', handleChange); + return () => mediaQuery.removeEventListener('change', handleChange); + }, []); + + const toggleTheme = () => { + setTheme(prev => prev === 'light' ? 'dark' : 'light'); + }; + + return ( + + {children} + + ); +}; \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/index.css b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/index.css new file mode 100644 index 00000000..5b7e24b3 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/index.css @@ -0,0 +1,120 @@ +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* Light theme variables */ +[data-theme="light"] { + --bg-primary: #ffffff; + --bg-secondary: #f5f5f5; + --bg-hover: #e9e9e9; + --bg-selected: #e3f2fd; + --text-primary: #213547; + --text-secondary: #666666; + --border-color: #e0e0e0; + --shadow-color: rgba(0, 0, 0, 0.1); + --link-color: #0066cc; + --link-hover: #0052a3; + --error-color: #d32f2f; + --success-color: #388e3c; +} + +/* Dark theme variables */ +[data-theme="dark"] { + --bg-primary: #1e1e1e; + --bg-secondary: #2d2d2d; + --bg-hover: #3a3a3a; + --bg-selected: #1a4d7a; + --text-primary: #e0e0e0; + --text-secondary: #b0b0b0; + --border-color: #404040; + --shadow-color: rgba(0, 0, 0, 0.3); + --link-color: #64b5f6; + --link-hover: #90caf9; + --error-color: #f44336; + --success-color: #66bb6a; +} + +/* Apply theme colors */ +body { + margin: 0; + padding: 0; + min-width: 320px; + min-height: 100vh; + color: var(--text-primary); + background-color: var(--bg-primary); + transition: background-color 0.3s ease, color 0.3s ease; + overflow: hidden; +} + +#root { + width: 100%; + height: 100vh; + margin: 0; + padding: 0; + overflow: hidden; +} + +a { + font-weight: 500; + color: var(--link-color); + text-decoration: inherit; +} +a:hover { + color: var(--link-hover); +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +ul { + list-style: none; + padding: 0; + margin: 0; +} + +button { + border-radius: 8px; + border: 1px solid var(--border-color); + padding: 0.6em 1.2em; + background-color: var(--bg-secondary); + color: var(--text-primary); + font-size: 1em; + font-weight: 500; + font-family: inherit; + cursor: pointer; + transition: background-color 0.25s, border-color 0.25s; +} +button:hover { + background-color: var(--bg-hover); + border-color: var(--text-secondary); +} +button:focus, +button:focus-visible { + outline: 2px solid var(--link-color); + outline-offset: 2px; +} + +/* Additional utility classes */ +.error-message { + color: var(--error-color); + padding: 1rem; + background-color: var(--bg-secondary); + border-radius: 4px; + margin: 0.5rem 0; +} + +.success-message { + color: var(--success-color); + padding: 1rem; + background-color: var(--bg-secondary); + border-radius: 4px; + margin: 0.5rem 0; +} \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/lib/api.ts b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/lib/api.ts new file mode 100644 index 00000000..2d0912e4 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/lib/api.ts @@ -0,0 +1,2 @@ +// Re-export everything from the generated caller-utils +export * from '../types/api'; \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/main.tsx b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/main.tsx new file mode 100644 index 00000000..3d7150da --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/main.tsx @@ -0,0 +1,10 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App.tsx' +import './index.css' + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/store/fileExplorer.ts b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/store/fileExplorer.ts new file mode 100644 index 00000000..140700fc --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/store/fileExplorer.ts @@ -0,0 +1,110 @@ +import { create } from 'zustand'; +import { FileExplorer } from '../lib/api'; + +interface FileExplorerStore { + currentPath: string; + files: FileExplorer.FileInfo[]; + selectedFiles: string[]; + expandedDirectories: Set; + uploadProgress: Map; + sharedLinks: Map; + loading: boolean; + error: string | null; + + // Actions + setCurrentPath: (path: string) => void; + setFiles: (files: FileExplorer.FileInfo[]) => void; + selectFile: (path: string) => void; + deselectFile: (path: string) => void; + toggleFileSelection: (path: string) => void; + clearSelection: () => void; + selectAll: () => void; + toggleDirectoryExpanded: (path: string) => void; + updateUploadProgress: (fileId: string, progress: number) => void; + addSharedLink: (path: string, link: string) => void; + removeSharedLink: (path: string) => void; + isFileShared: (path: string) => boolean; + setLoading: (loading: boolean) => void; + setError: (error: string | null) => void; +} + +const useFileExplorerStore = create((set, get) => ({ + currentPath: '', // Start with empty path to avoid loading root before home is set + files: [], + selectedFiles: [], + expandedDirectories: new Set(), + uploadProgress: new Map(), + sharedLinks: new Map(), + loading: false, + error: null, + + setCurrentPath: (path) => set({ currentPath: path }), + + setFiles: (files) => set({ files, error: null }), + + selectFile: (path) => set((state) => ({ + selectedFiles: [...state.selectedFiles, path] + })), + + deselectFile: (path) => set((state) => ({ + selectedFiles: state.selectedFiles.filter(p => p !== path) + })), + + toggleFileSelection: (path) => { + const state = get(); + if (state.selectedFiles.includes(path)) { + state.deselectFile(path); + } else { + state.selectFile(path); + } + }, + + clearSelection: () => set({ selectedFiles: [] }), + + selectAll: () => set((state) => ({ + selectedFiles: state.files.map(f => f.path) + })), + + toggleDirectoryExpanded: (path) => set((state) => { + const newExpanded = new Set(state.expandedDirectories); + if (newExpanded.has(path)) { + newExpanded.delete(path); + } else { + newExpanded.add(path); + } + return { expandedDirectories: newExpanded }; + }), + + updateUploadProgress: (fileId, progress) => set((state) => { + const newProgress = new Map(state.uploadProgress); + if (progress >= 100) { + newProgress.delete(fileId); + } else { + newProgress.set(fileId, progress); + } + return { uploadProgress: newProgress }; + }), + + addSharedLink: (path, link) => set((state) => { + const newLinks = new Map(state.sharedLinks); + newLinks.set(path, link); + return { sharedLinks: newLinks }; + }), + + removeSharedLink: (path) => set((state) => { + const newLinks = new Map(state.sharedLinks); + newLinks.delete(path); + return { sharedLinks: newLinks }; + }), + + isFileShared: (path) => { + const state = get(); + return state.sharedLinks.has(path); + }, + + setLoading: (loading) => set({ loading }), + + setError: (error) => set({ error }), +})); + +export default useFileExplorerStore; \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/types/api.ts b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/types/api.ts new file mode 100644 index 00000000..68d8d24a --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/types/api.ts @@ -0,0 +1,2 @@ +// Re-export everything from caller-utils +export * from '../../../target/ui/caller-utils'; \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/types/global.ts b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/types/global.ts new file mode 100644 index 00000000..44640a4c --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/types/global.ts @@ -0,0 +1,10 @@ +declare module "global" { + global { + interface Window { + our: { + node: string; + process: string; + }; + } + } +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/vite-env.d.ts b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/tsconfig.json b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/tsconfig.json new file mode 100644 index 00000000..6f148432 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + // "strict": true, + // "noUnusedLocals": true, + // "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": [ + "src", + "../pkg/manifest.json", + "../pkg/metadata.json", + ], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/tsconfig.node.json b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/tsconfig.node.json new file mode 100644 index 00000000..42872c59 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/vite.config.ts b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/vite.config.ts new file mode 100644 index 00000000..3683e564 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/file-explorer/ui/vite.config.ts @@ -0,0 +1,67 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +/* +If you are developing a UI outside of a Hyperware project, +comment out the following 2 lines: +*/ +import manifest from '../pkg/manifest.json' +import metadata from '../metadata.json' + +/* +IMPORTANT: +This must match the process name from pkg/manifest.json + pkg/metadata.json +The format is "/" + "process_name:package_name:publisher_node" +*/ +const BASE_URL = `/${manifest[0].process_name}:${metadata.properties.package_name}:${metadata.properties.publisher}`; + +// This is the proxy URL, it must match the node you are developing against +const PROXY_URL = (process.env.VITE_NODE_URL || 'http://127.0.0.1:8080').replace('localhost', '127.0.0.1'); + +console.log('process.env.VITE_NODE_URL', process.env.VITE_NODE_URL, PROXY_URL); + +export default defineConfig({ + plugins: [react()], + base: BASE_URL, + build: { + rollupOptions: { + external: ['/our.js'] + } + }, + server: { + open: true, + proxy: { + '/our': { + target: PROXY_URL, + changeOrigin: true, + }, + [`${BASE_URL}/our.js`]: { + target: PROXY_URL, + changeOrigin: true, + rewrite: (path) => path.replace(BASE_URL, ''), + }, + // This route will match all other HTTP requests to the backend + [`^${BASE_URL}/(?!(@vite/client|src/.*|node_modules/.*|@react-refresh|$))`]: { + target: PROXY_URL, + changeOrigin: true, + }, + // '/example': { + // target: PROXY_URL, + // changeOrigin: true, + // rewrite: (path) => path.replace(BASE_URL, ''), + // // This is only for debugging purposes + // configure: (proxy, _options) => { + // proxy.on('error', (err, _req, _res) => { + // console.log('proxy error', err); + // }); + // proxy.on('proxyReq', (proxyReq, req, _res) => { + // console.log('Sending Request to the Target:', req.method, req.url); + // }); + // proxy.on('proxyRes', (proxyRes, req, _res) => { + // console.log('Received Response from the Target:', proxyRes.statusCode, req.url); + // }); + // }, + // }, + } + } +}); diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/Cargo.toml b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/Cargo.toml new file mode 100644 index 00000000..bf793365 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/Cargo.toml @@ -0,0 +1,11 @@ +[profile.release] +lto = true +opt-level = "s" +panic = "abort" + +[workspace] +members = [ + "id", + "target/caller-utils", +] +resolver = "2" diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/README.md b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/README.md new file mode 100644 index 00000000..b0027a8a --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/README.md @@ -0,0 +1,3 @@ +# id + +For use with https://github.com/nick1udwig/sign diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/id/Cargo.toml b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/id/Cargo.toml new file mode 100644 index 00000000..81a3cd48 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/id/Cargo.toml @@ -0,0 +1,35 @@ +[dependencies] +anyhow = "1.0.97" +process_macros = "0.1" +rmp-serde = "1.3.0" +serde_json = "1.0" +wit-bindgen = "0.36.0" + +[dependencies.caller-utils] +path = "../target/caller-utils" + +[dependencies.hyperprocess_macro] +git = "https://github.com/hyperware-ai/hyperprocess-macro" +rev = "4c944b2" + +[dependencies.hyperware_app_common] +git = "https://github.com/hyperware-ai/hyperprocess-macro" +rev = "4c944b2" + +[dependencies.serde] +features = ["derive"] +version = "1.0" + +[features] +simulation-mode = [] + +[lib] +crate-type = ["cdylib"] + +[package] +edition = "2021" +name = "id" +version = "0.1.0" + +[package.metadata.component] +package = "hyperware:process" diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/id/src/icon b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/id/src/icon new file mode 100644 index 00000000..f67b371b --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/id/src/icon @@ -0,0 +1 @@ +data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwMCIgaGVpZ2h0PSIxMDAwIiB2aWV3Qm94PSIwIDAgMTAwMCAxMDAwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cmVjdCB4PSIyMCIgeT0iMjAiIHdpZHRoPSI5NjAiIGhlaWdodD0iOTYwIiByeD0iNDgwIiBmaWxsPSJ1cmwoI3BhaW50MF9saW5lYXJfMjA5MV8xMDI4MikiIGZpbGwtb3BhY2l0eT0iMC40Ii8+CjxyZWN0IHg9IjIwIiB5PSIyMCIgd2lkdGg9Ijk2MCIgaGVpZ2h0PSI5NjAiIHJ4PSI0ODAiIHN0cm9rZT0idXJsKCNwYWludDFfbGluZWFyXzIwOTFfMTAyODIpIiBzdHJva2Utd2lkdGg9IjQwIi8+CjxwYXRoIGQ9Ik01ODEuMTE2IDU4NS43ODNMNjY0LjUzOCA2NjkuMTJDNjE3LjY5OSA3MTUuNzU4IDU1Ni42MjUgNzM5IDQ5NS4yNDUgNzM5QzQzMy44NjUgNzM5IDM3Mi42MzggNzE1LjYwNSAzMjYuMTA1IDY2OS4xMkMyODAuNzk3IDYyMy44NTggMjU2IDU2My45MTcgMjU2IDUwMEMyNTYgNDM2LjA4MyAyODAuOTUgMzc2LjE0MiAzMjYuMTA1IDMzMC44OEMzNzEuMjYgMjg1LjYxOSA0MzEuMjYyIDI2MSA0OTUuMjQ1IDI2MUM1NTkuMjI3IDI2MSA2MTkuMjMgMjg1LjkyNCA2NjQuNTM4IDMzMC44OEw1ODAuOTYzIDQxNC41MjNDNTQ1LjYwNCAzODMuOTQgNTA1LjE5NCAzNzQuNzY2IDQ2MS4yNjQgMzkxLjEyN0MzOTQuOTg1IDQxNS44OTkgMzY2LjgyMSA0ODkuMjk2IDM5Ny40MzUgNTUyLjc1NEMzOTguNjU5IDU1NS4yMDEgMzk4Ljk2NSA1NTguNzE4IDM5OC4zNTMgNTYxLjMxN0MzOTUuNzUxIDU3Mi40OCAzOTIuNjg5IDU4My40OSAzODkuNzgxIDU5NC4zNDZDMzg2LjEwNyA2MDcuOTU1IDM5My45MTQgNjE1Ljc1NCA0MDcuNTM3IDYxMi4yMzdDNDE4LjU1OCA2MDkuMzMxIDQyOS41NzkgNjA2LjEyIDQ0MC42IDYwMy42NzRDNDQzLjM1NSA2MDIuOTA5IDQ0Ny4wMjkgNjAzLjIxNSA0NDkuNjMxIDYwNC40MzhDNDkwLjUgNjIzLjM5OSA1MjkuOTkxIDYyMC44IDU2Ny43OTkgNTk2LjE4MUM1NzIuNTQ0IDU5My4xMjMgNTc2LjY3NyA1ODkuNDUzIDU4MS4xMTYgNTg1Ljc4M1oiIGZpbGw9InVybCgjcGFpbnQyX2xpbmVhcl8yMDkxXzEwMjgyKSIvPgo8ZGVmcz4KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDBfbGluZWFyXzIwOTFfMTAyODIiIHgxPSI1MDAiIHkxPSIwIiB4Mj0iNTAwIiB5Mj0iMTAwMCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPgo8c3RvcCBzdG9wLWNvbG9yPSIjRjM1NDIyIi8+CjxzdG9wIG9mZnNldD0iMSIgc3RvcC1vcGFjaXR5PSIwIi8+CjwvbGluZWFyR3JhZGllbnQ+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQxX2xpbmVhcl8yMDkxXzEwMjgyIiB4MT0iNzgyLjUiIHkxPSI3My41IiB4Mj0iMTg1LjUiIHkyPSI4OTQuNSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPgo8c3RvcCBzdG9wLWNvbG9yPSIjRjM1NDIyIi8+CjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI0E1MzEwQyIvPgo8L2xpbmVhckdyYWRpZW50Pgo8bGluZWFyR3JhZGllbnQgaWQ9InBhaW50Ml9saW5lYXJfMjA5MV8xMDI4MiIgeDE9Ijc1NCIgeTE9Ijg5LjUiIHgyPSIyNTYiIHkyPSIxMDE1LjUiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0YzNTQyMiIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNBNzMyMEQiLz4KPC9saW5lYXJHcmFkaWVudD4KPC9kZWZzPgo8L3N2Zz4K \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/id/src/lib.rs b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/id/src/lib.rs new file mode 100644 index 00000000..8c40a479 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/id/src/lib.rs @@ -0,0 +1,52 @@ +use caller_utils::sign::{sign_local_rpc, verify_local_rpc}; +use hyperprocess_macro::hyperprocess; +use hyperware_process_lib::logging::{init_logging, Level}; +use hyperware_process_lib::Address; + +#[derive(Default, Debug, serde::Serialize, serde::Deserialize)] +struct IdState {} + +fn make_sign_sys() -> Address { + Address::new("our", ("sign", "sign", "sys")) +} + +#[hyperprocess( + name = "id", + ui = Some(HttpBindingConfig::default()), + endpoints = vec![ + Binding::Http { + path: "/api", + config: HttpBindingConfig::default(), + }, + Binding::Ws { + path: "/ws", + config: WsBindingConfig::default(), + } + ], + save_config = SaveOptions::Never, + wit_world = "id-sys-v0", +)] +impl IdState { + #[init] + async fn init(&mut self) { + init_logging(Level::DEBUG, Level::INFO, None, None, None).unwrap(); + } + + #[http] + async fn sign(&mut self, message: Vec) -> Result, String> { + let target = make_sign_sys(); + match sign_local_rpc(&target, message).await { + Ok(r) => r, + Err(e) => Err(e.to_string()), + } + } + + #[http] + async fn verify(&mut self, message: Vec, signature: Vec) -> Result { + let target = make_sign_sys(); + match verify_local_rpc(&target, message, signature).await { + Ok(r) => r, + Err(e) => Err(e.to_string()), + } + } +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/metadata.json b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/metadata.json new file mode 100644 index 00000000..5bf6ace7 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/metadata.json @@ -0,0 +1,20 @@ +{ + "name": "id", + "description": "Prove your Hyperware id", + "image": "", + "properties": { + "package_name": "id", + "current_version": "0.1.0", + "publisher": "sys", + "mirrors": [], + "code_hashes": { + "0.1.0": "" + }, + "wit_version": 1, + "dependencies": [ + "sign:sys" + ] + }, + "external_url": "https://hyperware.ai", + "animation_url": "" +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/pkg/manifest.json b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/pkg/manifest.json new file mode 100644 index 00000000..3fed0681 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/pkg/manifest.json @@ -0,0 +1,19 @@ +[ + { + "process_name": "id", + "process_wasm_path": "/id.wasm", + "on_exit": "Restart", + "request_networking": false, + "request_capabilities": [ + "http-server:distro:sys", + "sign:sign:sys", + "vfs:distro:sys" + ], + "grant_capabilities": [ + "http-server:distro:sys", + "sign:sign:sys", + "vfs:distro:sys" + ], + "public": false + } +] diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/.eslintrc.cjs b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/.eslintrc.cjs new file mode 100644 index 00000000..d6c95379 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/.eslintrc.cjs @@ -0,0 +1,18 @@ +module.exports = { + root: true, + env: { browser: true, es2020: true }, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:react-hooks/recommended', + ], + ignorePatterns: ['dist', '.eslintrc.cjs'], + parser: '@typescript-eslint/parser', + plugins: ['react-refresh'], + rules: { + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/.gitignore b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/.gitignore new file mode 100644 index 00000000..a547bf36 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/README.md b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/README.md new file mode 100644 index 00000000..b0e896f4 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/README.md @@ -0,0 +1,56 @@ +# Hyperware UI Template + +Based on the Vite React Typescript template. + +## Setup + +When using `kit new`, the `BASE_URL` on line 9 of `vite.config.ts` will be set automatically. +The `BASE_URL` will be the first process in `manifest.json`, the `package` from `metadata.json`, and `publisher` from `metadata.json`. +If you have multiple processes in `manifest.json`, make sure the first process will be the one serving the UI. + +## Development + +Run `npm i` and then `npm run dev` to start working on the UI. + +You may see an error: + +``` +[vite] Pre-transform error: Failed to load url /our.js (resolved id: /our.js). Does the file exist? +``` + +You can safely ignore this error. The file will be served by the node via the proxy. + +## public vs assets + +The `public/assets` folder contains files that are referenced in `index.html`, `src/assets` is for asset files that are only referenced in `src` code. + +## About Vite + React + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: + +- Configure the top-level `parserOptions` property like this: + +```js +export default { + // other rules... + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + project: ['./tsconfig.json', './tsconfig.node.json'], + tsconfigRootDir: __dirname, + }, +} +``` + +- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked` +- Optionally add `plugin:@typescript-eslint/stylistic-type-checked` +- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/index.html b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/index.html new file mode 100644 index 00000000..60766304 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/index.html @@ -0,0 +1,16 @@ + + + + + + + + + + Simple Id + + +
+ + + diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/package-lock.json b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/package-lock.json new file mode 100644 index 00000000..b84255a3 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/package-lock.json @@ -0,0 +1,3384 @@ +{ + "name": "ui-template", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "ui-template", + "version": "0.0.0", + "dependencies": { + "@hyperware-ai/client-api": "^0.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "zustand": "^4.4.7" + }, + "devDependencies": { + "@types/node": "^20.10.4", + "@types/react": "^18.2.43", + "@types/react-dom": "^18.2.17", + "@typescript-eslint/eslint-plugin": "^6.14.0", + "@typescript-eslint/parser": "^6.14.0", + "@vitejs/plugin-react": "^4.2.1", + "eslint": "^8.55.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.5", + "http-proxy-middleware": "^2.0.6", + "typescript": "^5.2.2", + "vite": "^5.0.8" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.6.tgz", + "integrity": "sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.6", + "@babel/parser": "^7.23.6", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.6", + "@babel/types": "^7.23.6", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.6.tgz", + "integrity": "sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.6", + "@babel/types": "^7.23.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.23.3.tgz", + "integrity": "sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.23.3.tgz", + "integrity": "sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.6.tgz", + "integrity": "sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", + "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.10.tgz", + "integrity": "sha512-Q+mk96KJ+FZ30h9fsJl+67IjNJm3x2eX+GBWGmocAKgzp27cowCOOqSdscX80s0SpdFXZnIv/+1xD1EctFx96Q==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.10.tgz", + "integrity": "sha512-7W0bK7qfkw1fc2viBfrtAEkDKHatYfHzr/jKAHNr9BvkYDXPcC6bodtm8AyLJNNuqClLNaeTLuwURt4PRT9d7w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.10.tgz", + "integrity": "sha512-1X4CClKhDgC3by7k8aOWZeBXQX8dHT5QAMCAQDArCLaYfkppoARvh0fit3X2Qs+MXDngKcHv6XXyQCpY0hkK1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.10.tgz", + "integrity": "sha512-O/nO/g+/7NlitUxETkUv/IvADKuZXyH4BHf/g/7laqKC4i/7whLpB0gvpPc2zpF0q9Q6FXS3TS75QHac9MvVWw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.10.tgz", + "integrity": "sha512-YSRRs2zOpwypck+6GL3wGXx2gNP7DXzetmo5pHXLrY/VIMsS59yKfjPizQ4lLt5vEI80M41gjm2BxrGZ5U+VMA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.10.tgz", + "integrity": "sha512-alfGtT+IEICKtNE54hbvPg13xGBe4GkVxyGWtzr+yHO7HIiRJppPDhOKq3zstTcVf8msXb/t4eavW3jCDpMSmA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.10.tgz", + "integrity": "sha512-dMtk1wc7FSH8CCkE854GyGuNKCewlh+7heYP/sclpOG6Cectzk14qdUIY5CrKDbkA/OczXq9WesqnPl09mj5dg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.10.tgz", + "integrity": "sha512-G5UPPspryHu1T3uX8WiOEUa6q6OlQh6gNl4CO4Iw5PS+Kg5bVggVFehzXBJY6X6RSOMS8iXDv2330VzaObm4Ag==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.10.tgz", + "integrity": "sha512-j6gUW5aAaPgD416Hk9FHxn27On28H4eVI9rJ4az7oCGTFW48+LcgNDBN+9f8rKZz7EEowo889CPKyeaD0iw9Kg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.10.tgz", + "integrity": "sha512-QxaouHWZ+2KWEj7cGJmvTIHVALfhpGxo3WLmlYfJ+dA5fJB6lDEIg+oe/0//FuyVHuS3l79/wyBxbHr0NgtxJQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.10.tgz", + "integrity": "sha512-4ub1YwXxYjj9h1UIZs2hYbnTZBtenPw5NfXCRgEkGb0b6OJ2gpkMvDqRDYIDRjRdWSe/TBiZltm3Y3Q8SN1xNg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.10.tgz", + "integrity": "sha512-lo3I9k+mbEKoxtoIbM0yC/MZ1i2wM0cIeOejlVdZ3D86LAcFXFRdeuZmh91QJvUTW51bOK5W2BznGNIl4+mDaA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.10.tgz", + "integrity": "sha512-J4gH3zhHNbdZN0Bcr1QUGVNkHTdpijgx5VMxeetSk6ntdt+vR1DqGmHxQYHRmNb77tP6GVvD+K0NyO4xjd7y4A==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.10.tgz", + "integrity": "sha512-tgT/7u+QhV6ge8wFMzaklOY7KqiyitgT1AUHMApau32ZlvTB/+efeCtMk4eXS+uEymYK249JsoiklZN64xt6oQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.10.tgz", + "integrity": "sha512-0f/spw0PfBMZBNqtKe5FLzBDGo0SKZKvMl5PHYQr3+eiSscfJ96XEknCe+JoOayybWUFQbcJTrk946i3j9uYZA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.10.tgz", + "integrity": "sha512-pZFe0OeskMHzHa9U38g+z8Yx5FNCLFtUnJtQMpwhS+r4S566aK2ci3t4NCP4tjt6d5j5uo4h7tExZMjeKoehAA==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.10.tgz", + "integrity": "sha512-SpYNEqg/6pZYoc+1zLCjVOYvxfZVZj6w0KROZ3Fje/QrM3nfvT2llI+wmKSrWuX6wmZeTapbarvuNNK/qepSgA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.10.tgz", + "integrity": "sha512-ACbZ0vXy9zksNArWlk2c38NdKg25+L9pr/mVaj9SUq6lHZu/35nx2xnQVRGLrC1KKQqJKRIB0q8GspiHI3J80Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.10.tgz", + "integrity": "sha512-PxcgvjdSjtgPMiPQrM3pwSaG4kGphP+bLSb+cihuP0LYdZv1epbAIecHVl5sD3npkfYBZ0ZnOjR878I7MdJDFg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.10.tgz", + "integrity": "sha512-ZkIOtrRL8SEJjr+VHjmW0znkPs+oJXhlJbNwfI37rvgeMtk3sxOQevXPXjmAPZPigVTncvFqLMd+uV0IBSEzqA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.10.tgz", + "integrity": "sha512-+Sa4oTDbpBfGpl3Hn3XiUe4f8TU2JF7aX8cOfqFYMMjXp6ma6NJDztl5FDG8Ezx0OjwGikIHw+iA54YLDNNVfw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.10.tgz", + "integrity": "sha512-EOGVLK1oWMBXgfttJdPHDTiivYSjX6jDNaATeNOaCOFEVcfMjtbx7WVQwPSE1eIfCp/CaSF2nSrDtzc4I9f8TQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.10.tgz", + "integrity": "sha512-whqLG6Sc70AbU73fFYvuYzaE4MNMBIlR1Y/IrUeOXFrWHxBEjjbZaQ3IXIQS8wJdAzue2GwYZCjOrgrU1oUHoA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, + "node_modules/@hyperware-ai/client-api": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@hyperware-ai/client-api/-/client-api-0.1.0.tgz", + "integrity": "sha512-qDj7xew+Z1qSQtiq8oc2ntZuiVdM1rtwIAQnyLxpL0j+f3cCfUnaDE6/604wJIrYmh8xjrtxUpWqu+ZmZoy6yg==", + "dependencies": { + "buffer": "^6.0.3", + "node-forge": "^1.3.1", + "typescript": "^4.9.5" + } + }, + "node_modules/@hyperware-ai/client-api/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.1.tgz", + "integrity": "sha512-6vMdBZqtq1dVQ4CWdhFwhKZL6E4L1dV6jUjuBvsavvNJSppzi6dLBbuV+3+IyUREaj9ZFvQefnQm28v4OCXlig==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.1.tgz", + "integrity": "sha512-Jto9Fl3YQ9OLsTDWtLFPtaIMSL2kwGyGoVCmPC8Gxvym9TCZm4Sie+cVeblPO66YZsYH8MhBKDMGZ2NDxuk/XQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.1.tgz", + "integrity": "sha512-LtYcLNM+bhsaKAIGwVkh5IOWhaZhjTfNOkGzGqdHvhiCUVuJDalvDxEdSnhFzAn+g23wgsycmZk1vbnaibZwwA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.1.tgz", + "integrity": "sha512-KyP/byeXu9V+etKO6Lw3E4tW4QdcnzDG/ake031mg42lob5tN+5qfr+lkcT/SGZaH2PdW4Z1NX9GHEkZ8xV7og==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.1.tgz", + "integrity": "sha512-Yqz/Doumf3QTKplwGNrCHe/B2p9xqDghBZSlAY0/hU6ikuDVQuOUIpDP/YcmoT+447tsZTmirmjgG3znvSCR0Q==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.1.tgz", + "integrity": "sha512-u3XkZVvxcvlAOlQJ3UsD1rFvLWqu4Ef/Ggl40WAVCuogf4S1nJPHh5RTgqYFpCOvuGJ7H5yGHabjFKEZGExk5Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.1.tgz", + "integrity": "sha512-0XSYN/rfWShW+i+qjZ0phc6vZ7UWI8XWNz4E/l+6edFt+FxoEghrJHjX1EY/kcUGCnZzYYRCl31SNdfOi450Aw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.1.tgz", + "integrity": "sha512-LmYIO65oZVfFt9t6cpYkbC4d5lKHLYv5B4CSHRpnANq0VZUQXGcCPXHzbCXCz4RQnx7jvlYB1ISVNCE/omz5cw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.1.tgz", + "integrity": "sha512-kr8rEPQ6ns/Lmr/hiw8sEVj9aa07gh1/tQF2Y5HrNCCEPiCBGnBUt9tVusrcBBiJfIt1yNaXN6r1CCmpbFEDpg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.1.tgz", + "integrity": "sha512-t4QSR7gN+OEZLG0MiCgPqMWZGwmeHhsM4AkegJ0Kiy6TnJ9vZ8dEIwHw1LcZKhbHxTY32hp9eVCMdR3/I8MGRw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.1.tgz", + "integrity": "sha512-7XI4ZCBN34cb+BH557FJPmh0kmNz2c25SCQeT9OiFWEgf8+dL6ZwJ8f9RnUIit+j01u07Yvrsuu1rZGxJCc51g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.1.tgz", + "integrity": "sha512-yE5c2j1lSWOH5jp+Q0qNL3Mdhr8WuqCNVjc6BxbVfS5cAS6zRmdiw7ktb8GNpDCEUJphILY6KACoFoRtKoqNQg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.1.tgz", + "integrity": "sha512-PyJsSsafjmIhVgaI1Zdj7m8BB8mMckFah/xbpplObyHfiXzKcI5UOUXRyOdHW7nz4DpMCuzLnF7v5IWHenCwYA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.4", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.4.tgz", + "integrity": "sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/http-proxy": { + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.10.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz", + "integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.11", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", + "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==", + "devOptional": true + }, + "node_modules/@types/react": { + "version": "18.2.45", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.45.tgz", + "integrity": "sha512-TtAxCNrlrBp8GoeEp1npd5g+d/OejJHFxS3OWmrPBMFaVQMSN0OFySozJio5BHxTuTeug00AVXVAjfDSfk+lUg==", + "devOptional": true, + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.2.18", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz", + "integrity": "sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==", + "devOptional": true + }, + "node_modules/@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.15.0.tgz", + "integrity": "sha512-j5qoikQqPccq9QoBAupOP+CBu8BaJ8BLjaXSioDISeTZkVO3ig7oSIKh3H+rEpee7xCXtWwSB4KIL5l6hWZzpg==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.15.0", + "@typescript-eslint/type-utils": "6.15.0", + "@typescript-eslint/utils": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.15.0.tgz", + "integrity": "sha512-MkgKNnsjC6QwcMdlNAel24jjkEO/0hQaMDLqP4S9zq5HBAUJNQB6y+3DwLjX7b3l2b37eNAxMPLwb3/kh8VKdA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.15.0", + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/typescript-estree": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.15.0.tgz", + "integrity": "sha512-+BdvxYBltqrmgCNu4Li+fGDIkW9n//NrruzG9X1vBzaNK+ExVXPoGB71kneaVw/Jp+4rH/vaMAGC6JfMbHstVg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.15.0.tgz", + "integrity": "sha512-CnmHKTfX6450Bo49hPg2OkIm/D/TVYV7jO1MCfPYGwf6x3GO0VU8YMO5AYMn+u3X05lRRxA4fWCz87GFQV6yVQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.15.0", + "@typescript-eslint/utils": "6.15.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.15.0.tgz", + "integrity": "sha512-yXjbt//E4T/ee8Ia1b5mGlbNj9fB9lJP4jqLbZualwpP2BCQ5is6BcWwxpIsY4XKAhmdv3hrW92GdtJbatC6dQ==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.15.0.tgz", + "integrity": "sha512-7mVZJN7Hd15OmGuWrp2T9UvqR2Ecg+1j/Bp1jXUEY2GZKV6FXlOIoqVDmLpBiEiq3katvj/2n2mR0SDwtloCew==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.15.0.tgz", + "integrity": "sha512-eF82p0Wrrlt8fQSRL0bGXzK5nWPRV2dYQZdajcfzOD9+cQz9O7ugifrJxclB+xVOvWvagXfqS4Es7vpLP4augw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.15.0", + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/typescript-estree": "6.15.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.15.0.tgz", + "integrity": "sha512-1zvtdC1a9h5Tb5jU9x3ADNXO9yjP8rXlaoChu0DQX40vf5ACVpYIVIZhIMZ6d5sDXH7vq4dsZBT1fEGj8D2n2w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.15.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz", + "integrity": "sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.5", + "@babel/plugin-transform-react-jsx-self": "^7.23.3", + "@babel/plugin-transform-react-jsx-source": "^7.23.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0" + } + }, + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001571", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001571.tgz", + "integrity": "sha512-tYq/6MoXhdezDLFZuCO/TKboTzuQ/xR5cFdgXPfDtM7/kchBO3b4VWghE/OAi/DV7tTdhmLjZiZBZi1fA/GheQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "devOptional": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.616", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.616.tgz", + "integrity": "sha512-1n7zWYh8eS0L9Uy+GskE0lkBUNK83cXTVJI0pU3mGprFsbfSdAc15VTFbo+A+Bq4pwstmL30AVcEU3Fo463lNg==", + "dev": true + }, + "node_modules/esbuild": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.10.tgz", + "integrity": "sha512-S1Y27QGt/snkNYrRcswgRFqZjaTG5a5xM3EQo97uNBnH505pdzSNe/HLBq1v0RO7iK/ngdbhJB6mDAp0OK+iUA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.10", + "@esbuild/android-arm": "0.19.10", + "@esbuild/android-arm64": "0.19.10", + "@esbuild/android-x64": "0.19.10", + "@esbuild/darwin-arm64": "0.19.10", + "@esbuild/darwin-x64": "0.19.10", + "@esbuild/freebsd-arm64": "0.19.10", + "@esbuild/freebsd-x64": "0.19.10", + "@esbuild/linux-arm": "0.19.10", + "@esbuild/linux-arm64": "0.19.10", + "@esbuild/linux-ia32": "0.19.10", + "@esbuild/linux-loong64": "0.19.10", + "@esbuild/linux-mips64el": "0.19.10", + "@esbuild/linux-ppc64": "0.19.10", + "@esbuild/linux-riscv64": "0.19.10", + "@esbuild/linux-s390x": "0.19.10", + "@esbuild/linux-x64": "0.19.10", + "@esbuild/netbsd-x64": "0.19.10", + "@esbuild/openbsd-x64": "0.19.10", + "@esbuild/sunos-x64": "0.19.10", + "@esbuild/win32-arm64": "0.19.10", + "@esbuild/win32-ia32": "0.19.10", + "@esbuild/win32-x64": "0.19.10" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.5.tgz", + "integrity": "sha512-D53FYKJa+fDmZMtriODxvhwrO+IOqrxoEo21gMA0sjHdU6dPVH4OhyFip9ypl8HOF5RV5KdTo+rBQLvnY2cO8w==", + "dev": true, + "peerDependencies": { + "eslint": ">=7" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", + "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.4.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", + "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-refresh": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", + "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.1.tgz", + "integrity": "sha512-pgPO9DWzLoW/vIhlSoDByCzcpX92bKEorbgXuZrqxByte3JFk2xSW2JEeAcyLc9Ru9pqcNNW+Ob7ntsk2oT/Xw==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.9.1", + "@rollup/rollup-android-arm64": "4.9.1", + "@rollup/rollup-darwin-arm64": "4.9.1", + "@rollup/rollup-darwin-x64": "4.9.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.9.1", + "@rollup/rollup-linux-arm64-gnu": "4.9.1", + "@rollup/rollup-linux-arm64-musl": "4.9.1", + "@rollup/rollup-linux-riscv64-gnu": "4.9.1", + "@rollup/rollup-linux-x64-gnu": "4.9.1", + "@rollup/rollup-linux-x64-musl": "4.9.1", + "@rollup/rollup-win32-arm64-msvc": "4.9.1", + "@rollup/rollup-win32-ia32-msvc": "4.9.1", + "@rollup/rollup-win32-x64-msvc": "4.9.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/vite": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.12.tgz", + "integrity": "sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==", + "dev": true, + "dependencies": { + "esbuild": "^0.19.3", + "postcss": "^8.4.32", + "rollup": "^4.2.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zustand": { + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.4.7.tgz", + "integrity": "sha512-QFJWJMdlETcI69paJwhSMJz7PPWjVP8Sjhclxmxmxv/RYI7ZOvR5BHX+ktH0we9gTWQMxcne8q1OY8xxz604gw==", + "dependencies": { + "use-sync-external-store": "1.2.0" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } + } + } +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/package.json b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/package.json new file mode 100644 index 00000000..ec9ddd50 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/package.json @@ -0,0 +1,35 @@ +{ + "name": "ui-template", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite --port 3000", + "start": "vite --port 3000", + "build": "tsc && vite build", + "copy": "mkdir -p ../pkg/ui && rm -rf ../pkg/ui/* && cp -r dist/* ../pkg/ui/", + "build:copy": "npm run build && npm run copy", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview" + }, + "dependencies": { + "@hyperware-ai/client-api": "^0.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "zustand": "^4.4.7" + }, + "devDependencies": { + "@types/node": "^20.10.4", + "@types/react": "^18.2.43", + "@types/react-dom": "^18.2.17", + "@typescript-eslint/eslint-plugin": "^6.14.0", + "@typescript-eslint/parser": "^6.14.0", + "@vitejs/plugin-react": "^4.2.1", + "eslint": "^8.55.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.5", + "http-proxy-middleware": "^2.0.6", + "typescript": "^5.2.2", + "vite": "^5.0.8" + } +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/public/assets/vite.svg b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/public/assets/vite.svg new file mode 100644 index 00000000..e7b8dfb1 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/public/assets/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/App.css b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/App.css new file mode 100644 index 00000000..30b8e13e --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/App.css @@ -0,0 +1,173 @@ +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; + width: 75%; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: filter 300ms; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 1em; +} + +.read-the-docs { + color: #888; +} + +.message-list { + display: flex; + flex-direction: column; + margin-bottom: 0.5em; + text-align: left; +} + +.message-list li { + margin-bottom: 1em; + padding: 1em; + border-radius: 0.5em; + background-color: #f5f5f5; + border: 1px solid #e0e0e0; + overflow-wrap: break-word; + width: 90%; +} + +.signed-message { + display: flex; + flex-direction: column; + gap: 0.5em; +} + +.message-content { + display: flex; + flex-direction: column; + gap: 0.5em; +} + +.message-text { + font-weight: 500; +} + +.message-signature { + font-family: monospace; + font-size: 0.85em; + color: #666; + background-color: #efefef; + padding: 0.5em; + border-radius: 0.3em; + border: 1px solid #ddd; + overflow-x: auto; +} + +.verification { + display: flex; + align-items: center; + gap: 1em; + margin-top: 0.5em; +} + +.verify-button { + background-color: #4b9ad8; + border: none; + color: white; + padding: 0.5em 1em; + border-radius: 0.3em; + cursor: pointer; + font-size: 0.9em; +} + +.verify-button:hover { + background-color: #357abd; +} + +.verification-result { + font-size: 1.2em; + font-weight: bold; + padding: 0.2em 0.5em; + border-radius: 50%; + display: inline-flex; + align-items: center; + justify-content: center; +} + +.verification-result.verified { + color: white; + background-color: #4caf50; +} + +.verification-result.failed { + color: white; + background-color: #f44336; +} + +.node-not-connected { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + background-color: rgba(255, 255, 255, 0.9); + z-index: 1000; +} + +.input-row { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + width: 100%; +} + +.input-row > button { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + padding: 0.5em 1.2em; + background-color: #4b9ad8; + color: white; + font-weight: 600; +} + +.input-row > button:hover { + background-color: #357abd; +} + +.input-row > input { + border: 1px solid #ccc; + padding: 0.5em 0.8em; + font-size: 1em; + border-radius: 0.25em; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + width: 100%; +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/App.tsx b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/App.tsx new file mode 100644 index 00000000..d994bb5c --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/App.tsx @@ -0,0 +1,182 @@ +import { useState, useEffect, useCallback } from "react"; +import HyperwareClientApi from "@hyperware-ai/client-api"; +import "./App.css"; +import useIdStore from "./store/id"; +import { sign, verify, ApiError } from "../../target/ui/caller-utils"; + +const BASE_URL = import.meta.env.BASE_URL; +if (window.our) window.our.process = BASE_URL?.replace("/", ""); + +const PROXY_TARGET = `${(import.meta.env.VITE_NODE_URL || "http://localhost:8080")}${BASE_URL}`; + +// This env also has BASE_URL which should match the process + package name +const WEBSOCKET_URL = import.meta.env.DEV + ? `${PROXY_TARGET.replace('http', 'ws')}` + : undefined; + +function App() { + const { messageHistory, addSignedMessage, updateVerificationStatus } = useIdStore(); + const [message, setMessage] = useState(""); + const [nodeConnected, setNodeConnected] = useState(true); + const [api, setApi] = useState(); + + useEffect(() => { + // Connect to the Hyperdrive via websocket + console.log('WEBSOCKET URL', WEBSOCKET_URL) + if (window.our?.node && window.our?.process) { + const api = new HyperwareClientApi({ + uri: WEBSOCKET_URL, + nodeId: window.our.node, + processId: window.our.process, + onOpen: (_event, _api) => { + console.log("Connected to Hyperware"); + }, + onMessage: (json, _api) => { + console.log('WEBSOCKET MESSAGE', json) + try { + const data = JSON.parse(json); + console.log("WebSocket received message", data); + } catch (error) { + console.error("Error parsing WebSocket message", error); + } + }, + }); + + setApi(api); + } else { + setNodeConnected(false); + } + }, []); + + const sendMessage = useCallback( + async (event) => { + event.preventDefault(); + + if (!message) return; + + // Create a message object + const encoder = new TextEncoder(); + const messageBytes = encoder.encode(message); + const messageArray = Array.from(messageBytes); + + // Send a message to the node via the sign function + try { + const signature = await sign(messageArray); + + // Add the message and its signature to the store + addSignedMessage(message, signature); + setMessage(""); + } catch (error) { + if (error instanceof ApiError) { + console.error("API Error:", error.message, error.details); + } else { + console.error(error); + } + } + }, + [message, setMessage, addSignedMessage] + ); + + const verifyMessage = useCallback( + async (index: number) => { + const signedMessage = messageHistory.messages[index]; + if (!signedMessage) return; + + // Create message bytes + const encoder = new TextEncoder(); + const messageBytes = encoder.encode(signedMessage.message); + const messageArray = Array.from(messageBytes); + + // Send a verification request via the verify function + try { + const isValid = await verify(messageArray, signedMessage.signature); + + // Update the verification status in the store + updateVerificationStatus(index, isValid); + } catch (error) { + if (error instanceof ApiError) { + console.error("API Error:", error.message, error.details); + } else { + console.error(error); + } + } + }, + [messageHistory, updateVerificationStatus] + ); + + return ( +
+
+ ID: {window.our?.node} +
+ {!nodeConnected && ( +
+

Node not connected

+

+ You need to start a node at {PROXY_TARGET} before you can use this UI + in development. +

+
+ )} +

Signature Verifier

+
+
+

Message History

+
+
    + {messageHistory.messages.map((signedMessage, index) => ( +
  • +
    + {signedMessage.message} + + Signature: [{signedMessage.signature.slice(0, 5).join(', ')} + {signedMessage.signature.length > 5 ? '...' : ''}] + +
    +
    + + {signedMessage.verified !== undefined && ( + + {signedMessage.verified ? '✓' : '✗'} + + )} +
    +
  • + ))} +
+
+
+
+ setMessage(event.target.value)} + autoFocus + /> + +
+
+
+
+
+ ); +} + +export default App; diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/assets/react.svg b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/assets/react.svg new file mode 100644 index 00000000..6c87de9b --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/assets/vite.svg b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/assets/vite.svg new file mode 100644 index 00000000..e7b8dfb1 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/assets/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/index.css b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/index.css new file mode 100644 index 00000000..22463e3e --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/index.css @@ -0,0 +1,72 @@ +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +ul { + list-style: none; + padding: 0; + margin: 0; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + background-color: darkblue; + color: white; + font-size: 1em; + font-weight: 500; + font-family: inherit; + cursor: pointer; + transition: background-color 0.25s; +} +button:hover { + background-color: blue; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/main.tsx b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/main.tsx new file mode 100644 index 00000000..3d7150da --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/main.tsx @@ -0,0 +1,10 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App.tsx' +import './index.css' + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/store/id.ts b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/store/id.ts new file mode 100644 index 00000000..a53b8fc4 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/store/id.ts @@ -0,0 +1,39 @@ +import { create } from 'zustand' +import { SignedMessage, MessageHistory } from '../types/Id' +import { persist, createJSONStorage } from 'zustand/middleware' + +export interface IdStore { + messageHistory: MessageHistory + addSignedMessage: (message: string, signature: number[]) => void + updateVerificationStatus: (index: number, verified: boolean) => void + get: () => IdStore + set: (partial: IdStore | Partial) => void +} + +const useIdStore = create()( + persist( + (set, get) => ({ + messageHistory: { messages: [] }, + addSignedMessage: (message: string, signature: number[]) => { + const { messageHistory } = get() + messageHistory.messages.push({ message, signature }) + set({ messageHistory }) + }, + updateVerificationStatus: (index: number, verified: boolean) => { + const { messageHistory } = get() + if (index >= 0 && index < messageHistory.messages.length) { + messageHistory.messages[index].verified = verified + set({ messageHistory }) + } + }, + get, + set, + }), + { + name: 'id', // unique name + storage: createJSONStorage(() => sessionStorage), // (optional) by default, 'localStorage' is used + } + ) +) + +export default useIdStore diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/types/Id.ts b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/types/Id.ts new file mode 100644 index 00000000..0b5bda01 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/types/Id.ts @@ -0,0 +1,32 @@ +export interface SignedMessage { + message: string + signature: number[] + verified?: boolean +} + +export interface NewMessage { + id: string + author: string + content: string +} + +export interface SignIdMessage { + Sign: number[] +} + +export interface VerifyIdMessage { + Verify: [number[], number[]] +} + +export interface SignResponse { + Ok: number[] +} + +export interface VerifyResponse { + Ok: boolean +} + +// MessageHistory consists of a list of signed messages +export interface MessageHistory { + messages: SignedMessage[] +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/types/global.ts b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/types/global.ts new file mode 100644 index 00000000..44640a4c --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/types/global.ts @@ -0,0 +1,10 @@ +declare module "global" { + global { + interface Window { + our: { + node: string; + process: string; + }; + } + } +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/vite-env.d.ts b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/tsconfig.json b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/tsconfig.json new file mode 100644 index 00000000..6f148432 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + // "strict": true, + // "noUnusedLocals": true, + // "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": [ + "src", + "../pkg/manifest.json", + "../pkg/metadata.json", + ], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/tsconfig.node.json b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/tsconfig.node.json new file mode 100644 index 00000000..42872c59 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/vite.config.ts b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/vite.config.ts new file mode 100644 index 00000000..3683e564 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/id/ui/vite.config.ts @@ -0,0 +1,67 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +/* +If you are developing a UI outside of a Hyperware project, +comment out the following 2 lines: +*/ +import manifest from '../pkg/manifest.json' +import metadata from '../metadata.json' + +/* +IMPORTANT: +This must match the process name from pkg/manifest.json + pkg/metadata.json +The format is "/" + "process_name:package_name:publisher_node" +*/ +const BASE_URL = `/${manifest[0].process_name}:${metadata.properties.package_name}:${metadata.properties.publisher}`; + +// This is the proxy URL, it must match the node you are developing against +const PROXY_URL = (process.env.VITE_NODE_URL || 'http://127.0.0.1:8080').replace('localhost', '127.0.0.1'); + +console.log('process.env.VITE_NODE_URL', process.env.VITE_NODE_URL, PROXY_URL); + +export default defineConfig({ + plugins: [react()], + base: BASE_URL, + build: { + rollupOptions: { + external: ['/our.js'] + } + }, + server: { + open: true, + proxy: { + '/our': { + target: PROXY_URL, + changeOrigin: true, + }, + [`${BASE_URL}/our.js`]: { + target: PROXY_URL, + changeOrigin: true, + rewrite: (path) => path.replace(BASE_URL, ''), + }, + // This route will match all other HTTP requests to the backend + [`^${BASE_URL}/(?!(@vite/client|src/.*|node_modules/.*|@react-refresh|$))`]: { + target: PROXY_URL, + changeOrigin: true, + }, + // '/example': { + // target: PROXY_URL, + // changeOrigin: true, + // rewrite: (path) => path.replace(BASE_URL, ''), + // // This is only for debugging purposes + // configure: (proxy, _options) => { + // proxy.on('error', (err, _req, _res) => { + // console.log('proxy error', err); + // }); + // proxy.on('proxyReq', (proxyReq, req, _res) => { + // console.log('Sending Request to the Target:', req.method, req.url); + // }); + // proxy.on('proxyRes', (proxyRes, req, _res) => { + // console.log('Received Response from the Target:', proxyRes.statusCode, req.url); + // }); + // }, + // }, + } + } +}); diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/Cargo.toml b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/Cargo.toml new file mode 100644 index 00000000..859185a7 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/Cargo.toml @@ -0,0 +1,11 @@ +[profile.release] +lto = true +opt-level = "s" +panic = "abort" + +[workspace] +members = [ + "sign", + "target/caller-utils", +] +resolver = "2" diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/README.md b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/README.md new file mode 100644 index 00000000..0c901b60 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/README.md @@ -0,0 +1,46 @@ +# sign + +A fork of [hyperdrive's `sign`](https://github.com/hyperware-ai/hyperdrive/tree/4d5223758087d2813f3598c69907306e953dbab1/hyperdrive/packages/sign) using the Hyperapp Framework. + +## Goals + +1. Get Hyperapp Framework into a more full-featured, robust state by serving as a testing ground for it & its `kit` integration, +2. Begin the move of core apps to Hyperapp Framework. + +## Usage + +Use [`hf/build-add-hyper-bindgen` branch of `kit`](https://github.com/hyperware-ai/kit/pull/312) i.e. +``` +cargo install --git https://github.com/hyperware-ai/kit --locked --branch hf/build-add-hyper-bindgen +``` + +Build using +``` +kit b --hyperapp +``` + +## Current state & TODOs + +1. Working end-to-end with [id](https://github.com/nick1udwig/id) as of [kit@3984259](https://github.com/hyperware-ai/kit/pull/312/commits/39842593e3cd4288823da93bff3658d7e1fdd84a) [sign@9570dbc](https://github.com/nick1udwig/sign/commit/9570dbc9cb0fbcd49eab9af692b1689dd5b23d2d) [id@6dd79d5](https://github.com/nick1udwig/id/commit/6dd79d591c1b98bbdc237c1558e6604136f12178). +2. Use as follows: + ``` + # Get proper version of kit + cargo install --git https://github.com/hyperware-ai/kit --locked --branch hf/build-add-hyper-bindgen + + # Start fake node + kit f + + # In new terminal + git clone https://github.com/nick1udwig/sign.git + cd sign + kit b --hyperapp + kit s + cd .. + + git clone https://github.com/nick1udwig/id.git + cd id + kit b --hyperapp -p 8080 + kit s + cd .. + ``` + Then open localhost:8080/id:id:sys and set your fake node terminal to Event Loop verbosity (hit Ctrl + V 3 times in the fake node terminal). diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/metadata.json b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/metadata.json new file mode 100644 index 00000000..e711b99c --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/metadata.json @@ -0,0 +1,18 @@ +{ + "name": "Sign", + "description": "Sign messages with Hyperware", + "image": "", + "properties": { + "package_name": "sign", + "current_version": "1.0.0", + "publisher": "sys", + "mirrors": [], + "code_hashes": { + "1.0.0": "" + }, + "wit_version": 1, + "dependencies": [] + }, + "external_url": "https://hyperware.ai", + "animation_url": "" +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/pkg/manifest.json b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/pkg/manifest.json new file mode 100644 index 00000000..1c4eaf09 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/pkg/manifest.json @@ -0,0 +1,11 @@ +[ + { + "process_name": "sign", + "process_wasm_path": "/sign.wasm", + "on_exit": "Restart", + "request_networking": false, + "request_capabilities": ["net:distro:sys", "vfs:distro:sys"], + "grant_capabilities": ["net:distro:sys", "vfs:distro:sys"], + "public": false + } +] diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/sign/Cargo.toml b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/sign/Cargo.toml new file mode 100644 index 00000000..d0c792a8 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/sign/Cargo.toml @@ -0,0 +1,35 @@ +[dependencies] +anyhow = "1.0.97" +process_macros = "0.1" +rmp-serde = "1.1.2" +serde_json = "1.0" +wit-bindgen = "0.36.0" + +[dependencies.caller-utils] +path = "../target/caller-utils" + +[dependencies.hyperprocess_macro] +git = "https://github.com/hyperware-ai/hyperprocess-macro" +rev = "4c944b2" + +[dependencies.hyperware_app_common] +git = "https://github.com/hyperware-ai/hyperprocess-macro" +rev = "4c944b2" + +[dependencies.serde] +features = ["derive"] +version = "1.0" + +[features] +simulation-mode = [] + +[lib] +crate-type = ["cdylib"] + +[package] +edition = "2021" +name = "sign" +version = "0.1.0" + +[package.metadata.component] +package = "hyperware:process" diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/sign/src/icon b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/sign/src/icon new file mode 100644 index 00000000..f67b371b --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/sign/src/icon @@ -0,0 +1 @@ +data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwMCIgaGVpZ2h0PSIxMDAwIiB2aWV3Qm94PSIwIDAgMTAwMCAxMDAwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cmVjdCB4PSIyMCIgeT0iMjAiIHdpZHRoPSI5NjAiIGhlaWdodD0iOTYwIiByeD0iNDgwIiBmaWxsPSJ1cmwoI3BhaW50MF9saW5lYXJfMjA5MV8xMDI4MikiIGZpbGwtb3BhY2l0eT0iMC40Ii8+CjxyZWN0IHg9IjIwIiB5PSIyMCIgd2lkdGg9Ijk2MCIgaGVpZ2h0PSI5NjAiIHJ4PSI0ODAiIHN0cm9rZT0idXJsKCNwYWludDFfbGluZWFyXzIwOTFfMTAyODIpIiBzdHJva2Utd2lkdGg9IjQwIi8+CjxwYXRoIGQ9Ik01ODEuMTE2IDU4NS43ODNMNjY0LjUzOCA2NjkuMTJDNjE3LjY5OSA3MTUuNzU4IDU1Ni42MjUgNzM5IDQ5NS4yNDUgNzM5QzQzMy44NjUgNzM5IDM3Mi42MzggNzE1LjYwNSAzMjYuMTA1IDY2OS4xMkMyODAuNzk3IDYyMy44NTggMjU2IDU2My45MTcgMjU2IDUwMEMyNTYgNDM2LjA4MyAyODAuOTUgMzc2LjE0MiAzMjYuMTA1IDMzMC44OEMzNzEuMjYgMjg1LjYxOSA0MzEuMjYyIDI2MSA0OTUuMjQ1IDI2MUM1NTkuMjI3IDI2MSA2MTkuMjMgMjg1LjkyNCA2NjQuNTM4IDMzMC44OEw1ODAuOTYzIDQxNC41MjNDNTQ1LjYwNCAzODMuOTQgNTA1LjE5NCAzNzQuNzY2IDQ2MS4yNjQgMzkxLjEyN0MzOTQuOTg1IDQxNS44OTkgMzY2LjgyMSA0ODkuMjk2IDM5Ny40MzUgNTUyLjc1NEMzOTguNjU5IDU1NS4yMDEgMzk4Ljk2NSA1NTguNzE4IDM5OC4zNTMgNTYxLjMxN0MzOTUuNzUxIDU3Mi40OCAzOTIuNjg5IDU4My40OSAzODkuNzgxIDU5NC4zNDZDMzg2LjEwNyA2MDcuOTU1IDM5My45MTQgNjE1Ljc1NCA0MDcuNTM3IDYxMi4yMzdDNDE4LjU1OCA2MDkuMzMxIDQyOS41NzkgNjA2LjEyIDQ0MC42IDYwMy42NzRDNDQzLjM1NSA2MDIuOTA5IDQ0Ny4wMjkgNjAzLjIxNSA0NDkuNjMxIDYwNC40MzhDNDkwLjUgNjIzLjM5OSA1MjkuOTkxIDYyMC44IDU2Ny43OTkgNTk2LjE4MUM1NzIuNTQ0IDU5My4xMjMgNTc2LjY3NyA1ODkuNDUzIDU4MS4xMTYgNTg1Ljc4M1oiIGZpbGw9InVybCgjcGFpbnQyX2xpbmVhcl8yMDkxXzEwMjgyKSIvPgo8ZGVmcz4KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDBfbGluZWFyXzIwOTFfMTAyODIiIHgxPSI1MDAiIHkxPSIwIiB4Mj0iNTAwIiB5Mj0iMTAwMCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPgo8c3RvcCBzdG9wLWNvbG9yPSIjRjM1NDIyIi8+CjxzdG9wIG9mZnNldD0iMSIgc3RvcC1vcGFjaXR5PSIwIi8+CjwvbGluZWFyR3JhZGllbnQ+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQxX2xpbmVhcl8yMDkxXzEwMjgyIiB4MT0iNzgyLjUiIHkxPSI3My41IiB4Mj0iMTg1LjUiIHkyPSI4OTQuNSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPgo8c3RvcCBzdG9wLWNvbG9yPSIjRjM1NDIyIi8+CjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI0E1MzEwQyIvPgo8L2xpbmVhckdyYWRpZW50Pgo8bGluZWFyR3JhZGllbnQgaWQ9InBhaW50Ml9saW5lYXJfMjA5MV8xMDI4MiIgeDE9Ijc1NCIgeTE9Ijg5LjUiIHgyPSIyNTYiIHkyPSIxMDE1LjUiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0YzNTQyMiIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNBNzMyMEQiLz4KPC9saW5lYXJHcmFkaWVudD4KPC9kZWZzPgo8L3N2Zz4K \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/sign/src/lib.rs b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/sign/src/lib.rs new file mode 100644 index 00000000..3f8fae06 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/example-apps/sign/sign/src/lib.rs @@ -0,0 +1,94 @@ +use anyhow::anyhow; + +use hyperware_process_lib::logging::{init_logging, Level}; +use hyperware_process_lib::net::{NetAction, NetResponse}; +use hyperware_process_lib::{last_blob, our, LazyLoadBlob, Request}; + +use hyperware_app_common::{send_rmp, source}; +use hyperprocess_macro::hyperprocess; + +#[derive(Default, Debug, serde::Serialize, serde::Deserialize)] +struct SignState {} + +async fn sign(message: Vec) -> anyhow::Result> { + let message = make_message(&message); + let body = rmp_serde::to_vec(&NetAction::Sign)?; + + let req = Request::to(("our", "net", "distro", "sys")) + .expects_response(5) + .blob(LazyLoadBlob { + mime: None, + bytes: message, + }) + .body(body); + + let _resp: NetResponse = send_rmp(req).await?; + + let Some(signature) = last_blob() else { + return Err(anyhow!("no blob")); + }; + + Ok(signature.bytes) +} + +async fn verify(message: Vec, signature: Vec) -> anyhow::Result { + let message = make_message(&message); + let body = rmp_serde::to_vec(&NetAction::Verify { + from: our(), + signature, + })?; + + let req = Request::to(("our", "net", "distro", "sys")) + .expects_response(5) + .blob(LazyLoadBlob { + mime: None, + bytes: message, + }) + .body(body); + + let resp: NetResponse = send_rmp(req).await?; + + match resp { + NetResponse::Verified(is_good) => { + Ok(is_good) + } + _ => Err(anyhow!("weird response")), + } +} + +/// net:distro:sys prepends the message to sign with the sender of the request +/// +/// since any sign requests passed through sign:sign:sys will look to net:distro:sys +/// like they come from sign:sign:sys, we additionally prepend the message with +/// source here +/// +/// so final message to be signed looks like +/// +/// [sign-address, source, bytes].concat() +fn make_message(bytes: &Vec) -> Vec { + [source().to_string().as_bytes(), &bytes].concat() +} + +#[hyperprocess( + name = "sign", + ui = None, + endpoints = vec![], + save_config = SaveOptions::Never, + wit_world = "sign-sys-v0", +)] +impl SignState { + #[init] + async fn init(&mut self) { + init_logging(Level::DEBUG, Level::INFO, None, None, None).unwrap(); + } + + #[local] + async fn sign(&mut self, message: Vec) -> Result, String> { + sign(message).await.map_err(|e| e.to_string()) + } + + #[local] + async fn verify(&mut self, message: Vec, signature: Vec) -> Result { + verify(message, signature).await.map_err(|e| e.to_string()) + } +} diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/guides/00-QUICK-REFERENCE.md b/src/new/templates/rust/ui/hyperapp-skeleton/resources/guides/00-QUICK-REFERENCE.md new file mode 100644 index 00000000..0764e0f2 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/guides/00-QUICK-REFERENCE.md @@ -0,0 +1,272 @@ +# 🚀 Hyperware Quick Reference for AI Models + +## Critical Rules - MUST FOLLOW + +### 1. HTTP Endpoints Parameter Handling +```rust +// ✅ Modern approach - Direct type deserialization (requires generated caller-utils) +#[http(method = "POST")] +async fn create_item(&mut self, request: CreateItemReq) -> Result { } + +// ✅ Legacy approach - Manual JSON parsing (still valid) +#[http] +async fn create_item(&mut self, request_body: String) -> Result { + let req: CreateItemReq = serde_json::from_str(&request_body)?; +} +``` + +**Note**: The modern approach requires generated TypeScript caller-utils that wrap requests in method-named objects. + +For detailed explanation and more examples, see [Troubleshooting Guide - Section 1](./02-TROUBLESHOOTING.md#error-failed-to-deserialize-http-request) + +### 2. Frontend MUST Include `/our.js` Script +```html + + + + + +``` + +### 3. API Call Formats +```typescript +// ✅ Modern approach (with generated caller-utils) +// Single parameter - wrapped in method-named object +{ "CreateItem": { name: "foo", value: 42 } } + +// ✅ Legacy approach (manual API calls) +// Single string parameter +{ "CreateItem": "raw string value" } +// Multiple parameters as array (rare) +{ "UpdateItem": ["id123", "new value"] } +``` + +**Note**: Most modern apps use generated caller-utils that handle the wrapping automatically. + +### 4. Remote Calls MUST Set Timeout +```rust +// ❌ WRONG - No timeout +Request::new() + .target(address) + .body(data) + .send(); + +// ✅ CORRECT - Always set expects_response +Request::new() + .target(address) + .body(data) + .expects_response(30) // 30 second timeout + .send_and_await_response(30); +``` + +### 5. WIT-Compatible Types Only +```rust +// ✅ ALLOWED +String, bool, u8-u64, i8-i64, f32, f64 +Vec, Option +Simple structs with public fields + +// ❌ NOT ALLOWED +HashMap → use Vec<(K,V)> +[T; N] → use Vec +Complex enums → use simple enums + separate data + +// 🔥 ESCAPE HATCH: Return JSON strings +#[http] +async fn get_complex(&self, _request_body: String) -> String { + serde_json::to_string(&self.complex_data).unwrap() +} +``` + +## Build Commands + +```bash +# First time build (installs dependencies) +kit bs --hyperapp + +# Regular build +kit b --hyperapp + +# Clean rebuild +rm -rf target/ ui/node_modules ui/dist pkg/ +kit b --hyperapp +``` + +**Note**: `kit b --hyperapp` automatically generates `pkg/manifest.json` + +## Project Structure +``` +skeleton-app/ +├── Cargo.toml # Workspace config +├── metadata.json # App metadata +├── skeleton-app/ # Rust backend +│ ├── Cargo.toml # DO NOT add hyperware_process_lib here! +│ └── src/ +│ └── lib.rs # Main app logic +├── ui/ # React frontend +│ ├── index.html # MUST have + + My App + +``` + +**Debug in Browser Console:** +```javascript +// Check if script loaded +console.log(window.our); +// Should show: { node: "yournode.os", process: "app:package:publisher" } + +// If undefined, check network tab for /our.js request +``` + +### ❌ Error: "Failed to parse ProcessId" + +**Examples:** +``` +Failed to parse ProcessId: InvalidFormat +``` + +**Root Cause:** Incorrect ProcessId format + +**Solution:** +```rust +// ❌ WRONG formats +let pid = "myapp".parse::(); // Missing parts +let pid = "myapp:myapp".parse::(); // Missing publisher +let pid = "myapp-myapp-publisher".parse::(); // Wrong separator + +// ✅ CORRECT format: "process:package:publisher" +let pid = "myapp:myapp:publisher.os".parse::()?; + +// For your app matching remote nodes +let publisher = "skeleton.os"; // Or whatever the remote uses +let pid = format!("skeleton-app:skeleton-app:{}", publisher) + .parse::()?; +``` + +### ❌ Error: Parameter format mismatch + +**Symptoms:** Frontend call succeeds but backend receives wrong data + +**Root Cause:** Multi-parameter endpoints need tuple format + +**Solution:** +```typescript +// ❌ WRONG - Object format +const response = await fetch('/api', { + body: JSON.stringify({ + CreateItem: { + name: "Item", + description: "Description" + } + }) +}); + +// ✅ CORRECT - Tuple/array format for multiple params +const response = await fetch('/api', { + body: JSON.stringify({ + CreateItem: ["Item", "Description"] + }) +}); + +// For single parameter, value directly +const response = await fetch('/api', { + body: JSON.stringify({ + GetItem: "item-id-123" + }) +}); +``` + +--- + +## 3. P2P Communication Issues + +### ❌ Error: "SendError" or "Failed to send request" + +**Common Causes:** + +1. **Target node not running:** +```bash +# Check if target node is accessible +# In your node's terminal, you should see incoming requests +``` + +2. **Wrong node name:** +```rust +// ❌ WRONG - Using placeholder +let target = Address::new("placeholder.os", process_id); + +// ✅ CORRECT - Use actual node name +let target = Address::new("alice.os", process_id); // Real node +``` + +3. **Missing timeout:** +```rust +// ❌ WRONG - No timeout set +Request::new() + .target(address) + .body(data) + .send(); + +// ✅ CORRECT - Always set expects_response +Request::new() + .target(address) + .body(data) + .expects_response(30) // REQUIRED! + .send_and_await_response(30)?; +``` + +4. **Wrong request format:** +```rust +// ❌ WRONG - Array format +let wrapper = json!({ + "HandleRequest": [param1, param2] // Arrays don't work +}); + +// ✅ CORRECT - Tuple format for multiple params +let wrapper = json!({ + "HandleRequest": (param1, param2) // Tuple format +}); + +// ✅ CORRECT - Single param +let wrapper = json!({ + "HandleRequest": param +}); +``` + +### ❌ Error: Remote endpoint not found + +**Symptom:** Call succeeds but returns error about missing method + +**Root Cause:** Method name mismatch or missing #[remote] attribute + +**Solution:** +```rust +// On receiving node: +#[remote] // Must have this attribute! +async fn handle_sync(&mut self, data: String) -> Result { + // Implementation +} + +// On calling node: +let wrapper = json!({ + "HandleSync": data // Must match exactly (case-sensitive) +}); +``` + +### ❌ Error: Can't decode remote response + +**Root Cause:** Response type mismatch + +**Solution:** +```rust +// ❌ Expecting wrong type +let response: ComplexType = serde_json::from_slice(&response.body())?; + +// ✅ Match what remote actually returns +let response: String = serde_json::from_slice(&response.body())?; +// Then parse if needed +let data: ComplexType = serde_json::from_str(&response)?; +``` + +### ❌ Error: ProcessId parse errors in P2P apps + +**Symptoms:** +``` +Failed to parse ProcessId: InvalidFormat +``` + +**Common P2P Pattern:** +```rust +// ❌ WRONG - Hardcoded publisher assumption +let pid = "samchat:samchat:publisher.os".parse::()?; + +// ✅ CORRECT - Use consistent publisher across nodes +let publisher = "hpn-testing-beta.os"; // Or get from config +let target_process_id_str = format!("samchat:samchat:{}", publisher); +let target_process_id = target_process_id_str.parse::() + .map_err(|e| format!("Failed to parse ProcessId: {}", e))?; +``` + +### ❌ Error: Node ID not initialized + +**Symptoms:** +``` +Sender node ID not initialized +``` + +**Root Cause:** Trying to use node ID before init + +**Solution:** +```rust +// In state +pub struct AppState { + my_node_id: Option, +} + +// In init +#[init] +async fn initialize(&mut self) { + self.my_node_id = Some(our().node.clone()); +} + +// In handlers +let sender = self.my_node_id.clone() + .ok_or_else(|| "Node ID not initialized".to_string())?; +``` + +### ❌ Error: Group/conversation management issues + +**Common P2P Chat Errors:** +```rust +// Group not found +let conversation = self.conversations.get(&group_id) + .ok_or_else(|| "Group conversation not found".to_string())?; + +// Not a group conversation +if !conversation.is_group { + return Err("Not a group conversation".to_string()); +} + +// Member already exists +if conversation.participants.contains(&new_member) { + return Err("Member already in group".to_string()); +} +``` + +### ❌ Error: Remote file/data fetch failures + +**Complex P2P data retrieval pattern:** +```rust +// Try local first, then remote +match local_result { + Ok(response) => { + if let Some(blob) = response.blob() { + return Ok(blob.bytes); + } + }, + Err(_) => { + // Fetch from remote node + let remote_result = Request::new() + .target(remote_address) + .body(request_body) + .expects_response(30) + .send_and_await_response(30)?; + + match remote_result { + Ok(response) => { + // Parse nested Result + let response_json: serde_json::Value = + serde_json::from_slice(&response.body())?; + + if let Some(data) = response_json.get("Ok") { + // Handle success + } else if let Some(err) = response_json.get("Err") { + return Err(format!("Remote error: {}", err)); + } + }, + Err(e) => return Err(format!("Remote fetch failed: {:?}", e)) + } + } +} +``` + +--- + +## 4. State Management Issues + +### ❌ Error: State not persisting + +**Root Cause:** Wrong save_config or state not serializable + +**Solution:** +```rust +#[hyperprocess( + // ... + save_config = SaveOptions::EveryMessage, // Most reliable + // OR + save_config = SaveOptions::OnInterval(30), // Every 30 seconds +)] + +// Ensure state is serializable +#[derive(Default, Serialize, Deserialize)] +pub struct AppState { + // All fields must be serializable +} +``` + +### ❌ Error: Race conditions in React state + +**Symptom:** Action uses old state value + +**Solution:** +```typescript +// ❌ WRONG - State might not be updated +const handleJoin = async (gameId: string) => { + setSelectedGame(gameId); + await joinGame(); // Uses selectedGame from state - WRONG! +}; + +// ✅ CORRECT - Pass value explicitly +const handleJoin = async (gameId: string) => { + setSelectedGame(gameId); + await joinGame(gameId); // Pass directly +}; + +// ✅ BETTER - Use callback form +const handleUpdate = () => { + setItems(prevItems => { + // Work with prevItems, not items from closure + return [...prevItems, newItem]; + }); +}; +``` + +### ❌ Error: Stale data in UI + +**Root Cause:** Not refreshing after mutations + +**Solution:** +```typescript +// In your store +const createItem = async (data: CreateData) => { + try { + await api.createItem(data); + // ✅ Refresh data after mutation + await get().fetchItems(); + } catch (error) { + // Handle error + } +}; + +// With optimistic updates +const deleteItem = async (id: string) => { + // Optimistic update + set(state => ({ + items: state.items.filter(item => item.id !== id) + })); + + try { + await api.deleteItem(id); + } catch (error) { + // Rollback on error + await get().fetchItems(); + throw error; + } +}; +``` + +--- + +## 5. Manifest & Capability Issues + +### ❌ Error: "failed to open file `pkg/manifest.json`" + +**Full Error:** +``` +ERROR: failed to open file `/path/to/app/pkg/manifest.json` +No such file or directory (os error 2) +``` + +**Root Cause:** manifest.json not generated during build + +**Solutions:** + +1. **Build properly with kit:** +```bash +# This generates manifest.json automatically +kit b --hyperapp +``` + +2. **Check if pkg directory exists:** +```bash +ls -la pkg/ +# Should contain: manifest.json, your-app.wasm, ui/ +``` + +3. **If still missing, check metadata.json:** +```json +// metadata.json must exist and be valid +{ + "package": "skeleton-app", + "publisher": "skeleton.os" +} +``` + +**See**: [Manifest & Deployment Guide](./08-MANIFEST-AND-DEPLOYMENT.md) for details + +### ❌ Error: "Process does not have capability X" + +**Example:** +``` +Error: Process skeleton-app:skeleton-app:user.os does not have capability vfs:distro:sys +``` + +**Root Cause:** Using system feature without requesting capability + +**Solution:** Add to manifest.json: +```json +"request_capabilities": [ + "homepage:homepage:sys", + "http-server:distro:sys", + "vfs:distro:sys" // Add missing capability +] +``` + +**See**: [Capabilities Guide](./09-CAPABILITIES-GUIDE.md) for all capabilities + +### ❌ Error: App doesn't appear on homepage + +**Root Cause:** Missing homepage capability or add_to_homepage call + +**Solution:** +1. Check manifest.json includes: +```json +"request_capabilities": [ + "homepage:homepage:sys" // Required! +] +``` + +2. Check init function calls: +```rust +#[init] +async fn initialize(&mut self) { + add_to_homepage("My App", Some("🚀"), Some("/"), None); +} +``` + +--- + +## 6. Development Workflow Issues + +### Clean Build Process +```bash +# When things are really broken +rm -rf target/ +rm -rf ui/node_modules ui/dist +rm -rf pkg/ +rm Cargo.lock + +# Fresh build +kit b --hyperapp +``` + +### Check Generated Files +```bash +# View generated WIT +cat api/*.wit + +# Check built package +ls -la pkg/ + +# Verify UI was built +ls -la pkg/ui/ +``` + +### Test Incrementally +```bash +# 1. Test backend compiles +cd skeleton-app && cargo check + +# 2. Test UI builds +cd ui && npm run build + +# 3. Full build +cd .. && kit b --hyperapp +``` + +--- + +## 6. Common Patterns That Cause Issues + +### ❌ WebSocket Handler Issues +```rust +// ❌ WRONG - Async WebSocket handler +#[ws] +async fn websocket(&mut self, channel_id: u32, message_type: WsMessageType, blob: LazyLoadBlob) { + // WebSocket handlers must NOT be async! +} + +// ✅ CORRECT - Synchronous handler +#[ws] +fn websocket(&mut self, channel_id: u32, message_type: WsMessageType, blob: LazyLoadBlob) { + match message_type { + WsMessageType::Text => { + // Handle text message + } + WsMessageType::Close => { + // Handle disconnect + } + _ => {} + } +} +``` + +**Common WebSocket Issues:** +1. **Missing endpoint configuration** in hyperprocess macro: +```rust +#[hyperprocess( + endpoints = vec![ + Binding::Ws { + path: "/ws", + config: WsBindingConfig::default().authenticated(false), + }, + ], +)] +``` + +2. **Frontend connection issues:** +```typescript +// ❌ WRONG - Missing authentication +const ws = new WebSocket('ws://localhost:8080/ws'); + +// ✅ CORRECT - Include proper URL +const ws = new WebSocket(`ws://${window.location.host}/${appName}/ws`); +``` + +### ❌ Forgetting async on endpoints +```rust +// ❌ WRONG - Not async +#[http] +fn get_data(&self, _request_body: String) -> String { + // Won't compile +} + +// ✅ CORRECT - Must be async +#[http] +async fn get_data(&self, _request_body: String) -> String { + // Works +} +``` + +### ❌ Wrong imports order +```rust +// ❌ Can cause issues +use serde::{Serialize, Deserialize}; +use hyperprocess_macro::*; + +// ✅ Better order +use hyperprocess_macro::*; +use hyperware_process_lib::{our, Address, ProcessId, Request}; +use serde::{Deserialize, Serialize}; +``` + +--- + +## Debug Checklist + +When nothing works, check: + +1. **Build issues:** + - [ ] All HTTP methods have `_request_body` parameter? + - [ ] No `hyperware_process_lib` in Cargo.toml? + - [ ] All types are WIT-compatible? + - [ ] `#[hyperprocess]` before impl block? + +2. **Runtime issues:** + - [ ] `/our.js` script in HTML head? + - [ ] Node is actually running? + - [ ] Correct ProcessId format? + - [ ] Frontend using tuple format for params? + +3. **P2P issues:** + - [ ] Target node running? + - [ ] Using real node names? + - [ ] `expects_response` timeout set? + - [ ] Method names match exactly? + +4. **State issues:** + - [ ] State is serializable? + - [ ] Refreshing after mutations? + - [ ] Passing values explicitly (not from React state)? + +## 7. Audio/Real-time Data Issues (Voice Apps) + +### ❌ Base64 encoding/decoding issues +```rust +// ❌ WRONG - Manual base64 handling +let decoded = base64::decode(&data)?; + +// ✅ CORRECT - Use proper engine +use base64::{Engine as _, engine::general_purpose}; +let decoded = general_purpose::STANDARD.decode(&data).unwrap_or_default(); +let encoded = general_purpose::STANDARD.encode(&bytes); +``` + +### ❌ Thread safety with audio processing +```rust +// ❌ WRONG - Direct mutation in WebSocket handler +self.audio_buffer.push(audio_data); + +// ✅ CORRECT - Use Arc> for thread-safe access +use std::sync::{Arc, Mutex}; + +// In state +audio_processors: HashMap>>, + +// In handler +if let Ok(mut proc) = processor.lock() { + proc.process_audio(data); +} +``` + +### ❌ WebSocket message sequencing +```rust +// Track sequence numbers for audio streams +#[derive(Serialize, Deserialize)] +struct AudioData { + data: String, + sequence: Option, + timestamp: Option, +} + +// Maintain sequence counters +participant_sequences: HashMap, +``` + +### ❌ Binary data in LazyLoadBlob +```rust +// For binary WebSocket data +let blob = LazyLoadBlob { + mime: Some("application/octet-stream".to_string()), + bytes: audio_bytes, +}; +send_ws_push(channel_id, WsMessageType::Binary, blob); +``` + +## 8. P2P Validation Patterns + +### Common P2P validation errors from samchat: + +**Backend validation:** +```rust +// Empty fields +if recipient_address.trim().is_empty() || message_content.trim().is_empty() { + return Err("Recipient address and message content cannot be empty".to_string()); +} + +// Format validation +if !is_group && !recipient_address.contains('.') { + return Err("Invalid recipient address format (e.g., 'username.os')".to_string()); +} + +// Group constraints +if participants.len() < 2 { + return Err("Group must have at least 2 participants".to_string()); +} +``` + +**Frontend validation:** +```typescript +// In React component +if (!groupName.trim()) { + setError("Please enter a group name"); + return; +} + +// Parse and validate lists +const members = groupMembers.split(',').map(m => m.trim()).filter(m => m); +if (members.length === 0) { + setError("Please enter at least one valid member address"); + return; +} + +// Clear errors on navigation +const handleSelectConversation = useCallback((conversationId: string) => { + fetchMessages(conversationId); + setError(null); + setReplyingTo(null); +}, [fetchMessages]); +``` + +## Still Stuck? + +1. Add logging everywhere: + ```rust + println!("DEBUG: Method called with: {:?}", request_body); + ``` + +2. Check both node consoles for P2P issues + +3. Use browser DevTools: + - Network tab for HTTP/WebSocket + - Console for JavaScript errors + - Application tab for storage + +4. For voice apps: + - Check browser permissions for microphone + - Monitor WebSocket frames in DevTools + - Log audio buffer sizes and timing + +5. Start with minimal example and add complexity + +6. Compare with working examples: + - samchat for P2P chat patterns + - voice for WebSocket/audio patterns \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/guides/03-WIT-TYPES-DATA-MODELING.md b/src/new/templates/rust/ui/hyperapp-skeleton/resources/guides/03-WIT-TYPES-DATA-MODELING.md new file mode 100644 index 00000000..2d3aa391 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/guides/03-WIT-TYPES-DATA-MODELING.md @@ -0,0 +1,734 @@ +# 📊 WIT Types & Data Modeling Guide + +## Understanding WIT (WebAssembly Interface Types) + +WIT is the type system that bridges your Rust code with the frontend. The hyperprocess macro automatically generates WIT files from your Rust types, but it has strict requirements. + +## Type Compatibility Matrix + +| Rust Type | WIT Type | Supported | Notes | +|-----------|----------|-----------|-------| +| `bool` | `bool` | ✅ | | +| `u8`, `u16`, `u32`, `u64` | `u8`, `u16`, `u32`, `u64` | ✅ | | +| `i8`, `i16`, `i32`, `i64` | `s8`, `s16`, `s32`, `s64` | ✅ | | +| `f32`, `f64` | `float32`, `float64` | ✅ | | +| `String` | `string` | ✅ | | +| `Vec` | `list` | ✅ | T must be supported | +| `Option` | `option` | ✅ | T must be supported | +| `(T1, T2, ...)` | `tuple` | ✅ | All T must be supported | +| `HashMap` | - | ❌ | Use `Vec<(K, V)>` | +| `HashSet` | - | ❌ | Use `Vec` | +| `[T; N]` | - | ❌ | Use `Vec` | +| `&str` | - | ❌ | Use `String` | +| `&[T]` | - | ❌ | Use `Vec` | +| Complex enums | - | ⚠️ | Only simple variants | +| Trait objects | - | ❌ | Not supported | + +## Data Modeling Strategies + +### 1. Simple Types - Direct Mapping + +```rust +// ✅ These types map directly to WIT +#[derive(Serialize, Deserialize, PartialEq)] +pub struct User { + pub id: String, + pub name: String, + pub age: u32, + pub active: bool, + pub balance: f64, +} + +#[derive(Serialize, Deserialize, PartialEq)] +pub struct Response { + pub users: Vec, + pub total: u64, + pub page: Option, +} + +// Use in endpoint +#[http] +async fn get_users(&self, _request_body: String) -> Response { + Response { + users: self.users.clone(), + total: self.users.len() as u64, + page: Some(0), + } +} +``` + +### 2. Complex Types - JSON String Pattern + +```rust +// Internal complex type (not exposed via WIT) +#[derive(Serialize, Deserialize)] +struct ComplexGameState { + board: HashMap, + history: Vec, + timers: HashMap, + metadata: serde_json::Value, +} + +// ✅ Return as JSON string +#[http] +async fn get_game_state(&self, _request_body: String) -> String { + serde_json::to_string(&self.game_state).unwrap() +} + +// ✅ Accept as JSON string +#[http] +async fn update_game_state(&mut self, request_body: String) -> Result { + let state: ComplexGameState = serde_json::from_str(&request_body) + .map_err(|e| format!("Invalid game state: {}", e))?; + + self.game_state = state; + Ok("Updated".to_string()) +} +``` + +### 3. Enum Handling + +```rust +// ❌ WRONG - Complex enum variants not supported by WIT directly +pub enum GameEvent { + PlayerJoined { player_id: String, timestamp: u64 }, + MoveMade { from: Position, to: Position }, + GameEnded { winner: Option, reason: EndReason }, +} + +// ✅ PATTERN 1: Simple enum + data struct (WIT-compatible) +#[derive(Serialize, Deserialize, PartialEq)] +pub enum EventType { + PlayerJoined, + MoveMade, + GameEnded, +} + +#[derive(Serialize, Deserialize, PartialEq)] +pub struct GameEvent { + pub event_type: EventType, + pub player_id: Option, + pub from_position: Option, + pub to_position: Option, + pub winner: Option, + pub timestamp: u64, +} + +// ✅ PATTERN 2: Complex enums with mixed variants (JSON-only) +#[derive(Serialize, Deserialize)] +pub enum WsMessage { + // Simple variants work fine + Heartbeat, + Disconnect, + + // Complex variants with nested serde attributes + #[serde(rename_all = "camelCase")] + JoinRoom { + room_id: String, + auth_token: Option, + user_settings: UserSettings, + }, + + // Single data variants + Chat(String), + UpdateStatus(Status), +} + +// ✅ PATTERN 3: Tagged unions via JSON +#[derive(Serialize, Deserialize)] +#[serde(tag = "type")] +pub enum GameEvent { + PlayerJoined { player_id: String, timestamp: u64 }, + MoveMade { from: Position, to: Position }, + GameEnded { winner: Option }, +} + +// Return as JSON string +#[http] +async fn get_events(&self, _request_body: String) -> String { + serde_json::to_string(&self.events).unwrap() +} +``` + +### 4. HashMap Replacement Patterns + +```rust +// ❌ WRONG - HashMap not supported +pub struct GameData { + pub players: HashMap, + pub scores: HashMap, +} + +// ✅ PATTERN 1: Use Vec of tuples +#[derive(Serialize, Deserialize, PartialEq)] +pub struct GameData { + pub players: Vec<(String, Player)>, + pub scores: Vec<(String, u32)>, +} + +// ✅ PATTERN 2: Separate key-value struct +#[derive(Serialize, Deserialize, PartialEq)] +pub struct PlayerEntry { + pub id: String, + pub player: Player, +} + +#[derive(Serialize, Deserialize, PartialEq)] +pub struct ScoreEntry { + pub player_id: String, + pub score: u32, +} + +#[derive(Serialize, Deserialize, PartialEq)] +pub struct GameData { + pub players: Vec, + pub scores: Vec, +} + +// ✅ PATTERN 3: Internal HashMap, external Vec +#[derive(Default, Serialize, Deserialize)] +pub struct AppState { + // Internal representation (not exposed) + players_map: HashMap, +} + +// Exposed via endpoints +#[http] +async fn get_players(&self, _request_body: String) -> Vec { + self.players_map.values().cloned().collect() +} + +#[http] +async fn get_player(&self, request_body: String) -> Result { + let id: String = serde_json::from_str(&request_body)?; + self.players_map.get(&id) + .cloned() + .ok_or_else(|| "Player not found".to_string()) +} +``` + +### 5. Nested Type Visibility + +```rust +// ❌ PROBLEM: WIT generator can't find NestedData +pub struct Response { + pub data: NestedData, +} + +pub struct NestedData { + pub items: Vec, +} + +pub struct Item { + pub id: String, +} + +// ✅ FIX 1: Ensure all types are referenced in endpoints +#[http] +async fn get_response(&self, _request_body: String) -> Response { ... } + +#[http] +async fn get_nested_data(&self, _request_body: String) -> NestedData { ... } + +#[http] +async fn get_item(&self, _request_body: String) -> Item { ... } + +// ✅ FIX 2: Flatten the structure +#[derive(Serialize, Deserialize, PartialEq)] +pub struct Response { + pub items: Vec, + pub metadata: ResponseMetadata, +} +``` + +## Design Patterns for Data Modeling + +### 1. Command Pattern for Complex Operations + +```rust +// Instead of complex parameters, use command objects +#[derive(Deserialize)] +pub struct CreateGameCommand { + pub name: String, + pub max_players: u8, + pub settings: GameSettings, +} + +#[derive(Deserialize)] +pub struct GameSettings { + pub time_limit: Option, + pub allow_spectators: bool, + pub game_mode: String, +} + +// ✅ Modern approach - Direct type deserialization +#[http(method = "POST")] +async fn create_game(&mut self, command: CreateGameCommand) -> Result { + // Process command directly + let game_id = self.create_game_from_command(command)?; + + Ok(GameInfo { + id: game_id, + status: GameStatus::Waiting, + }) +} + +// ✅ Legacy approach - Manual JSON parsing +#[http] +async fn create_game_legacy(&mut self, request_body: String) -> Result { + let command: CreateGameCommand = serde_json::from_str(&request_body)?; + + // Process command + let game_id = self.create_game_from_command(command)?; + + Ok(serde_json::json!({ "game_id": game_id }).to_string()) +} +``` + +### 2. View Pattern for Complex Queries + +```rust +// Internal complex state +struct Game { + id: String, + players: HashMap, + board: BoardState, + history: Vec, + // ... many more fields +} + +// Simplified view for API +#[derive(Serialize, Deserialize, PartialEq)] +pub struct GameView { + pub id: String, + pub player_count: u8, + pub current_turn: String, + pub status: GameStatus, +} + +#[derive(Serialize, Deserialize, PartialEq)] +pub struct GameDetailView { + pub id: String, + pub players: Vec, + pub board_state: String, // Serialized board + pub last_move: Option, +} + +// Expose views, not internal state +#[http] +async fn list_games(&self, _request_body: String) -> Vec { + self.games.values() + .map(|game| game.to_view()) + .collect() +} + +#[http] +async fn get_game_detail(&self, request_body: String) -> Result { + let id: String = serde_json::from_str(&request_body)?; + self.games.get(&id) + .map(|game| game.to_detail_view()) + .ok_or_else(|| "Game not found".to_string()) +} +``` + +### 3. Event Sourcing Pattern + +```rust +// Events as simple data +#[derive(Serialize, Deserialize, PartialEq)] +pub struct Event { + pub id: String, + pub timestamp: String, + pub event_type: String, + pub data: String, // JSON encoded event data +} + +// Store events, rebuild state +#[derive(Default, Serialize, Deserialize)] +pub struct AppState { + events: Vec, + // Cached current state (rebuilt from events) + #[serde(skip)] + current_state: Option, +} + +impl AppState { + fn rebuild_state(&mut self) { + let mut state = ComputedState::default(); + for event in &self.events { + state.apply_event(event); + } + self.current_state = Some(state); + } +} + +#[http] +async fn add_event(&mut self, request_body: String) -> Result { + let event: Event = serde_json::from_str(&request_body)?; + self.events.push(event); + self.rebuild_state(); + Ok("Event added".to_string()) +} +``` + +## Real-World Patterns from P2P Apps + +### Timestamp Handling (from samchat) + +```rust +// ❌ WRONG - chrono types not WIT-compatible +use chrono::{DateTime, Utc}; +pub struct Message { + pub timestamp: DateTime, +} + +// ✅ CORRECT - RFC3339 strings (sorts lexicographically!) +pub struct ChatMessage { + pub timestamp: String, // RFC3339 string for WIT compatibility +} + +// Usage +let current_time_str = Utc::now().to_rfc3339(); + +// Sorting works naturally with RFC3339 strings +conversation.messages.sort_by(|a, b| a.timestamp.cmp(&b.timestamp)); +``` + +### Complex Message Types with Optionals + +```rust +// P2P chat pattern: One type handles multiple scenarios +#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)] +pub struct ChatMessage { + pub id: String, + pub conversation_id: String, + pub sender: String, + pub recipient: Option, // None for group messages + pub recipients: Option>, // Some for group messages + pub content: String, + pub timestamp: String, + pub delivered: bool, + pub file_info: Option, // Optional attachment + pub reply_to: Option, // Optional reply +} + +// This avoids complex enums while supporting: +// - Direct messages (recipient = Some, recipients = None) +// - Group messages (recipient = None, recipients = Some) +// - Messages with/without files +// - Messages with/without replies +``` + +### HashMap in State, Vec in API + +```rust +// Internal state uses HashMap for efficiency +#[derive(Default, Serialize, Deserialize)] +pub struct SamchatState { + conversations: HashMap, + my_node_id: Option, +} + +// But expose as Vec through endpoints +#[http] +async fn get_conversations(&self, _request_body: String) -> Vec { + self.conversations.values() + .map(|conv| ConversationSummary { + id: conv.id.clone(), + participants: conv.participants.clone(), + last_updated: conv.last_updated.clone(), + is_group: conv.is_group, + group_name: conv.group_name.clone(), + }) + .collect() +} +``` + +### Binary Data Transfer + +```rust +// Backend: Vec for file data +#[http] +async fn upload_file(&mut self, file_name: String, mime_type: String, file_data: Vec) -> Result { + // Process binary data +} + +// Frontend TypeScript: number[] maps to Vec +export interface UploadFileRequest { + UploadFile: [string, string, number[]]; // file_name, mime_type, file_data +} +``` + +## TypeScript/JavaScript Compatibility + +### camelCase Serialization + +When your frontend uses TypeScript/JavaScript conventions, use serde's rename attributes: + +```rust +// ✅ Rust snake_case -> TypeScript camelCase +#[derive(Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "camelCase")] +pub struct UserProfile { + pub user_id: String, // -> userId + pub display_name: String, // -> displayName + pub created_at: u64, // -> createdAt + pub is_active: bool, // -> isActive +} + +// ✅ Works with enums too +#[derive(Serialize, Deserialize)] +pub enum ApiMessage { + #[serde(rename_all = "camelCase")] + UserJoined { + user_id: String, + joined_at: u64, + }, + + #[serde(rename_all = "camelCase")] + MessageSent { + message_id: String, + sender_id: String, + sent_at: u64, + }, +} + +// ✅ Different rename patterns +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] // For C# style +pub struct ConfigData { + pub app_name: String, // -> AppName + pub version: String, // -> Version +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] // For constants +pub struct Constants { + pub max_users: u32, // -> MAX_USERS + pub timeout_ms: u64, // -> TIMEOUT_MS +} +``` + +### Skip Serialization + +For internal fields that shouldn't be exposed: + +```rust +#[derive(Default, Serialize, Deserialize)] +pub struct AppState { + // Public fields + pub users: Vec, + pub settings: Settings, + + // Internal cache - not serialized + #[serde(skip)] + user_cache: HashMap, + + // Skip with default value on deserialize + #[serde(skip_deserializing, default)] + computed_stats: Stats, + + // Custom default function + #[serde(skip, default = "default_processors")] + processors: HashMap, +} + +fn default_processors() -> HashMap { + HashMap::new() +} +``` + +## Best Practices + +### 1. Always Add PartialEq + +```rust +// WIT-exposed types need PartialEq +#[derive(Serialize, Deserialize, PartialEq)] +pub struct MyType { + pub field: String, +} +``` + +### 2. Use Builder Pattern for Complex Types + +```rust +#[derive(Default)] +pub struct GameBuilder { + name: Option, + max_players: Option, + settings: GameSettings, +} + +impl GameBuilder { + pub fn name(mut self, name: String) -> Self { + self.name = Some(name); + self + } + + pub fn max_players(mut self, max: u8) -> Self { + self.max_players = Some(max); + self + } + + pub fn build(self) -> Result { + Ok(Game { + id: uuid::Uuid::new_v4().to_string(), + name: self.name.ok_or("Name required")?, + max_players: self.max_players.unwrap_or(4), + settings: self.settings, + // ... initialize other fields + }) + } +} +``` + +### 3. Version Your Data Models + +```rust +#[derive(Serialize, Deserialize)] +pub struct SaveData { + pub version: u32, + pub data: serde_json::Value, +} + +impl SaveData { + pub fn migrate(self) -> Result { + match self.version { + 1 => migrate_v1_to_v2(self.data), + 2 => Ok(serde_json::from_value(self.data)?), + _ => Err(format!("Unknown version: {}", self.version)), + } + } +} +``` + +### 4. Document Your Types + +```rust +/// Represents a player in the game +#[derive(Serialize, Deserialize, PartialEq)] +pub struct Player { + /// Unique identifier for the player + pub id: String, + + /// Display name chosen by the player + pub name: String, + + /// Current score in the game + pub score: u32, + + /// Whether the player is currently active + pub active: bool, +} +``` + +## Common Patterns Reference + +### Pattern 1: ID-based Lookups +```rust +// Store as HashMap internally, expose as list +pub struct AppState { + items_map: HashMap, +} + +#[http] +async fn get_item(&self, request_body: String) -> Result { + let id: String = serde_json::from_str(&request_body)?; + self.items_map.get(&id).cloned() + .ok_or_else(|| "Not found".to_string()) +} + +#[http] +async fn list_items(&self, _request_body: String) -> Vec { + self.items_map.values().cloned().collect() +} +``` + +### Pattern 2: Pagination +```rust +#[derive(Deserialize)] +pub struct PageRequest { + pub page: usize, + pub per_page: usize, +} + +#[derive(Serialize, PartialEq)] +pub struct PageResponse { + pub items: Vec, + pub total: usize, + pub page: usize, + pub per_page: usize, +} + +#[http] +async fn list_paginated(&self, request_body: String) -> PageResponse { + let req: PageRequest = serde_json::from_str(&request_body) + .unwrap_or(PageRequest { page: 0, per_page: 20 }); + + let start = req.page * req.per_page; + let items: Vec<_> = self.items + .iter() + .skip(start) + .take(req.per_page) + .cloned() + .collect(); + + PageResponse { + items, + total: self.items.len(), + page: req.page, + per_page: req.per_page, + } +} +``` + +### Pattern 3: Result Types +```rust +#[derive(Serialize, Deserialize, PartialEq)] +pub struct ApiResult { + pub success: bool, + pub data: Option, + pub error: Option, +} + +impl ApiResult { + pub fn ok(data: T) -> Self { + Self { + success: true, + data: Some(data), + error: None, + } + } + + pub fn err(error: String) -> Self { + Self { + success: false, + data: None, + error: Some(error), + } + } +} + +#[http] +async fn safe_operation(&mut self, request_body: String) -> ApiResult { + match self.do_operation(request_body) { + Ok(result) => ApiResult::ok(result), + Err(e) => ApiResult::err(e.to_string()), + } +} +``` + +## Remember + +1. **When in doubt, use JSON strings** - They always work +2. **All public fields** - WIT needs to see them +3. **Test incrementally** - Build often to catch type issues early +4. **Keep it simple** - Complex types cause problems +5. **Document patterns** - Future you will thank you + +## See Also + +- [Troubleshooting Guide](./02-TROUBLESHOOTING.md#error-found-types-used-that-are-neither-wit-built-ins-nor-defined-locally) - For WIT type errors +- [Common Patterns](./01-COMMON-PATTERNS.md) - For implementation examples +- [Complete Examples](./07-COMPLETE-EXAMPLES.md) - For real-world usage \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/guides/04-P2P-PATTERNS.md b/src/new/templates/rust/ui/hyperapp-skeleton/resources/guides/04-P2P-PATTERNS.md new file mode 100644 index 00000000..62b4e470 --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/guides/04-P2P-PATTERNS.md @@ -0,0 +1,1079 @@ +# 🌐 P2P Communication Patterns Guide + +## Core Concepts + +In Hyperware, every user runs their own node. P2P communication allows nodes to: +- Share data directly without central servers +- Coordinate actions across the network +- Build collaborative applications +- Maintain distributed state + +## Endpoint Attributes + +Understanding the different endpoint types: + +- **`#[http]`** - HTTP endpoints accessible via frontend API calls +- **`#[remote]`** - Endpoints callable by other nodes via P2P +- **`#[local]`** - Internal endpoints callable within the same node +- **`#[local] #[remote]`** - Endpoints callable both locally and remotely + +```rust +// HTTP only - frontend calls +#[http] +async fn get_data(&self, _request_body: String) -> Vec { } + +// Remote only - other nodes call this +#[remote] +async fn sync_data(&mut self, data: String) -> Result { } + +// Both local and remote - flexible access +#[local] +#[remote] +async fn process_request(&mut self, req: Request) -> Result { } +``` + +## Essential Components + +### 1. Node Identity +```rust +// Get your own node identity +let my_node = our().node.clone(); // e.g., "alice.os" + +// Node identity comes from the user, not hardcoded +#[http] +async fn connect_to_node(&mut self, request_body: String) -> Result { + let target_node: String = serde_json::from_str(&request_body)?; + // Use target_node for communication +} +``` + +### 2. Process Identity +```rust +// ProcessId format: "process-name:package-name:publisher" +// Note: publisher must match between communicating nodes +let process_id = "myapp:myapp:publisher.os" + .parse::() + .map_err(|e| format!("Invalid ProcessId: {}", e))?; + +// For your app to talk to itself on other nodes +// IMPORTANT: All nodes must use the same publisher! +let my_process_id = format!("{}:{}:{}", + "skeleton-app", // process name (from metadata.json) + "skeleton-app", // package name (from metadata.json) + "skeleton.os" // publisher (must be consistent across nodes) +).parse::()?; +``` + +### 3. Address Construction +```rust +// Combine node + process to create full address +let target_address = Address::new( + "bob.os".to_string(), // target node + process_id // target process +); +``` + +### 4. Request Patterns + +Two ways to make P2P requests: + +**Traditional Pattern (hyperware_process_lib::Request):** +```rust +let response = Request::new() + .target(target_address) + .body(serde_json::to_vec(&data).unwrap()) + .expects_response(30) + .send_and_await_response(30)?; +``` + +**Modern Pattern (hyperware_app_common::send):** +```rust +use hyperware_app_common::send; + +// Type-safe request with automatic deserialization +let request = Request::to(&target_address) + .body(serde_json::to_vec(&data).unwrap()); + +match send::>(request).await { + Ok(Ok(response)) => { + // Use response directly - already deserialized + } + Ok(Err(e)) => { + // Remote returned an error + } + Err(e) => { + // Network/communication error + } +} +``` + +## P2P Communication Patterns + +### Pattern 1: Direct Request-Response + +**Use Case:** Query data from another node + +```rust +// On the requesting node +#[http] +async fn get_remote_data(&self, request_body: String) -> Result { + let target_node: String = serde_json::from_str(&request_body)?; + + // Build address + let process_id = "skeleton-app:skeleton-app:skeleton.os".parse::()?; + let target = Address::new(target_node, process_id); + + // Create request + let request_data = json!({ + "since": self.last_sync_time, + "limit": 100 + }); + + // Wrap for remote method + let wrapper = json!({ + "GetDataSince": serde_json::to_string(&request_data).unwrap() + }); + + // Send and await response + let response = Request::new() + .target(target) + .body(serde_json::to_vec(&wrapper).unwrap()) + .expects_response(30) // 30 second timeout + .send_and_await_response(30) + .map_err(|e| format!("Remote request failed: {:?}", e))?; + + // Parse response + if let Ok(body) = response.body() { + Ok(String::from_utf8_lossy(&body).to_string()) + } else { + Err("No response body".to_string()) + } +} + +// On the receiving node +#[remote] +async fn get_data_since(&self, request_json: String) -> Result { + #[derive(Deserialize)] + struct DataRequest { + since: String, + limit: usize, + } + + let req: DataRequest = serde_json::from_str(&request_json)?; + + // Get requested data + let data: Vec<_> = self.data.iter() + .filter(|d| d.timestamp > req.since) + .take(req.limit) + .cloned() + .collect(); + + Ok(serde_json::to_string(&data).unwrap()) +} +``` + +### Pattern 2: Fire-and-Forget Notifications + +**Use Case:** Notify other nodes without waiting for response + +```rust +// Broadcast notification to multiple nodes +#[http] +async fn broadcast_event(&mut self, request_body: String) -> Result { + #[derive(Deserialize)] + struct BroadcastRequest { + event_type: String, + data: serde_json::Value, + } + + let req: BroadcastRequest = serde_json::from_str(&request_body)?; + + let notification = json!({ + "event": req.event_type, + "data": req.data, + "from": our().node, + "timestamp": chrono::Utc::now().to_rfc3339(), + }); + + let wrapper = json!({ + "HandleNotification": serde_json::to_string(¬ification).unwrap() + }); + + let mut sent = 0; + let mut failed = 0; + + // Send to all known nodes + for node in &self.connected_nodes { + let process_id = "skeleton-app:skeleton-app:skeleton.os".parse::()?; + let target = Address::new(node.clone(), process_id); + + // Fire and forget - still set timeout for reliability + match Request::new() + .target(target) + .body(serde_json::to_vec(&wrapper).unwrap()) + .expects_response(5) // Short timeout + .send() { + Ok(_) => sent += 1, + Err(e) => { + println!("Failed to notify {}: {:?}", node, e); + failed += 1; + } + } + } + + Ok(json!({ + "sent": sent, + "failed": failed + }).to_string()) +} + +// Receiving node +#[remote] +async fn handle_notification(&mut self, notification_json: String) -> Result { + let notification: serde_json::Value = serde_json::from_str(¬ification_json)?; + + // Process notification + self.notifications.push(notification); + + // Just acknowledge receipt + Ok("ACK".to_string()) +} +``` + +### Pattern 3: Distributed State Synchronization + +**Use Case:** Keep state synchronized across multiple nodes + +```rust +// State sync request +#[derive(Serialize, Deserialize)] +pub struct SyncRequest { + pub node_id: String, + pub state_hash: String, + pub last_update: String, +} + +#[derive(Serialize, Deserialize)] +pub struct SyncResponse { + pub updates: Vec, + pub full_sync_needed: bool, +} + +// Periodic sync with peers +impl AppState { + async fn sync_with_peer(&mut self, peer_node: String) -> Result<(), String> { + let process_id = "skeleton-app:skeleton-app:skeleton.os".parse::()?; + let target = Address::new(peer_node.clone(), process_id); + + // Send our state info + let sync_req = SyncRequest { + node_id: our().node.clone(), + state_hash: self.calculate_state_hash(), + last_update: self.last_update_time.clone(), + }; + + let wrapper = json!({ + "HandleSyncRequest": serde_json::to_string(&sync_req).unwrap() + }); + + let response = Request::new() + .target(target) + .body(serde_json::to_vec(&wrapper).unwrap()) + .expects_response(30) + .send_and_await_response(30)?; + + if let Ok(body) = response.body() { + let sync_resp: SyncResponse = serde_json::from_slice(&body)?; + + if sync_resp.full_sync_needed { + self.request_full_sync(peer_node).await?; + } else { + self.apply_updates(sync_resp.updates); + } + } + + Ok(()) + } +} + +#[remote] +async fn handle_sync_request(&mut self, request_json: String) -> Result { + let req: SyncRequest = serde_json::from_str(&request_json)?; + + // Check if we have newer data + let response = if req.state_hash != self.calculate_state_hash() { + SyncResponse { + updates: self.get_updates_since(&req.last_update), + full_sync_needed: self.updates_since(&req.last_update) > 100, + } + } else { + SyncResponse { + updates: vec![], + full_sync_needed: false, + } + }; + + Ok(serde_json::to_string(&response).unwrap()) +} +``` + +### Pattern 4: Collaborative Editing + +**Use Case:** Multiple nodes editing shared data + +```rust +// Operation-based CRDT pattern +#[derive(Serialize, Deserialize)] +pub enum Operation { + Insert { pos: usize, text: String, id: String }, + Delete { pos: usize, len: usize, id: String }, + Update { item_id: String, field: String, value: serde_json::Value }, +} + +#[derive(Default, Serialize, Deserialize)] +pub struct SharedDocument { + operations: Vec, + content: String, + version: u64, +} + +// Local edit creates operation +#[http] +async fn edit_document(&mut self, request_body: String) -> Result { + let op: Operation = serde_json::from_str(&request_body)?; + + // Apply locally + self.document.apply_operation(&op); + self.document.version += 1; + + // Broadcast to peers + self.broadcast_operation(op).await?; + + Ok("Applied".to_string()) +} + +// Broadcast operation to all peers +impl AppState { + async fn broadcast_operation(&self, op: Operation) -> Result<(), String> { + let wrapper = json!({ + "ApplyOperation": serde_json::to_string(&op).unwrap() + }); + + let process_id = "skeleton-app:skeleton-app:skeleton.os".parse::()?; + + for peer in &self.peers { + let target = Address::new(peer.clone(), process_id); + + // Best effort delivery + let _ = Request::new() + .target(target) + .body(serde_json::to_vec(&wrapper).unwrap()) + .expects_response(5) + .send(); + } + + Ok(()) + } +} + +// Receive operation from peer +#[remote] +async fn apply_operation(&mut self, op_json: String) -> Result { + let op: Operation = serde_json::from_str(&op_json)?; + + // Check if we've already seen this operation + if !self.document.has_operation(&op) { + self.document.apply_operation(&op); + self.document.version += 1; + + // Forward to other peers (gossip protocol) + self.broadcast_operation(op).await?; + } + + Ok("Applied".to_string()) +} +``` + +### Pattern 5: Node Authentication & Handshake + +**Use Case:** Authenticate nodes before allowing access to resources + +```rust +use hyperware_app_common::{send, source}; + +// Authentication request/response types +#[derive(Serialize, Deserialize)] +pub struct NodeHandshakeReq { + pub resource_id: String, +} + +#[derive(Serialize, Deserialize)] +pub struct NodeHandshakeResp { + pub auth_token: String, +} + +// Client initiates handshake +#[http(method = "POST")] +async fn start_handshake(&mut self, url: String) -> Result { + // Extract node from URL (e.g., "https://bob.os/app/resource/123") + let parts: Vec<&str> = url.split('/').collect(); + let host_node = parts.get(2) + .ok_or("Invalid URL format")? + .split(':').next() + .ok_or("No host found")?; + + // Extract resource ID + let resource_id = parts.last() + .ok_or("No resource ID in URL")? + .to_string(); + + // Build target address + let target = Address::new(host_node, ("app", "app", "publisher.os")); + + // Create handshake request + let handshake_req = NodeHandshakeReq { resource_id }; + + // Use typed send from hyperware_app_common + let body = json!({"NodeHandshake": handshake_req}); + let request = Request::to(&target).body(serde_json::to_vec(&body).unwrap()); + + match send::>(request).await { + Ok(Ok(resp)) => { + // Store token and redirect with auth + self.auth_tokens.insert(host_node.to_string(), resp.auth_token.clone()); + Ok(format!("{}?auth={}", url, resp.auth_token)) + } + Ok(Err(e)) => Err(format!("Handshake failed: {}", e)), + Err(e) => Err(format!("Request failed: {:?}", e)), + } +} + +// Server handles handshake - both local and remote calls +#[local] +#[remote] +async fn node_handshake(&mut self, req: NodeHandshakeReq) -> Result { + // Verify resource exists + if !self.resources.contains_key(&req.resource_id) { + return Err("Resource not found".to_string()); + } + + // Get caller identity using source() + let caller_node = source().node; + + // Generate unique auth token + let auth_token = generate_auth_token(); + + // Store token -> node mapping + self.node_auth.insert(auth_token.clone(), NodeAuth { + node_id: caller_node.clone(), + resource_id: req.resource_id, + granted_at: chrono::Utc::now().to_rfc3339(), + }); + + Ok(NodeHandshakeResp { auth_token }) +} + +// Verify token on subsequent requests +fn verify_auth(&self, token: &str) -> Result { + self.node_auth.get(token) + .cloned() + .ok_or_else(|| "Invalid auth token".to_string()) +} +``` + +### Pattern 6: Node Discovery & Presence + +**Use Case:** Find and track active nodes + +```rust +// Heartbeat/presence system +#[derive(Serialize, Deserialize)] +pub struct NodeInfo { + pub node_id: String, + pub app_version: String, + pub capabilities: Vec, + pub last_seen: String, +} + +// Announce presence to known nodes +impl AppState { + async fn announce_presence(&self) -> Result<(), String> { + let my_info = NodeInfo { + node_id: our().node.clone(), + app_version: env!("CARGO_PKG_VERSION").to_string(), + capabilities: vec!["sync".to_string(), "chat".to_string()], + last_seen: chrono::Utc::now().to_rfc3339(), + }; + + let wrapper = json!({ + "RegisterNode": serde_json::to_string(&my_info).unwrap() + }); + + let process_id = "skeleton-app:skeleton-app:skeleton.os".parse::()?; + + // Announce to bootstrap nodes + for bootstrap in &self.bootstrap_nodes { + let target = Address::new(bootstrap.clone(), process_id); + + match Request::new() + .target(target) + .body(serde_json::to_vec(&wrapper).unwrap()) + .expects_response(10) + .send_and_await_response(10) { + Ok(response) => { + // Bootstrap node returns list of other nodes + if let Ok(body) = response.body() { + let nodes: Vec = serde_json::from_slice(&body)?; + self.discovered_nodes.extend(nodes); + } + }, + Err(e) => println!("Bootstrap {} unreachable: {:?}", bootstrap, e), + } + } + + Ok(()) + } +} + +#[remote] +async fn register_node(&mut self, info_json: String) -> Result { + let info: NodeInfo = serde_json::from_str(&info_json)?; + + // Update our node registry + self.known_nodes.insert(info.node_id.clone(), info); + + // Return other known nodes + let other_nodes: Vec = self.known_nodes.values() + .filter(|n| n.node_id != info.node_id) + .cloned() + .collect(); + + Ok(serde_json::to_string(&other_nodes).unwrap()) +} +``` + +### Pattern 7: Distributed Transactions + +**Use Case:** Coordinate actions across multiple nodes + +```rust +// Two-phase commit pattern +#[derive(Serialize, Deserialize)] +pub enum TransactionPhase { + Prepare, + Commit, + Abort, +} + +#[derive(Serialize, Deserialize)] +pub struct Transaction { + pub id: String, + pub operation: String, + pub data: serde_json::Value, + pub participants: Vec, +} + +// Coordinator node initiates transaction +#[http] +async fn start_transaction(&mut self, request_body: String) -> Result { + let mut tx: Transaction = serde_json::from_str(&request_body)?; + tx.id = uuid::Uuid::new_v4().to_string(); + + // Phase 1: Prepare + let prepare_wrapper = json!({ + "PrepareTransaction": serde_json::to_string(&tx).unwrap() + }); + + let process_id = "skeleton-app:skeleton-app:skeleton.os".parse::()?; + let mut votes = HashMap::new(); + + for participant in &tx.participants { + let target = Address::new(participant.clone(), process_id); + + match Request::new() + .target(target) + .body(serde_json::to_vec(&prepare_wrapper).unwrap()) + .expects_response(10) + .send_and_await_response(10) { + Ok(response) => { + if let Ok(body) = response.body() { + let vote: bool = serde_json::from_slice(&body)?; + votes.insert(participant.clone(), vote); + } + }, + Err(_) => { + votes.insert(participant.clone(), false); + } + } + } + + // Phase 2: Commit or Abort + let all_voted_yes = votes.values().all(|&v| v); + let decision = if all_voted_yes { "Commit" } else { "Abort" }; + + let decision_wrapper = json!({ + decision: tx.id.clone() + }); + + // Notify all participants of decision + for participant in &tx.participants { + let target = Address::new(participant.clone(), process_id); + let _ = Request::new() + .target(target) + .body(serde_json::to_vec(&decision_wrapper).unwrap()) + .expects_response(5) + .send(); + } + + Ok(json!({ + "transaction_id": tx.id, + "decision": decision, + "votes": votes, + }).to_string()) +} + +// Participant node handlers +#[remote] +async fn prepare_transaction(&mut self, tx_json: String) -> Result { + let tx: Transaction = serde_json::from_str(&tx_json)?; + + // Check if we can commit + let can_commit = self.validate_transaction(&tx); + + if can_commit { + // Save to pending + self.pending_transactions.insert(tx.id.clone(), tx); + } + + Ok(can_commit) +} + +#[remote] +async fn commit(&mut self, tx_id: String) -> Result { + if let Some(tx) = self.pending_transactions.remove(&tx_id) { + self.apply_transaction(tx)?; + Ok("Committed".to_string()) + } else { + Err("Transaction not found".to_string()) + } +} + +#[remote] +async fn abort(&mut self, tx_id: String) -> Result { + self.pending_transactions.remove(&tx_id); + Ok("Aborted".to_string()) +} +``` + +## Error Handling & Resilience + +### Retry with Exponential Backoff +```rust +// Note: This pattern requires the "timer:distro:sys" capability! +async fn reliable_remote_call( + target: Address, + method: &str, + data: String, +) -> Result { + let wrapper = json!({ method: data }); + let body = serde_json::to_vec(&wrapper).unwrap(); + + for attempt in 0..3 { + if attempt > 0 { + // Exponential backoff: 100ms, 200ms, 400ms + let delay_ms = 100 * (1 << attempt); + timer::set_timer(delay_ms, None); + } + + match Request::new() + .target(target.clone()) + .body(body.clone()) + .expects_response(30) + .send_and_await_response(30) { + Ok(response) => { + if let Ok(body) = response.body() { + return Ok(String::from_utf8_lossy(&body).to_string()); + } + }, + Err(e) if attempt < 2 => { + println!("Attempt {} failed: {:?}, retrying...", attempt + 1, e); + continue; + }, + Err(e) => return Err(format!("Failed after 3 attempts: {:?}", e)), + } + } + + Err("Max retries exceeded".to_string()) +} +``` + +### Circuit Breaker Pattern +```rust +// Note: HashMap is used here for internal state only - not exposed via WIT +#[derive(Default)] +pub struct CircuitBreaker { + failures: HashMap, + last_failure: HashMap, + threshold: u32, + timeout_secs: u64, +} + +impl CircuitBreaker { + pub fn can_call(&self, node: &str) -> bool { + if let Some(&failures) = self.failures.get(node) { + if failures >= self.threshold { + if let Some(&last) = self.last_failure.get(node) { + return last.elapsed().as_secs() > self.timeout_secs; + } + } + } + true + } + + pub fn record_success(&mut self, node: &str) { + self.failures.remove(node); + self.last_failure.remove(node); + } + + pub fn record_failure(&mut self, node: &str) { + *self.failures.entry(node.to_string()).or_insert(0) += 1; + self.last_failure.insert(node.to_string(), std::time::Instant::now()); + } +} +``` + +## Best Practices + +### 1. Always Set Timeouts +```rust +// ✅ Good +.expects_response(30) +.send_and_await_response(30) + +// ❌ Bad - Can hang forever +.send() +``` + +### 2. Handle Network Partitions +```rust +// Track node availability +pub struct NodeTracker { + nodes: HashMap, +} + +pub struct NodeStatus { + last_successful_contact: String, + consecutive_failures: u32, + is_reachable: bool, +} +``` + +### 3. Use Idempotent Operations +```rust +// Include operation ID to prevent duplicates +#[derive(Serialize, Deserialize)] +pub struct Operation { + pub id: String, // Unique ID + pub action: Action, +} + +impl AppState { + fn apply_operation(&mut self, op: Operation) -> Result<(), String> { + // Check if already applied + if self.applied_operations.contains(&op.id) { + return Ok(()); // Idempotent + } + + // Apply operation + self.execute_action(op.action)?; + self.applied_operations.insert(op.id); + Ok(()) + } +} +``` + +### 4. Design for Eventual Consistency +```rust +// Use vector clocks or timestamps +#[derive(Serialize, Deserialize)] +pub struct VersionedData { + pub data: serde_json::Value, + pub version: VectorClock, + pub last_modified: String, +} + +// Resolve conflicts +impl VersionedData { + fn merge(self, other: Self) -> Self { + if self.version.happens_before(&other.version) { + other + } else if other.version.happens_before(&self.version) { + self + } else { + // Concurrent updates - need resolution strategy + self.resolve_conflict(other) + } + } +} +``` + +## Testing P2P Features + +### Local Testing Setup +```bash +# Terminal 1 +kit s --fake-node alice.os + +# Terminal 2 +kit s --fake-node bob.os + +# Terminal 3 (optional) +kit s --fake-node charlie.os +``` + +### Test Scenarios +1. **Basic connectivity** - Can nodes find each other? +2. **Data sync** - Do all nodes eventually see the same data? +3. **Partition tolerance** - What happens when a node goes offline? +4. **Conflict resolution** - How are concurrent updates handled? +5. **Performance** - How does latency affect the user experience? + +### Debug Output +```rust +// Add comprehensive logging +println!("[P2P] Sending {} to {}", method, target_node); +println!("[P2P] Response: {:?}", response); +println!("[P2P] State after sync: {:?}", self.state); +``` + +## Real-World P2P Patterns from samchat + +### Pattern 8: Group Membership Notifications + +**Use Case:** Notify all members when a group is created or modified + +```rust +// Create group and notify all members +#[http] +async fn create_group(&mut self, group_name: String, initial_members: Vec) -> Result { + let creator = self.my_node_id.clone() + .ok_or_else(|| "Creator node ID not initialized".to_string())?; + + // Ensure creator is included + let mut participants = initial_members; + if !participants.contains(&creator) { + participants.push(creator.clone()); + } + + let group_id = format!("group_{}", Uuid::new_v4()); + + // Create group locally + let conversation = Conversation { + id: group_id.clone(), + participants: participants.clone(), + is_group: true, + group_name: Some(group_name.clone()), + created_by: Some(creator.clone()), + // ... + }; + self.conversations.insert(group_id.clone(), conversation); + + // Notify all other members + let publisher = "hpn-testing-beta.os"; // Consistent across all nodes! + let target_process_id = format!("samchat:samchat:{}", publisher) + .parse::()?; + + for participant in &participants { + if participant != &creator { + let target_address = Address::new(participant.clone(), target_process_id.clone()); + let notification = GroupJoinNotification { + group_id: group_id.clone(), + group_name: group_name.clone(), + participants: participants.clone(), + created_by: creator.clone(), + }; + + let request_wrapper = json!({ "HandleGroupJoin": notification }); + + // Fire-and-forget but still set expects_response for reliability + let _ = Request::new() + .target(target_address) + .body(serde_json::to_vec(&request_wrapper).unwrap()) + .expects_response(30) + .send(); + } + } + + Ok(group_id) +} + +// Handle notification on receiving nodes +#[remote] +async fn handle_group_join(&mut self, notification: GroupJoinNotification) -> Result { + // Create the group conversation locally + let conversation = Conversation { + id: notification.group_id.clone(), + participants: notification.participants, + is_group: true, + group_name: Some(notification.group_name), + created_by: Some(notification.created_by), + // ... + }; + + self.conversations.insert(notification.group_id, conversation); + Ok(true) +} +``` + +### Pattern 9: Remote Data Retrieval with Local Caching + +**Use Case:** Fetch files or data from remote nodes with fallback + +```rust +// Try local first, then remote +#[http] +async fn download_file(&mut self, file_id: String, sender_node: String) -> Result, String> { + // Try local VFS first + let file_path = format!("/samchat:hpn-testing-beta.os/files/{}", file_id); + let vfs_address = Address::new(our().node.clone(), "vfs:distro:sys".parse::()?); + + let local_result = Request::new() + .target(vfs_address.clone()) + .body(json!({ "path": file_path, "action": "Read" })) + .expects_response(5) + .send_and_await_response(5); + + if let Ok(response) = local_result { + if let Some(blob) = response.blob() { + return Ok(blob.bytes); + } + } + + // Not found locally, fetch from remote + if sender_node != our().node { + let target = Address::new(sender_node, + "samchat:samchat:hpn-testing-beta.os".parse::()?); + + let remote_result = Request::new() + .target(target) + .body(json!({ "GetRemoteFile": file_id })) + .expects_response(30) + .send_and_await_response(30)?; + + // Parse nested Result from remote + let response_json: serde_json::Value = + serde_json::from_slice(&remote_result.body())?; + + if let Some(file_data) = response_json.get("Ok") { + let bytes: Vec = serde_json::from_value(file_data.clone())?; + + // Cache locally for future use + let _ = Request::new() + .target(vfs_address) + .body(json!({ "path": file_path, "action": "Write" })) + .blob(LazyLoadBlob::new(Some("file"), bytes.clone())) + .expects_response(5) + .send_and_await_response(5); + + return Ok(bytes); + } + } + + Err("File not found".to_string()) +} +``` + +### Pattern 10: Message Distribution to Multiple Recipients + +**Use Case:** Send messages to group members without blocking + +```rust +// Distribute message to all group members +async fn send_group_message(&mut self, group_id: String, content: String) -> Result { + let sender = self.my_node_id.clone() + .ok_or_else(|| "Node ID not initialized".to_string())?; + + let conversation = self.conversations.get(&group_id) + .ok_or_else(|| "Group not found".to_string())?; + + // Get all recipients except sender + let recipients: Vec = conversation.participants.iter() + .filter(|p| *p != &sender) + .cloned() + .collect(); + + let message = ChatMessage { + id: Uuid::new_v4().to_string(), + conversation_id: group_id, + sender, + recipients: Some(recipients.clone()), + content, + timestamp: Utc::now().to_rfc3339(), + // ... + }; + + // Save locally first + self.conversations.get_mut(&group_id).unwrap() + .messages.push(message.clone()); + + // Distribute to all recipients + let target_process_id = "samchat:samchat:hpn-testing-beta.os" + .parse::()?; + + for recipient in recipients { + let target = Address::new(recipient, target_process_id.clone()); + + // Fire-and-forget pattern but WITH expects_response + let _ = Request::new() + .target(target) + .body(json!({ "ReceiveMessage": message.clone() })) + .expects_response(30) // Still set timeout! + .send(); // Don't await response + } + + Ok(true) +} +``` + +### Key Patterns from samchat: + +1. **Consistent Publisher**: Always use the same publisher across all nodes + ```rust + let publisher = "hpn-testing-beta.os"; // Same for ALL nodes! + let process_id = format!("samchat:samchat:{}", publisher); + ``` + +2. **Fire-and-Forget WITH Timeout**: Even when not awaiting responses, set expects_response + ```rust + Request::new() + .expects_response(30) // Important for reliability + .send(); // Not awaiting + ``` + +3. **Node ID in State**: Store your node ID at initialization + ```rust + #[init] + async fn initialize(&mut self) { + self.my_node_id = Some(our().node.clone()); + } + ``` + +4. **Optional Fields for Flexibility**: Use Option for fields that vary by message type + ```rust + pub struct ChatMessage { + recipient: Option, // Direct messages + recipients: Option>, // Group messages + file_info: Option, // File attachments + reply_to: Option, // Replies + } + ``` + +## Remember + +1. **No central authority** - Design for peer equality +2. **Expect failures** - Networks are unreliable +3. **Plan for conflicts** - Concurrent updates will happen +4. **Test with multiple nodes** - Single node testing misses P2P issues +5. **Document protocols** - Other developers need to understand your P2P design +6. **Consistent naming** - Use the same publisher/process names across all nodes +7. **Always set timeouts** - Even for fire-and-forget patterns \ No newline at end of file diff --git a/src/new/templates/rust/ui/hyperapp-skeleton/resources/guides/05-UI-FRONTEND-GUIDE.md b/src/new/templates/rust/ui/hyperapp-skeleton/resources/guides/05-UI-FRONTEND-GUIDE.md new file mode 100644 index 00000000..c78443ae --- /dev/null +++ b/src/new/templates/rust/ui/hyperapp-skeleton/resources/guides/05-UI-FRONTEND-GUIDE.md @@ -0,0 +1,1553 @@ +# 💻 UI/Frontend Development Guide + +## Frontend Stack Overview + +- **React 18** - UI framework +- **TypeScript** - Type safety +- **Zustand** - State management +- **Vite** - Build tool +- **CSS Modules** or plain CSS - Styling + +## Critical Setup Requirements + +### 1. The `/our.js` Script (MANDATORY) + +```html + + + + + + + + + + My Hyperware App + + +
+ + + +``` + +### 2. Global Types Setup + +```typescript +// src/types/global.ts +declare global { + interface Window { + our?: { + node: string; // e.g., "alice.os" + process: string; // e.g., "myapp:myapp:publisher.os" + }; + } +} + +export const BASE_URL = ''; // Empty in production + +export const isHyperwareEnvironment = (): boolean => { + return typeof window !== 'undefined' && window.our !== undefined; +}; + +export const getNodeId = (): string | null => { + return window.our?.node || null; +}; +``` + +## API Communication Patterns + +### 1. Basic API Service + +```typescript +// src/utils/api.ts +import { BASE_URL } from '../types/global'; + +// IMPORTANT: Backend HTTP methods return String or Result +// Complex data is serialized as JSON strings that must be parsed on frontend + +// Generic API call function +export async function makeApiCall( + method: string, + data?: TRequest +): Promise { + const body = data !== undefined + ? { [method]: data } + : { [method]: "" }; // Empty string for no params + + const response = await fetch(`${BASE_URL}/api`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(body), + }); + + if (!response.ok) { + const error = await response.text(); + throw new Error(`API Error: ${response.status} - ${error}`); + } + + return response.json(); +} + +// Typed API methods +export const api = { + // No parameters - backend returns JSON string + async getStatus() { + const response = await makeApiCall('GetStatus', ""); + return JSON.parse(response) as StatusResponse; + }, + + // Single parameter - backend returns JSON string + async getItem(id: string) { + const response = await makeApiCall('GetItem', id); + return JSON.parse(response) as Item; + }, + + // Multiple parameters (as JSON object - common pattern) + async createItem(name: string, description: string) { + const response = await makeApiCall( + 'CreateItem', + JSON.stringify({ name, description }) + ); + return JSON.parse(response) as CreateResponse; + }, + + // Complex object (send as JSON string) + async updateSettings(settings: Settings) { + return makeApiCall( + 'UpdateSettings', + JSON.stringify(settings) + ); + }, +}; +``` + +### 2. Error Handling + +```typescript +// src/utils/errors.ts +export class ApiError extends Error { + constructor( + message: string, + public status?: number, + public details?: unknown + ) { + super(message); + this.name = 'ApiError'; + } +} + +export function getErrorMessage(error: unknown): string { + if (error instanceof ApiError) { + return error.message; + } + if (error instanceof Error) { + return error.message; + } + if (typeof error === 'string') { + return error; + } + return 'An unknown error occurred'; +} + +// Wrapper with error handling +export async function apiCallWithRetry( + apiCall: () => Promise, + maxRetries = 3 +): Promise { + let lastError: unknown; + + for (let i = 0; i < maxRetries; i++) { + try { + return await apiCall(); + } catch (error) { + lastError = error; + if (i < maxRetries - 1) { + // Exponential backoff + await new Promise(resolve => + setTimeout(resolve, Math.pow(2, i) * 1000) + ); + } + } + } + + throw lastError; +} +``` + +## State Management with Zustand + +### 1. Store Structure + +```typescript +// src/store/app.ts +import { create } from 'zustand'; +import { devtools, persist } from 'zustand/middleware'; +import { immer } from 'zustand/middleware/immer'; + +interface AppState { + // Connection + nodeId: string | null; + isConnected: boolean; + + // Data + items: Item[]; + currentItem: Item | null; + + // UI State + isLoading: boolean; + error: string | null; + + // Filters/Settings + filters: { + search: string; + category: string | null; + sortBy: 'name' | 'date' | 'priority'; + }; +} + +interface AppActions { + // Connection + initialize: () => void; + + // Data operations + fetchItems: () => Promise; + createItem: (data: CreateItemData) => Promise; + updateItem: (id: string, updates: Partial) => Promise; + deleteItem: (id: string) => Promise; + selectItem: (id: string | null) => void; + + // UI operations + setError: (error: string | null) => void; + clearError: () => void; + setFilter: (filter: Partial) => void; + + // P2P operations + syncWithNode: (nodeId: string) => Promise; +} + +export const useAppStore = create()( + devtools( + persist( + immer((set, get) => ({ + // Initial state + nodeId: null, + isConnected: false, + items: [], + currentItem: null, + isLoading: false, + error: null, + filters: { + search: '', + category: null, + sortBy: 'name', + }, + + // Actions + initialize: () => { + const nodeId = getNodeId(); + set(state => { + state.nodeId = nodeId; + state.isConnected = nodeId !== null; + }); + + if (nodeId) { + get().fetchItems(); + } + }, + + fetchItems: async () => { + set(state => { + state.isLoading = true; + state.error = null; + }); + + try { + const items = await api.getItems(); + set(state => { + state.items = items; + state.isLoading = false; + }); + } catch (error) { + set(state => { + state.error = getErrorMessage(error); + state.isLoading = false; + }); + } + }, + + createItem: async (data) => { + set(state => { state.isLoading = true; }); + + try { + const response = await api.createItem(data); + + // Optimistic update + const newItem: Item = { + id: response.id, + ...data, + createdAt: new Date().toISOString(), + }; + + set(state => { + state.items.push(newItem); + state.currentItem = newItem; + state.isLoading = false; + }); + + // Refresh to ensure consistency + await get().fetchItems(); + } catch (error) { + set(state => { + state.error = getErrorMessage(error); + state.isLoading = false; + }); + throw error; // Re-throw for form handling + } + }, + + // ... other actions + })), + { + name: 'app-storage', + partialize: (state) => ({ + // Only persist UI preferences, not data + filters: state.filters, + }), + } + ) + ) +); + +// Selector hooks +export const useItems = () => { + const { items, filters } = useAppStore(); + + return items.filter(item => { + if (filters.search && !item.name.toLowerCase().includes(filters.search.toLowerCase())) { + return false; + } + if (filters.category && item.category !== filters.category) { + return false; + } + return true; + }).sort((a, b) => { + switch (filters.sortBy) { + case 'name': + return a.name.localeCompare(b.name); + case 'date': + return b.createdAt.localeCompare(a.createdAt); + case 'priority': + return b.priority - a.priority; + } + }); +}; + +export const useCurrentItem = () => useAppStore(state => state.currentItem); +export const useIsLoading = () => useAppStore(state => state.isLoading); +export const useError = () => useAppStore(state => state.error); +``` + +### 2. React Components + +```typescript +// src/components/ItemList.tsx +import React, { useEffect } from 'react'; +import { useAppStore, useItems } from '../store/app'; +import { ErrorMessage } from './ErrorMessage'; +import { LoadingSpinner } from './LoadingSpinner'; + +export const ItemList: React.FC = () => { + const items = useItems(); + const { isLoading, error, selectItem, currentItem } = useAppStore(); + + if (error) return ; + if (isLoading && items.length === 0) return ; + + return ( +
+ {items.map(item => ( +
selectItem(item.id)} + > +

{item.name}

+

{item.description}

+ + {new Date(item.createdAt).toLocaleDateString()} + +
+ ))} + + {items.length === 0 && ( +
+

No items found

+ +
+ )} +
+ ); +}; +``` + +### 3. Forms with Validation + +```typescript +// src/components/CreateItemForm.tsx +import React, { useState } from 'react'; +import { useAppStore } from '../store/app'; + +interface FormData { + name: string; + description: string; + category: string; +} + +interface FormErrors { + name?: string; + description?: string; + category?: string; +} + +export const CreateItemForm: React.FC<{ onClose: () => void }> = ({ onClose }) => { + const { createItem, isLoading } = useAppStore(); + const [formData, setFormData] = useState({ + name: '', + description: '', + category: '', + }); + const [errors, setErrors] = useState({}); + const [submitError, setSubmitError] = useState(null); + + const validate = (): boolean => { + const newErrors: FormErrors = {}; + + if (!formData.name.trim()) { + newErrors.name = 'Name is required'; + } else if (formData.name.length < 3) { + newErrors.name = 'Name must be at least 3 characters'; + } + + if (!formData.description.trim()) { + newErrors.description = 'Description is required'; + } + + if (!formData.category) { + newErrors.category = 'Please select a category'; + } + + setErrors(newErrors); + return Object.keys(newErrors).length === 0; + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + + if (!validate()) return; + + setSubmitError(null); + + try { + await createItem(formData); + onClose(); + } catch (error) { + setSubmitError(getErrorMessage(error)); + } + }; + + const handleChange = (field: keyof FormData) => ( + e: React.ChangeEvent + ) => { + setFormData(prev => ({ ...prev, [field]: e.target.value })); + // Clear error when user types + if (errors[field]) { + setErrors(prev => ({ ...prev, [field]: undefined })); + } + }; + + return ( +
+

Create New Item

+ + {submitError && ( +
{submitError}
+ )} + +
+ + + {errors.name && {errors.name}} +
+ +
+ +